summaryrefslogtreecommitdiffstats
path: root/korundum
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit90825e2392b2d70e43c7a25b8a3752299a933894 (patch)
treee33aa27f02b74604afbfd0ea4f1cfca8833d882a /korundum
downloadtdebindings-90825e2392b2d70e43c7a25b8a3752299a933894.tar.gz
tdebindings-90825e2392b2d70e43c7a25b8a3752299a933894.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebindings@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'korundum')
-rw-r--r--korundum/AUTHORS30
-rw-r--r--korundum/ChangeLog630
-rw-r--r--korundum/Makefile.am1
-rw-r--r--korundum/README184
-rw-r--r--korundum/TODO0
-rw-r--r--korundum/bin/Makefile.am13
-rw-r--r--korundum/bin/krubyinit.cpp29
-rw-r--r--korundum/rubylib/Makefile.am1
-rwxr-xr-xkorundum/rubylib/examples/RubberDoc.rb1265
-rw-r--r--korundum/rubylib/examples/RubberDoc.rc35
-rwxr-xr-xkorundum/rubylib/examples/dcop/dcopcall.rb37
-rwxr-xr-xkorundum/rubylib/examples/dcop/dcoppredicate.rb41
-rwxr-xr-xkorundum/rubylib/examples/dcop/dcopsend.rb35
-rwxr-xr-xkorundum/rubylib/examples/dcop/dcopsignal.rb26
-rwxr-xr-xkorundum/rubylib/examples/dcop/dcopslot.rb88
-rwxr-xr-xkorundum/rubylib/examples/dcop/dcoptest.rb129
-rwxr-xr-xkorundum/rubylib/examples/dcop/petshop.rb91
-rw-r--r--korundum/rubylib/examples/kludgeror.rb138
-rw-r--r--korundum/rubylib/examples/kurldemo.rb110
-rw-r--r--korundum/rubylib/examples/menudemo.rb310
-rw-r--r--korundum/rubylib/examples/mimetype.rb286
-rw-r--r--korundum/rubylib/examples/rbKHTMLPart.rb217
-rw-r--r--korundum/rubylib/examples/rbtestimage.pngbin0 -> 36928 bytes
-rw-r--r--korundum/rubylib/examples/systray.rb66
-rw-r--r--korundum/rubylib/examples/uikmdi.rb187
-rw-r--r--korundum/rubylib/examples/uikmdi.rc11
-rw-r--r--korundum/rubylib/examples/uimodules/uidialogs.rb256
-rw-r--r--korundum/rubylib/examples/uimodules/uimenus.rb137
-rw-r--r--korundum/rubylib/examples/uimodules/uimisc.rb273
-rw-r--r--korundum/rubylib/examples/uimodules/uiwidgets.rb827
-rw-r--r--korundum/rubylib/examples/uimodules/uixml.rb56
-rw-r--r--korundum/rubylib/examples/uisampler.rb238
-rwxr-xr-xkorundum/rubylib/examples/xmlgui.rb42
-rw-r--r--korundum/rubylib/examples/xmlgui.rc18
-rw-r--r--korundum/rubylib/examples/xmlmenudemo.rb314
-rw-r--r--korundum/rubylib/examples/xmlmenudemoui.rc49
-rw-r--r--korundum/rubylib/korundum/Korundum.cpp1183
-rw-r--r--korundum/rubylib/korundum/Makefile.am10
-rw-r--r--korundum/rubylib/korundum/configure.in.in15
-rw-r--r--korundum/rubylib/korundum/kdehandlers.cpp1428
-rw-r--r--korundum/rubylib/korundum/lib/KDE/Korundum.rb1
-rw-r--r--korundum/rubylib/korundum/lib/KDE/Makefile.am5
-rw-r--r--korundum/rubylib/korundum/lib/KDE/korundum.rb1391
-rw-r--r--korundum/rubylib/korundum/lib/Makefile.am1
-rw-r--r--korundum/rubylib/rbkconfig_compiler/Makefile.am28
-rw-r--r--korundum/rubylib/rbkconfig_compiler/README.dox251
-rw-r--r--korundum/rubylib/rbkconfig_compiler/TODO1
-rw-r--r--korundum/rubylib/rbkconfig_compiler/autoexample.rb49
-rwxr-xr-xkorundum/rubylib/rbkconfig_compiler/checkkcfg.pl83
-rw-r--r--korundum/rubylib/rbkconfig_compiler/example.kcfg55
-rw-r--r--korundum/rubylib/rbkconfig_compiler/example.rb40
-rw-r--r--korundum/rubylib/rbkconfig_compiler/exampleprefs_base.kcfgc18
-rw-r--r--korundum/rubylib/rbkconfig_compiler/general_base.ui46
-rw-r--r--korundum/rubylib/rbkconfig_compiler/kcfg.xsd191
-rw-r--r--korundum/rubylib/rbkconfig_compiler/myoptions_base.ui35
-rw-r--r--korundum/rubylib/rbkconfig_compiler/rbkconfig_compiler.cpp1330
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/Makefile.am40
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/myprefs.rb5
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test1.kcfg55
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test1.kcfgc18
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test1main.rb4
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test2.kcfg78
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test2.kcfgc11
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test2main.rb5
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test3.kcfg26
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test3.kcfgc12
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test3main.rb4
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test4.kcfg42
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test4.kcfgc11
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test4main.rb4
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test5.kcfg42
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test5.kcfgc11
-rw-r--r--korundum/rubylib/rbkconfig_compiler/tests/test5main.rb4
-rw-r--r--korundum/rubylib/templates/annotated/basicapp.rb106
-rw-r--r--korundum/rubylib/templates/annotated/menuapp1.rb278
-rw-r--r--korundum/rubylib/templates/annotated/menuapp2.rb260
-rw-r--r--korundum/rubylib/templates/annotated/menuapp3.rb221
-rw-r--r--korundum/rubylib/templates/annotated/menuapp3ui.rc24
-rw-r--r--korundum/rubylib/templates/annotated/minimal.rb80
-rw-r--r--korundum/rubylib/templates/annotated/systray1.rb94
-rw-r--r--korundum/rubylib/templates/basic/basicapp.rb61
-rw-r--r--korundum/rubylib/templates/basic/menuapp1.rb213
-rw-r--r--korundum/rubylib/templates/basic/menuapp2.rb216
-rw-r--r--korundum/rubylib/templates/basic/menuapp3.rb174
-rw-r--r--korundum/rubylib/templates/basic/menuapp3ui.rc24
-rw-r--r--korundum/rubylib/templates/basic/minimal.rb56
-rw-r--r--korundum/rubylib/templates/basic/systray1.rb75
-rw-r--r--korundum/rubylib/tutorials/p1/p1.rb13
-rw-r--r--korundum/rubylib/tutorials/p2/p2.rb12
-rw-r--r--korundum/rubylib/tutorials/p3/p3.rb61
-rw-r--r--korundum/rubylib/tutorials/p4/p4.rb67
-rw-r--r--korundum/rubylib/tutorials/p5/p5.rb82
-rw-r--r--korundum/rubylib/tutorials/p6/addurl.sh3
-rw-r--r--korundum/rubylib/tutorials/p6/p6.rb26
-rw-r--r--korundum/rubylib/tutorials/p7/p7.rb127
-rw-r--r--korundum/rubylib/tutorials/p8/p8.rb39
-rw-r--r--korundum/rubylib/tutorials/p9/p9.rb110
-rw-r--r--korundum/rubylib/tutorials/p9/p9ui.rc14
98 files changed, 15139 insertions, 0 deletions
diff --git a/korundum/AUTHORS b/korundum/AUTHORS
new file mode 100644
index 00000000..0756dc66
--- /dev/null
+++ b/korundum/AUTHORS
@@ -0,0 +1,30 @@
+/***************************************************************************
+ * (C) 2003 Richard Dale All rights reserved. *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+Chief Wreck On The Highway
+ Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+Bug fixes, enhancements, sample code
+ Alex Kellett
+
+QtRuby is a ruby version of the PerlQt/Smoke project, written by:
+ Ashley Winters
+ Germain Garand
+ David Faure
+
+Equipment
+ 800 Mhz iBook with Yellow Dog 3.0, Macally Micro 3 button mouse
+
+Books
+ 'Programming with Qt' by Mathias Kalle Dalheimer
+ 'Programming Ruby' by David Thomas and Andrew Hunt
+ 'The Ruby Way' by Hal Fulton
+ 'Ruby In a Nutshell' by Yukihiro Matsumoto
+ 'Advanced Perl Programming' by Sriram Srinivasan
diff --git a/korundum/ChangeLog b/korundum/ChangeLog
new file mode 100644
index 00000000..0d904be8
--- /dev/null
+++ b/korundum/ChangeLog
@@ -0,0 +1,630 @@
+2007-03-05 Richard Dale <rdale@foton.es>
+
+ * Added a marshaller for QValueList<WId>& as requested by volty on #qtruby
+
+2007-07-06 Richard Dale <rdale@foton.es>
+
+ * Fixed bug in DCOPRef's reported by Han Holl, but how has it ever worked?
+
+2007-02-19 Richard Dale <rdale@foton.es>
+
+ * Fixed a bug where the sort method of KDE::ListView and KDE::ListViewItem
+ was no longer working, as the classes are 'Enumerable' and ruby was
+ calling the ruby sort method instead. Thanks to kelko for reporting it
+ on #kde-ruby.
+
+2006-11-21 Richard Dale <rdale@foton.es>
+
+ * Made KDE::ListView, KDE::ListViewItem Enumerable with implementations
+ of each() so they don't need to use the Qt External iterators like
+ Qt::ListViewItemIterator anymore. For instance:
+
+ lv = KDE::ListView.new do
+ ["one", "two", "three", "four"].each do |label|
+ KDE::ListViewItem.new(self, label, "zzz")
+ end
+ end
+
+ lv.each do |item|
+ p item.inspect
+ pp item.inspect
+ end
+
+ * Add inspect() and pretty_print() methods to KDE::ListViewItem so that
+ they show the text of their columns
+
+2006-10-22 Richard Dale <rdale@foton.es>
+
+ * Special case QValueList<int> as a DCOPRef return type. Fixes problem
+ reported by Brian Bart.
+
+2006-08-18 Richard Dale <rdale@foton.es>
+
+ * Added a KActionPtrList marshaller. Fixes problem reported by
+ eskatos on the #qtruby irc channel.
+
+2006-06-05 Richard Dale <rdale@foton.es>
+
+ * The metaObject methods for slots and signals are no longer added when
+ a Qt::Object is constructed, but when slots or signals are added to
+ a class. This means that signals as well as slots can be added to an
+ existing instance.
+
+2006-05-16 Richard Dale <rdale@foton.es>
+
+ * Fixed regression causing KDE::UniqueApplication.exec to not work
+
+ * Removed the konsole_part_metaobject() C function as it isn't
+ needed anymore
+
+2006-03-29 Richard Dale <rdale@foton.es>
+
+ * Added a KDE::KonsolePart class for when a konsolePart KPart is
+ dynamically loaded. It adds the five methods from the ExtTerminalInterface
+ to the KParts::ReadOnlyPart for interacting with the konsolePart.
+
+ * Example usage:
+
+ factory = KDE::LibLoader.self().factory("libkonsolepart")
+ if ! factory.nil?
+ @konsole = factory.create(self)
+ end
+
+ @konsole.autoStartShell = true
+ @konsole.startProgram("/bin/echo", ["echo", "-n"])
+ @konsole.showShellInDir( Qt::Dir.home.path )
+ @konsole.sendInput( "puts 'hello there konsole'" )
+
+ * Fixes problem reported by Ranjan Ghosh
+
+2006-03-21 Richard Dale <rdale@foton.es>
+
+ * Added various explicit calls to method_missing() for methods which
+ are defined in Kernel and Object, such as 'exec', 'select', 'format'
+ etc. Otherwise, the corresponding methods in the Smoke library were
+ not being invoked correctly.
+
+2006-02-08 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * When KDE::CmdLineArgs.init() was called with just a single
+ KDE::AboutData arg, it crashed. Fixes problem reported by
+ Han Holl.
+
+ * KDE::CmdLineArgs and KDE::AboutData instances are no longer
+ deleted by qtruby on garbage collection. Fixes another problem
+ reported by Han Holl.
+
+2005-12-08 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * A marshaller was defined for 'KFileItemList' as a value type, but not for
+ a 'KFileItemList*' pointer type. Fixes problem reported by Diego 'Flameeyes'
+ Pettenò
+
+2005-10-05 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Changed DCOP code now that Qt::ByteArray class is in the Smoke library
+ * Fixed some examples derived from PyKDE with 0 or 1 passed as a
+ boolean instead of true or false for Ruby. A bug in the overloaded
+ method resolution meant it worked when it shouldn't have.
+
+2005-09-26 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Removed get and set methods for accessing fields on the structs
+ KIO::UDSAtom and KDE::ConfigSkeleton::MenuItem::Choice as
+ they aren't needed any more now that accessor methods are
+ generated in the Smoke library.
+
+2005-06-08 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * DCOP signals were failing with a 'undefined method `fullSignalName'' error
+ * Fixes problem reported by Chris Gow
+
+2005-05-29 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * At the moment require 'Qt' and require 'Korundum' statements can't appear
+ in the same ruby program. Suitable fatal error messages are now displayed
+ to indicate the cause of the problem. Fixes bug reported by Caleb Tennis
+ and Dave M
+
+2005-05-21 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * KDE::DCOPRef.methods now returns remote DCOP methods as well as the local methods in
+ the DCOPRef. So now irb tab completion works with dynamically discovered DCOP methods,
+ in a DCOPRef.
+
+2005-04-03 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added some #ifdefs so the bindings build with KDE 3.1.x
+ * Fixed problem with rbkconfig_compile Makefile.am
+
+2005-03-30 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Fixed problems caused ''include Qt'' and "include KDE" statements in korundum.rb where a
+ couple of methods were being added to class Module was causing all the Qt and KDE methods
+ to be added to Module.
+
+2005-02-01 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added marshallers for KIO::UDSEntry and KIO::UDSEntryList, and accessor methods for
+ fields in the KIO::UDSAtom struct. Fixes problem reported by Ian Monroe.
+
+2005-01-27 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added some fixes for the rbkconfig_compiler code generation and
+ example code.
+ * The method 'isImmutable' is added to KDE::ConfigSkeletonItems
+ as a special case - it's missing from the Smoke runtime as it's
+ from a template based superclass.
+
+2005-01-26 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Translated the rbkconfig_compiler examples from C++ to ruby,
+ and improved the build rules in the Makefile.ams
+
+2005-01-20 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * The rbkconfig_compiler now uses Qt::Variants to hold the values in KDE::ConfigSkeleton
+ instance variables.
+ * The values of the KDE::ConfigSkeletonItems are then set as properties with the Qt::Variants.
+ It wasn't possible to handle references to primitive types such as 'int&' via ruby, so properties are
+ a more 'scripting language' oriented approach.
+ * The embedded code in the .kcfg examples was converted from C++ to ruby
+
+2005-01-20 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Tidied up the rbkconfig_compiler code
+ * Added marshaller for KConfigSkeleton::ItemEnum::Choice lists to and from ruby Arrays,
+ and accessor methods for the Item::Enum::Choice struct.
+
+2005-01-18 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added rbkconfig_compiler for compiling .kcfg files to ruby
+
+2004-12-29 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added inspect() and pretty_print() methods for KDE::AboutPerson and KDE::AboutTranslator,
+ along with some more fields in the KDE::AboutData inspector
+
+2004-12-15 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * The DCOPObject inspect method was crashing if the instance hadn't been fully
+ constructed
+ * The kde_resolve_classname function's arg types were changed to match the new
+ ones in the resolve_classname() function of QtRuby/handlers.cpp.
+
+2004-12-11 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * DCOPObject inspect() and pretty_print() methods added
+
+2004-12-09 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * More inspect() and pretty_print() methods for common classes to improve debugging -
+ KDE::DCOPRef, KDE::Service, KDE::URL, KDE::AboutData.
+
+2004-10-30 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * References to Qt.qWarning() changed to qWarning()
+
+2004-10-24 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Fixed crashes in the KURL::List marshalling. A copy is now made of each KURL item
+ in the list when being marshalled to a ruby Array. When a KURL::List is deleted the
+ contents are all deleted too as it's a QValueList. Hence, the need to make copies.
+
+2004-10-20 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * The RESTORE() method is no longer an KDE::Mainwindow method, but a globally available
+ Object method
+
+2004-10-20 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added I18N_NOOP() and I18N_NOOP2() methods
+
+2004-10-11 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Set global flag 'application_terminated' when KDE::Application or KDE::UniqueApplication
+ has returned from exec(). Once this is set the QtRuby runtime will no longer delete any
+ C++ instances. This will hopefully fix crash on application exit problems reported by Thibauld
+ Favre.
+
+CCMAIL: kde-bindings@kde.org
+
+2004-10-08 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Reverted recent fix for crash on exit, as it only occured with a Qt::Application and
+ seems to introduce a crash in KDE apps where none existed before.
+
+ CCMAIL: kde-bindings@kde.org
+ CCMAIL: thibauld.favre@laposte.net
+
+2004-10-06 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * When a Korundum application exits, the top level widgets are now destroyed
+ as well as the KDE::Application itself. This fixes a problem where the ruby garbage
+ collection frees instances in an arbitrary order afer the program has exited, and
+ destroys a Hash containing QMetaData info needed for tidying up.
+
+2004-10-04 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * When a ruby app exits, rb_gc_call_finalizer_at_exit() is called and all the ruby
+ instances are garbage collected. The problem is that this is done in an arbitrary
+ order, and KDE::Application was occasionally crashing in its destructor because
+ QMetaObject info it still needed was being deleted before then.
+
+ * Fixes problem reported by Thibauld Favre
+
+ CCMAIL: <tfavre@mandrakesoft.com>
+
+2004-10-03 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Removed warning about '*' being used as an argument prefix
+
+2004-09-30 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added some rtti tests for DOM::Node to instantiate a more accurate ruby class
+
+2004-09-30 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * The resolve_classname() function in qtruby handlers.cpp uses the various Qt rtti mechanisms to
+ get a more accurate classname to instantiate as a ruby instance. It has now been extended
+ with a callback to the Korundum library to do the same for KDE classes.
+
+ * This fixes a problem reported by Zack Rusin where a KArchiveEntry returned to ruby was not being
+ correctly constructed as either a KArchiveDirectory or KArchiveFile according to
+ the KArchiveEntry::isDirectory() method
+
+ CCMAIL: zack@kde.org
+
+
+2004-09-18 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added marshallers for KPluginInfo::List and QPtrList<KParts::Plugin>
+
+2004-09-16 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * The KDE::UniqueApplication constructor now sets up the $kapp global variable
+
+2004-09-16 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added $kapp global variable, example usage:
+
+ config = $kapp.config()
+
+2004-08-29 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added Kontact module to provide a namespace for the kontact plugin api
+
+2004-08-25 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Underscore naming for can be used for DCOP method names instead of camel case if
+ preferred. Any underscores in method names are removed, and the following
+ character is capitalised. For example, either of these two forms can be used
+ to call the same dcop function:
+
+ process_can_be_reused(1234)
+
+ processCanBeReused(1234)
+
+2004-08-24 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * The form 'foo?' can be used as a synonym for isFoo() or hasFoo() dcop methods.
+ * Instead of:
+ result = dcopRef.isFoo()
+ * Use this more rubyish form:
+ result = dcopRef.foo?
+ if result.nil?
+ puts "DCOP predicate failed"
+ else
+ puts "foo? is #{result}"
+ end
+
+
+2004-08-16 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * The 'qWarning()' calls in korundum.rb needed to be prefixed with the 'Qt.'' module
+ otherwise a missing dcop call causes an infinite loop.
+
+2004-08-14 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added KServiceGroup::List to ruby array marshaller
+
+2004-08-03 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Fixed regression bug in emitting dcop signals
+
+2004-08-03 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added a KMountPoint::List marshaller
+
+2004-07-30 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Removed the various Q_INT32 etc types from the Smoke stack <--> QDataStream
+ marshalling. This was because the code generated by the dcopidl2cpp tool
+ doesn't have them. So if a machine has native 64 bit ints, then that width
+ will be used rather than Q_INT32.
+
+2004-07-28 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added a couple of template methods for marshalling QValueLists and QMaps.
+ * Included a quite a few new marshaller functions for QPtrLists, as well as
+ the two types above.
+
+2004-07-28 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Fixed crash in marshalling KMimeTypes and KServiceGroups to ruby values
+
+2004-07-27 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Replaced QString casts to 'const char *' with latin1() calls
+
+2004-07-27 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added error messages for invalid dcop slot or signal declarations
+
+2004-07-27 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * DCOP error messages now go via qWarning() rather than puts()
+
+2004-07-26 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added QMap<QCString,DCOPRef> marshalling to and from Smoke as well as dcop
+
+2004-07-24 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * DCOP reply types can now contain colons
+ * Added KURL::List to ruby Array marshalling, fixed crash when
+ marshalling from a ruby Array to a KURL::List
+ * Add KURL::List ruby <--> dcop marshalling
+
+2004-07-24 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added QMap<QString,DCOPRef> ruby <--> dcop marshalling
+
+2004-07-23 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Tidied up the dcop meta object code a bit
+
+2004-07-23 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * If a ruby class with 'k_dcop' declarations isn't a subclass of DCOPObject,
+ only one instance of a DCOPObject is created no matter how many instances
+ are instantiated.
+
+2004-07-23 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Tidied code - removed unnecessary action_map_to_list helper method
+
+2004-07-21 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * QDataStream temporary variables added for the Q_INT32 etc types when
+ writing to a Smoke stack from a QDataStream.
+
+2004-07-21 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added casts to the various macros like 'Q_INT32' when writing a Smoke
+ stack to a QDataStream
+
+2004-07-21 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added QValueList<QCString> marshalling ruby <--> dcop
+
+2004-07-21 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Ruby dcop slots can now return actionMaps and windowLists as
+ 'QMap<QString,DCOPRef>' and 'QValueList<DCOPRef>' types
+
+2004-07-20 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added missing 'QMap<QString,DCOPRef>' dcop reply marshalling
+ * The recently added dcop reply type 'QValueList<DCOPRef>' now works
+ * The parsing of a dcop function type signature to add it to the cache
+ was wrong if the reply type contained angle brackets or commas
+
+2004-07-19 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added dynamic ruby to C++ argument type resolution in DCOPRef calls.
+ When a call of the form 'dcopRef.getPoint(5, "foobar")' is made, the C++
+ type signature is obtained from the list of those returned by
+ DCOPRef.functions(). If the function name is overloaded, the ruby arg
+ types are used to pick the correct call.
+
+2004-07-18 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Made 'parrot.age = 7' a synonym for 'parrot.setAge(7)' with dcop refs
+
+2004-07-17 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * More missing DCOP marshallers - QStringList and QCStringList
+ * A class with a 'k_dcop' slots declaration can now be an instance
+ of DCOPObject
+ * Converted the 'petshop' DCOP server example from pykde python
+
+2004-07-16 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added missing QCString DCOP marshalling
+
+2004-07-16 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Removed the recently added QValueList<DCOPRef> marshaller as no '<<'
+ or '<<' QDataStream marshallers are in the Smoke runtime
+ * Added missing primitive type marshalling to and from a DCOP QByteArray
+
+2004-07-15 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Fixed completely non-working DCOP call reply marshalling. An instance wasn't
+ being constructed to read the QByteArray containing the reply via a QDataStream.
+
+2004-07-15 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added QValueList<DCOPRef> marshalling
+
+2004-07-14 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Converted various example app templates from pykde to ruby Korundum
+
+2004-07-13 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * A DCOP send() now correctly returns true or false according to success
+ * DCOP call()s with void or ASYNC return types return true on success,
+ or nil on failure
+
+2004-07-13 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Improved the KSharePtr item marshalling so that a copy of the item
+ is constructed with no accompanying smart pointer. The new item
+ can be owned by ruby without needing to special case deref'ing
+ the pointer on destruction. Apart from KService's don't have a
+ public copy constructor, where the ref count is incremented to
+ prevent their destruction.
+
+2004-07-12 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * The full C++ type signature is no longer needed in DCOP calls:
+
+ dcopRef = KDE::DCOPRef.new("dcopslot", "MyWidget")
+
+ There are three different ways to specify the call:
+ 1) res = dcopRef.call("getPoint(QString)", "Hello from dcopsend")
+ 2) res = dcopRef.call("getPoint", "Hello from dcopsend")
+ 3) res = dcopRef.getPoint("Hello from dcopsend")
+
+ puts "result class: #{res.class.name} x: #{res.x} y: #{res.y}"
+
+ * Send to a DCOPRef is similar:
+ 1) dcopRef.send("mySlot(QString)", "Hello from dcopsend")
+ 2) dcopRef.send("mySlot", "Hello from dcopsend")
+
+ * If the type signature of the target dcop slot is ommited it is derived
+ from the ruby argument types:
+
+ String => QString
+ Float => double
+ Integer => int
+ Qt::Widget etc => QWidget
+ KDE::URL etc => KURL
+ [] => QStringList
+
+2004-07-08 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Reverted fix for QChar args being passed as ruby strings after
+ discussion with Germain Garand. A QChar arg is now passed like this:
+
+ cs = KDE::CharSelect.new(self, "chselect", nil, Qt::Char.new(0), 0)
+
+ This will no longer work for now:
+
+ cs = KDE::CharSelect.new(self, "chselect", nil, ' ', 0)
+
+2004-07-07 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Translated the excellent pykde 'UISampler' app to ruby
+ * Added KAction list marshalling
+ * KDE::MainWindow.RESTORE() and kRestoreMainWindows() methods added.
+
+2004-07-06 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added more translated pykde examples
+ * The type signatures of dcop signals and slots are now normalized and unwanted
+ white space is removed
+
+2004-07-02 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Translated some pykde example programs from python to ruby
+ * Added various marshallers for the KSharedPtr related methods/classes
+
+2004-07-02 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Replaced obsolete STR2CSTR() calls with StringValuePtr()
+
+2004-07-01 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * DCOP Signals now work, they are defined like this:
+
+ k_dcop_signals 'void testEmitSignal(QString)'
+
+ def doit()
+ puts "In doit.."
+ emit testEmitSignal("Hello DCOP Slot")
+ end
+
+ * Connect slot 'mySlot' to a DCOP signal like this:
+
+ res = slottest.connectDCOPSignal("dcopsignal", "SenderWidget",
+ "testEmitSignal(QString)", "mySlot(QString)",
+ true)
+
+2004-06-30 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added DCOPRef.call() and send() support.
+ * Define a dcop slot like this in one ruby program:
+
+ k_dcop 'QPoint getPoint(QString)'
+
+ def getPoint(msg)
+ puts "message: #{msg}"
+ return Qt::Point.new(50, 100)
+ end
+
+ * Call it from another program and print the reply, like this:
+
+ dcopRef = KDE::DCOPRef.new("dcopslot", "MyWidget")
+ res = dcopRef.call("QPoint getPoint(QString)", "Hello from dcopsend")
+ puts "result class: #{res.class.name} x: #{res.x} y: #{res.y}"
+
+ * Send to a DCOPRef is similar:
+
+ dcopRef = KDE::DCOPRef.new("dcopslot", "MyWidget")
+ dcopRef.send("mySlot(QString)", "Hello from dcopsend")
+
+ * Note that the full type signature of the target dcop slot must be
+ specified at present.
+
+2004-03-10 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Added marshaller for KTrader::OfferList to ruby array
+ * Used DOM::Node rtti to instantiate a ruby value with the correct subclass
+
+2004-03-03 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * If the DCOP reply type is 'void' or 'ASYNC', it isn't marshalled into the
+ QByteArray 'replyData' arg of DCOPObject::process().
+
+2004-03-02 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Slots and signals couldn't be added to KDE classes, such as KDE::PushButton
+
+2004-03-02 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * A DCOPClient instance is now created for classes with a 'k_dcop_signals'
+ declaration, and emitDCOPSignal() is called on that.
+
+2004-03-01 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Ruby DCOP support now working - here is some example code:
+
+ require 'Korundum'
+ class MyWidget < KDE::PushButton
+ k_dcop 'QPoint mySlot(int,QString)'
+
+ def initialize(parent, name)
+ super
+ end
+
+ def mySlot(counter,greeting)
+ return Qt::Point.new(50, 100)
+ end
+ end
+
+ - This slot is passed an integer and a string, and returns a Qt::Point.
+ - Note that the class doesn't have to inherit from DCOPObject. If you
+ include a 'k_dcop' slots declaration a 'listener' dcop object instance
+ is created automatically.
+
+
+2004-01-08 Alexander Kellett <lypanov@kde.org>
+ * Imported krubyinit sources, thus at last fixing the startup segv's with gentoo/x86/qt 3.2.
+
+2003-12-02 Richard Dale <Richard_Dale@tipitina.demon.co.uk>
+
+ * Korundum - a Ruby SMOKE adaptor for KDE, initial checkin (proxy commit from lypanov)
+
diff --git a/korundum/Makefile.am b/korundum/Makefile.am
new file mode 100644
index 00000000..33a55071
--- /dev/null
+++ b/korundum/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = rubylib bin
diff --git a/korundum/README b/korundum/README
new file mode 100644
index 00000000..cb283bd8
--- /dev/null
+++ b/korundum/README
@@ -0,0 +1,184 @@
+Please see kdebindings/qtruby/README
+
+KDE Specific Infomation:
+
+ - Instead of require 'Qt', use require 'Korundum' for KDE programs.
+
+ - The KDE K* classes such as KApplication are renamed as KDE::Application.
+ The other KDE classes are in the KParts::, KIO:: or DOM:: namespaces,
+ with the same names as their C++ counterparts.
+
+ - Use the 'rbkdeapi' script to introspect the Korundum api from the command
+ line. For example:
+
+ $ rbkdeapi KDE::Action
+
+ Will list all the methods in the KDE::Action class. There are currently
+ (as at KDE 3.3 beta 2) 977 classes/30841 methods in the Smoke library
+ runtime, so the coverage of the Qt/KDE api is pretty complete.
+
+ - DCOP Support. Here is a minimal ruby dcop slot implementation:
+
+ require 'Korundum'
+
+ class MyWidget < KDE::PushButton
+ k_dcop 'QPoint mySlot(int,QString)'
+
+ def initialize(parent, name)
+ super
+ end
+
+ def mySlot(counter,greeting)
+ return Qt::Point.new(50, 100)
+ end
+ end
+
+ This slot is passed an integer and a string, and returns a Qt::Point.
+
+ Note that the class doesn't have to inherit from DCOPObject. If you
+ include a 'k_dcop' slots declaration a 'listener' dcop object
+ instance is created automatically, and these four methods are added
+ to your class:
+
+ interfaces()
+ functions()
+ connectDCOPSignal()
+ disconnectDCOPSignal()
+
+ The name of the object is always the ruby classname, and you can only
+ instantiate one instance for each ruby class that has 'k_dcop'
+ declarations. See examples/dcop/dcopslot.rb and dcopsignal.rb for an
+ example of the simplest approach.
+
+ If you wish to use the full functionality of a DCOPObject, you can
+ subclass it and call all the methods, not just the four above.
+ Additionally, you can instantiate more than one instance per class and
+ rename the dcop object with the setObjId() method or by passing the name
+ to the constructor. See the examples/dcop/petshop.rb code for an
+ example of a more complex dcop object.
+
+ - Define a dcop slot like this in one ruby program:
+
+ k_dcop 'QPoint getPoint(QString)'
+
+ def getPoint(msg)
+ puts "message: #{msg}"
+ return Qt::Point.new(50, 100)
+ end
+
+ - Call it from another program and print the reply, like this:
+
+ dcopRef = KDE::DCOPRef.new("dcopslot", "MyWidget")
+
+ There are three different ways to specify a DCOP call:
+ 1) res = dcopRef.call("getPoint(QString)", "Hello from dcopsend")
+ 2) res = dcopRef.call("getPoint", "Hello from dcopsend")
+ 3) res = dcopRef.getPoint("Hello from dcopsend")
+
+ puts "result class: #{res.class.name} x: #{res.x} y: #{res.y}"
+
+ If the dcop slot has a 'void' or 'ASYNC' type, the result will be true
+ if the call succeeds or nil if it fails
+
+ - DCOP Attributes
+
+ You can set a dcop attribute like this, instead of calling
+ 'klipper.setClipboardContents("Hello there klipper")':
+
+ klipper = DCOPRef.new("klipper", "klipper")
+ klipper.clipboardContents = "Hello there klipper"
+
+ Amaze your friends! Do the programming equivalent of leaping
+ over tall buildings in one bound! Here with one line of quite
+ clear code, we read a file from disc and assign it the
+ 'clipboardContents' klipper attribute via dcop:
+
+ klipper.clipboardContents = IO.readlines("myfile").to_s
+
+ - DCOP Predicates
+
+ Instead of:
+
+ result = dcopRef.isFoo()
+
+ You can use this more rubyish form:
+
+ if dcopRef.foo?
+ puts "foo is true"
+ else
+ puts "foo? is false"
+ end
+
+ Similarly you can use foo? as an alias for methods of the form
+ hasFoo().
+ See examples/dcop/dcoppredicate.rb and dcopslot.rb
+
+ - Underscore to camel case DCOP method name conversion
+
+ Any underscores in a method name are removed, and the following
+ character is capitalised. For example:
+
+ res = dcopRef.get_point("Hello from dcopsend")
+
+ Is a synonym for:
+
+ res = dcopRef.getPoint("Hello from dcopsend")
+
+ - Send to a DCOPRef:
+
+ There are two different ways to specify a DCOP send:
+ 1) res = dcopRef.send("mySlot(QString)", "Hello from dcopsend")
+ 2) res = dcopRef.send("mySlot", "Hello from dcopsend")
+
+ The result will either be true or false (but not nil for fail like the
+ DCOPRef.call() method described above).
+
+ - When a call of the form 'dcopRef.getPoint(5, "foobar")' is made, the C++
+ type signature is obtained from the list of those returned by
+ DCOPRef.functions(). However, if a method name is overloaded the ruby
+ argument types are used to derive a type signature, in order to resolve
+ the call like this:
+
+ String => QString
+ Float => double
+ Integer => int
+ TrueClass|FalseClass (ie 'true' or 'false') => bool
+ Qt::Widget etc => QWidget
+ KDE::URL etc => KURL
+ Array => QStringList
+
+ Specify the full C++ type signature using the form
+ 'dcopRef.call("getPoint(int,QString)", 5, "foobar")' if these rules fail
+ to pick the right method.
+
+ - DCOP Signals are defined like this:
+
+ k_dcop_signals 'void testEmitSignal(QString)'
+
+ def doit()
+ emit testEmitSignal("Hello DCOP Slot")
+ end
+
+ - Connect slot 'mySlot' to a DCOP signal like this:
+
+ res = slottest.connectDCOPSignal("dcopsignal", "SenderWidget",
+ "testEmitSignal(QString)", "mySlot(QString)",
+ true)
+
+ - Use the '-kde' option with the rbuic tool to require the 'Korundum'
+ extension rather than the 'Qt' one. If the '-x' option is used in
+ conjunction, it generates a KDE top level. For example:
+
+ $ rbuic -x -kde knotifywidgetbase.ui -o knotifywidgetbase.rb
+
+ Will generate this top level code:
+
+ if $0 == __FILE__
+ about = KDE::AboutData.new("knotifywidgetbase", "KNotifyWidgetBase", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::Application.new()
+ w = KNotifyWidgetBase.new
+ a.setMainWidget(w)
+ w.show
+ a.exec
+ end
diff --git a/korundum/TODO b/korundum/TODO
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/korundum/TODO
diff --git a/korundum/bin/Makefile.am b/korundum/bin/Makefile.am
new file mode 100644
index 00000000..7053dc10
--- /dev/null
+++ b/korundum/bin/Makefile.am
@@ -0,0 +1,13 @@
+INCLUDES = $(all_includes) -I$(RUBY_ARCHDIR)
+
+bin_PROGRAMS = krubyinit
+krubyinit_LDFLAGS = -module $(all_libraries) -version-info 0:0:0 -L$(top_srcdir)/smoke/kde/ -L$(RUBY_LIBDIR)
+krubyinit_METASOURCES = AUTO
+krubyinit_SOURCES = krubyinit.cpp
+krubyinit_LDADD = $(LIB_KDE) $(RUBY_LIBRUBYARG) $(top_builddir)/smoke/kde/libsmokekde.la $(top_builddir)/qtruby/rubylib/qtruby/libqtrubyinternal.la
+
+install-exec-local:
+ @-rm -f $(DESTDIR)$(bindir)/rbkdeapi
+ @$(LN_S) rbqtapi $(DESTDIR)$(bindir)/rbkdeapi
+ @-rm -f $(DESTDIR)$(bindir)/rbkdesh
+ @$(LN_S) rbqtsh $(DESTDIR)$(bindir)/rbkdesh
diff --git a/korundum/bin/krubyinit.cpp b/korundum/bin/krubyinit.cpp
new file mode 100644
index 00000000..bbd7c806
--- /dev/null
+++ b/korundum/bin/krubyinit.cpp
@@ -0,0 +1,29 @@
+#include <ruby.h>
+
+/***************************************************************************
+ krubyinit - makes use of kdeinit_wrapper possible for ruby programs
+ -------------------
+ begin : Wed Jan 7 2004
+ copyright : (C) 2004 by Alexander Kellett
+ email : lypanov@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// this name can be used to allow apps
+// to detect what they were started with
+static const char* script_name = "krubyinit_app";
+
+int main(int argc, char **argv) {
+ ruby_init();
+ ruby_script((char*)script_name);
+ ruby_options(argc, argv);
+ ruby_run();
+}
diff --git a/korundum/rubylib/Makefile.am b/korundum/rubylib/Makefile.am
new file mode 100644
index 00000000..754d1b00
--- /dev/null
+++ b/korundum/rubylib/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = korundum rbkconfig_compiler
diff --git a/korundum/rubylib/examples/RubberDoc.rb b/korundum/rubylib/examples/RubberDoc.rb
new file mode 100755
index 00000000..604a9492
--- /dev/null
+++ b/korundum/rubylib/examples/RubberDoc.rb
@@ -0,0 +1,1265 @@
+#!/usr/bin/env ruby
+
+require 'Korundum'
+
+about = KDE::AboutData.new("one", "two", "three")
+KDE::CmdLineArgs.init(ARGV, about)
+app = KDE::Application.new()
+
+# Qt.debug_level = Qt::DebugLevel::High
+# Qt.debug_level = Qt::DebugLevel::Extensive
+
+# TODO
+# improve appearence of sidebar massively
+# cut off after certain number of results?
+# seperate title from proof of hit?
+# when pressing return adjust the current node
+# major speed ups for ctrl-n/p
+# ...
+
+DEBUG = false
+DEBUG_IDX = false
+DEBUG_FAST = true
+DEBUG_SEARCH = true
+DEBUG_GOTO = false # crashes?
+
+def time_me str
+ t1 = Time.now
+ yield
+ t2 = Time.now
+ log "#{str}: #{"%.02f" % (t2 - t1).to_f}s"
+end
+
+module DOMUtils
+
+ def DOMUtils.each_child node
+ indent = 0
+ until node.isNull
+ yield node
+ if not node.firstChild.isNull
+ node = node.firstChild
+ indent += 1
+ elsif not node.nextSibling.isNull
+ node = node.nextSibling
+ else
+ while indent > 0 and !node.isNull and node.nextSibling.isNull
+ node = node.parentNode
+ indent -= 1
+ end
+ if not node.isNull
+ node = node.nextSibling
+ end
+ end
+ break if indent == 0
+ end
+ end
+
+ def DOMUtils.find_node doc, path_a
+ n = doc
+ path_a.reverse.each {
+ |index|
+ top = n.childNodes.length
+ n = n.childNodes.item (top - index)
+ }
+ n
+ end
+
+ def DOMUtils.each_parent node
+ n = node
+ until n.isNull
+ yield n
+ n = n.parentNode
+ end
+ end
+
+ def DOMUtils.list_parent_node_types node
+ types_a = []
+ each_parent(node) {
+ |n| types_a << { :nodeType => n.nodeType, :elementId => n.elementId }
+ }
+ types_a
+ end
+
+ def DOMUtils.get_node_path node
+ n = node
+ path_a = []
+ until n.isNull
+ top = n.parentNode.childNodes.length
+ idx = n.index
+ path_a << (top-idx) if (n.elementId != 0)
+ n = n.parentNode
+ end
+ path_a
+ end
+
+end
+
+class String
+ def trigrams
+ list = []
+ 0.upto(self.length-3) {
+ |pos|
+ list << self.slice(pos, 3)
+ }
+ list
+ end
+end
+
+class GenericTriGramIndex
+ attr_accessor :trigrams
+
+ def initialize
+ clear
+ end
+
+ def clear
+ @trigrams = {}
+ end
+
+ def insert_with_key string, key
+ string.downcase.trigrams.each {
+ |trigram|
+ @trigrams[trigram] = [] unless @trigrams.has_key? trigram
+ @trigrams[trigram] << key
+ }
+ end
+
+ # returns a list of matching keys
+ def search search_string
+ warn "searching for a nil???" if search_string.nil?
+ return [] if search_string.nil?
+ return [] if search_string.length < 3
+ trigs = search_string.downcase.trigrams
+ key_subset = @trigrams[trigs.delete_at(0)]
+ return [] if key_subset.nil?
+ trigs.each {
+ |trigram|
+ trigram_subset = @trigrams[trigram]
+ return [] if trigram_subset.nil?
+ key_subset &= trigram_subset
+ }
+ key_subset
+ end
+end
+
+module LoggedDebug
+
+ def init_logger parent
+ @logger = Qt::TextEdit.new parent
+ @logger.setTextFormat Qt::LogText
+ end
+
+ def log s
+ @logger.append s
+ puts "LOG: #{s}"
+ scrolldown_logger
+ end
+
+ def scrolldown_logger
+ @logger.scrollToBottom
+ end
+
+end
+
+module MyGui
+
+ def init_gui
+ buttons = Qt::HBox.new self
+ @panes = Qt::Splitter.new self
+ @panes.setOrientation Qt::Splitter::Horizontal
+ setStretchFactor @panes, 10
+
+ @results_pane = Qt::VBox.new @panes
+
+ @rightpane = Qt::Splitter.new @panes
+ @rightpane.setOrientation Qt::Splitter::Vertical
+ @viewed = KDE::HTMLPart.new @rightpane
+ init_logger @rightpane
+
+ @listbox = Qt::ListBox.new @results_pane
+
+ @label = Qt::Label.new self
+
+ Qt::Object.connect @listbox, SIGNAL("clicked(QListBoxItem*)"),
+ self, SLOT("clicked_result(QListBoxItem*)")
+ Qt::Object.connect @viewed, SIGNAL("completed()"),
+ self, SLOT("khtml_part_init_complete()")
+
+ Qt::Object::connect @viewed, SIGNAL("setWindowCaption(const QString&)"),
+ @viewed.widget.topLevelWidget,
+ SLOT("setCaption(const QString&)")
+
+ Qt::Object::connect @viewed.browserExtension,
+ SIGNAL("openURLRequest(const KURL&, const KParts::URLArgs&)"),
+ self, SLOT("open_url(const KURL&)")
+
+ KDE::Action.new "&Quit", "quit", KDE::Shortcut.new(),
+ self, SLOT("quit()"), @main.actionCollection, "file_quit"
+ KDE::Action.new "&Index-All", KDE::Shortcut.new(),
+ self, SLOT("index_all()"), @main.actionCollection, "index_all"
+ @back = \
+ KDE::Action.new "&Back", "back", KDE::Shortcut.new(Qt::ALT + Qt::Key_Left),
+ self, SLOT("go_back()"), @main.actionCollection, "back"
+ @forward = \
+ KDE::Action.new "&Forward", "forward", KDE::Shortcut.new(Qt::ALT + Qt::Key_Right),
+ self, SLOT("go_forward()"), @main.actionCollection, "forward"
+ KDE::Action.new "&Home", "gohome", KDE::Shortcut.new(Qt::Key_Home),
+ self, SLOT("go_home()"), @main.actionCollection, "home"
+ KDE::Action.new "&Prev Match", "previous",KDE::Shortcut.new(Qt::CTRL + Qt::Key_P),
+ self, SLOT("goto_prev_match()"), @main.actionCollection, "prev_match"
+ KDE::Action.new "&Next Match", "next", KDE::Shortcut.new(Qt::CTRL + Qt::Key_N),
+ self, SLOT("goto_next_match()"), @main.actionCollection, "next_match"
+ KDE::Action.new "&Follow Match","down", KDE::Shortcut.new(Qt::Key_Return),
+ self, SLOT("goto_current_match_link()"), @main.actionCollection, "open_match"
+
+ KDE::Action.new "Search", "find", KDE::Shortcut.new(Qt::Key_F6),
+ self, SLOT("focus_search()"), @main.actionCollection, "focus_search"
+ KDE::Action.new "New Search", "find", KDE::Shortcut.new(Qt::CTRL + Qt::Key_Slash),
+ self, SLOT("focus_and_clear_search()"), @main.actionCollection, "focus_and_clear_search"
+
+ KDE::Action.new "&Create", "new", KDE::Shortcut.new(),
+ self, SLOT("project_create()"), @main.actionCollection, "project_create"
+ KDE::Action.new "&Choose...", "select", KDE::Shortcut.new(),
+ self, SLOT("project_goto()"), @main.actionCollection, "project_goto"
+
+ clearLocation = KDE::Action.new "Clear Location Bar", "locationbar_erase", KDE::Shortcut.new(),
+ self, SLOT("clear_location()"), @main.actionCollection, "clear_location"
+ clearLocation.setWhatsThis "Clear Location bar<p>Clears the content of the location bar."
+
+ @searchlabel = Qt::Label.new @main
+ @searchlabel.setText "Search: "
+
+ @searchcombo = KDE::HistoryCombo.new @main
+ focus_search
+ Qt::Object.connect @searchcombo, SIGNAL("returnPressed()"),
+ self, SLOT("goto_search()")
+ Qt::Object.connect @searchcombo, SIGNAL("textChanged(const QString&)"),
+ self, SLOT("search(const QString&)")
+
+ KDE::WidgetAction.new @searchlabel, "Search: ", KDE::Shortcut.new(Qt::Key_F6), nil, nil, @main.actionCollection, "location_label"
+ @searchlabel.setBuddy @searchcombo
+
+ ca = KDE::WidgetAction.new @searchcombo, "Search", KDE::Shortcut.new, nil, nil, @main.actionCollection, "toolbar_url_combo"
+ ca.setAutoSized true
+ Qt::WhatsThis::add @searchcombo, "Search<p>Enter a search term."
+ end
+
+ def focus_search
+ @searchcombo.setFocus
+ end
+
+ def focus_and_clear_search
+ clear_location
+ focus_search
+ end
+
+ def clear_location
+ @searchcombo.clearEdit
+ end
+
+ def uri_anchor_split url
+ url =~ /(.*?)(#(.*))?$/
+ return $1, $3
+ end
+
+ def open_url kurl
+ url, anchor = uri_anchor_split kurl.url
+ goto_url url, false unless id == @shown_doc_id
+ @viewed.gotoAnchor anchor unless anchor.nil?
+ end
+
+ def gui_init_proportions
+ # todo - save these settings
+ desktop = Qt::Application::desktop
+ sx = (desktop.width * (2.0/3.0)).to_i
+ sy = (desktop.height * (2.0/3.0)).to_i
+
+ @main.resize sx, sy
+
+ logsize = 0
+ resultssize = (sx / 5.0).to_i
+
+ @rightpane.setSizes [sy-logsize, logsize]
+ @panes.setSizes [resultssize, sx-resultssize]
+
+ @rightpane.setResizeMode @logger, Qt::Splitter::KeepSize
+
+ @panes.setResizeMode @results_pane, Qt::Splitter::KeepSize
+ @panes.setResizeMode @rightpane, Qt::Splitter::KeepSize
+ end
+
+end
+
+module IndexStorage
+
+ INDEX_VERSION = 3
+
+ IndexStore = Struct.new :index, :nodeindex, :textcache, :id2title, :id2uri, :id2depth, :version
+
+ def index_fname
+ basedir = ENV["HOME"] + "/.rubberdocs"
+ prefix = basedir + "/." + @pref.gsub(/\//,",") + ".idx"
+ Dir.mkdir basedir unless File.exists? basedir
+ "#{prefix}.doc"
+ end
+
+ def depth_debug
+ puts "depth_debug : begin"
+ @id2depth.each_key {
+ |id|
+ puts "indexed to depth #{@id2depth[id]} : #{@id2uri[id]}"
+ }
+ puts "end :"
+ end
+
+ def load_indexes
+ return false unless File.exists? index_fname
+ Qt::Application::setOverrideCursor(Qt::Cursor.new Qt::WaitCursor)
+ File.open(index_fname, "r") {
+ |file|
+ w = Marshal.load file rescue nil
+ return false if w.nil? || w.version < INDEX_VERSION
+ @index = w.index
+ @nodeindex = w.nodeindex
+ @textcache = w.textcache
+ @id2title = w.id2title
+ @id2uri = w.id2uri
+ @id2depth = w.id2depth
+ @indexed_more = false
+ true
+ }
+ Qt::Application::restoreOverrideCursor
+ end
+
+ def save_indexes
+ return unless @indexed_more
+ File.open(index_fname, "w") {
+ |file|
+ w = IndexStore.new
+ w.index = @index
+ w.nodeindex = @nodeindex
+ w.textcache = @textcache
+ w.id2title = @id2title
+ w.id2uri = @id2uri
+ w.id2depth = @id2depth
+ w.version = INDEX_VERSION
+ Marshal.dump w, file
+ }
+ end
+
+end
+
+module HTMLIndexer
+
+ DocNodeRef = Struct.new :doc_idx, :node_path
+
+ module IndexDepths
+ # TitleIndexed implies "LinkTitlesIndexed"
+ Allocated, TitleIndexed, LinksFollowed, Partial, Node = 0, 1, 2, 3, 4
+ end
+
+ def index_documents
+ # fix this to use kde's actual dir
+ @t1 = Time.now
+ @url = first_url
+ already_indexed = load_indexes
+ @top_doc_id = already_indexed ? @id2uri.keys.max + 1 : 0
+ return if already_indexed
+ t1 = Time.now
+ @viewed.hide
+ @done = []
+ @todo_links = []
+ progress = KDE::ProgressDialog.new(self, "blah", "Indexing files...", "Abort Indexing", true)
+ total_num_files = Dir.glob("#{@pref}/**/*.html").length
+ progress.progressBar.setTotalSteps total_num_files
+ @todo_links = [ DOM::DOMString.new first_url.url ]
+ until @todo_links.empty?
+ @todo_next = []
+ while more_to_do
+ progress.progressBar.setProgress @id2title.keys.length
+ end
+ @todo_links = @todo_next
+ fail "errr, you really didn't want to do that dave" if progress.wasCancelled
+ end
+ progress.progressBar.setProgress total_num_files
+ save_indexes
+ t2 = Time.now
+ log "all documents indexed in #{(t2 - t1).to_i}s"
+ end
+
+ def should_follow? lhref
+ case lhref
+ when /source/, /members/
+ ret = false
+ when /^file:#{@pref}/
+ ret = true
+ else
+ ret = false
+ end
+ ret
+ end
+
+ def gather_for_current_page
+ index_current_title
+ return [] if @id2depth[@shown_doc_id] >= IndexDepths::LinksFollowed
+ todo_links = []
+ title_map = {}
+ anchors = @viewed.htmlDocument.links
+ f = anchors.firstItem
+ count = anchors.length
+ until (count -= 1) < 0
+ text = ""
+ DOMUtils.each_child(f) {
+ |node|
+ text << node.nodeValue.string if node.nodeType == DOM::Node::TEXT_NODE
+ }
+ link = Qt::Internal::cast_object_to f, DOM::HTMLLinkElement
+ if should_follow? link.href.string
+ title_map[link.href.string] = text
+ urlonly, = uri_anchor_split link.href.string
+ add_link_to_index urlonly, text
+ todo_links << link.href unless DEBUG_FAST
+ end
+ f = anchors.nextItem
+ end
+ @id2depth[@shown_doc_id] = IndexDepths::LinksFollowed
+ return todo_links
+ end
+
+ def find_allocated_uri uri
+ id = @id2uri.invert[uri]
+ return id
+ end
+
+ # sets @shown_doc_id
+ def index_current_title
+ id = find_allocated_uri(@viewed.htmlDocument.URL.string)
+ return if !id.nil? and @id2depth[id] >= IndexDepths::TitleIndexed
+ log "making space for url #{@viewed.htmlDocument.URL.string.sub(@pref,"")}"
+ id = alloc_index_space @viewed.htmlDocument.URL.string if id.nil?
+ @indexed_more = true
+ @id2title[id] = @viewed.htmlDocument.title.string
+ @id2depth[id] = IndexDepths::TitleIndexed
+ @shown_doc_id = id
+ end
+
+ def alloc_index_space uri
+ @indexed_more = true
+ id = @top_doc_id
+ @id2uri[@top_doc_id] = uri
+ @id2title[@top_doc_id] = nil
+ @id2depth[@top_doc_id] = IndexDepths::Allocated
+ @top_doc_id += 1
+ id
+ end
+
+ def add_link_to_index uri, title
+ return unless find_allocated_uri(uri).nil?
+ @indexed_more = true
+ new_id = alloc_index_space uri
+ @id2title[new_id] = title
+ @index.insert_with_key title, new_id
+ end
+
+ def index_current_document
+ return if @id2depth[@shown_doc_id] >= IndexDepths::Partial
+ Qt::Application::setOverrideCursor(Qt::Cursor.new Qt::WaitCursor)
+ @indexed_more = true
+ @label.setText "Scanning : #{@url.prettyURL}"
+ log "indexing url #{@viewed.htmlDocument.URL.string.sub(@pref,"")}"
+ DOMUtils.each_child(@viewed.document) {
+ |node|
+ next unless node.nodeType == DOM::Node::TEXT_NODE
+ @index.insert_with_key node.nodeValue.string, @shown_doc_id
+ }
+ @id2depth[@shown_doc_id] = IndexDepths::Partial
+ @label.setText "Ready"
+ Qt::Application::restoreOverrideCursor
+ end
+
+ def preload_text
+ return if @id2depth[@shown_doc_id] >= IndexDepths::Node
+ Qt::Application::setOverrideCursor(Qt::Cursor.new Qt::WaitCursor)
+ @indexed_more = true
+ index_current_document
+ log "deep indexing url #{@viewed.htmlDocument.URL.string.sub(@pref,"")}"
+ @label.setText "Indexing : #{@url.prettyURL}"
+ doc_text = ""
+ t1 = Time.now
+ DOMUtils.each_child(@viewed.document) {
+ |node|
+ next unless node.nodeType == DOM::Node::TEXT_NODE
+ ref = DocNodeRef.new @shown_doc_id, DOMUtils.get_node_path(node)
+ @nodeindex.insert_with_key node.nodeValue.string, ref
+ @textcache[ref] = node.nodeValue.string
+ doc_text << node.nodeValue.string
+ }
+ @id2depth[@shown_doc_id] = IndexDepths::Node
+ @label.setText "Ready"
+ Qt::Application::restoreOverrideCursor
+ end
+
+end
+
+# TODO - this sucks, use khtml to get the values
+module IDS
+ A = 1
+ META = 62
+ STYLE = 85
+ TITLE = 95
+end
+
+module TermHighlighter
+
+ include IDS
+
+ FORBIDDEN_TAGS = [IDS::TITLE, IDS::META, IDS::STYLE]
+
+ def update_highlight
+ return if @search_text.nil? || @search_text.empty?
+ return if @in_update_highlight
+ @in_update_highlight = true
+ preload_text
+ highlighted_nodes = []
+ @nodeindex.search(@search_text).each {
+ |ref|
+ next unless ref.doc_idx == @shown_doc_id
+ highlighted_nodes << ref.node_path
+ }
+ highlight_node_list highlighted_nodes
+ @in_update_highlight = false
+ end
+
+ def mark_screwup
+ @screwups = 0 if @screwups.nil?
+ warn "if you see this, then alex screwed up!.... #{@screwups} times!"
+ @screwups += 1
+ end
+
+ def highlight_node_list highlighted_nodes
+ doc = @viewed.document
+ no_undo_buffer = @to_undo.nil?
+ current_doc_already_highlighted = (@shown_doc_id == @last_highlighted_doc_id)
+ undo_highlight @to_undo unless no_undo_buffer or !current_doc_already_highlighted
+ @last_highlighted_doc_id = @shown_doc_id
+ @to_undo = []
+ return if highlighted_nodes.empty?
+ Qt::Application::setOverrideCursor(Qt::Cursor.new Qt::WaitCursor)
+ cursor_override = true
+ @current_matching_node_index = 0 if @current_matching_node_index.nil?
+ @current_matching_node_index = @current_matching_node_index.modulo highlighted_nodes.length
+ caretnode = DOMUtils.find_node doc, highlighted_nodes[@current_matching_node_index]
+ @viewed.setCaretVisible false
+ @viewed.setCaretPosition caretnode, 0
+ caret_path = DOMUtils.get_node_path(caretnode)
+ count = 0
+ @skipped_highlight_requests = false
+ @current_matched_href = nil
+ highlighted_nodes.sort.each {
+ |path|
+ node = DOMUtils.find_node doc, path
+ next mark_screwup if node.nodeValue.string.nil?
+ match_idx = node.nodeValue.string.downcase.index @search_text.downcase
+ next mark_screwup if match_idx.nil?
+ parent_info = DOMUtils.list_parent_node_types node
+ has_title_parent = !(parent_info.detect { |a| FORBIDDEN_TAGS.include? a[:elementId] }.nil?)
+ next if has_title_parent
+ if path == caret_path
+ DOMUtils.each_parent(node) {
+ |n|
+ next unless n.elementId == IDS::A
+ # link = DOM::HTMLLinkElement.new n # WTF? why doesn't this work???
+ link = Qt::Internal::cast_object_to n, "DOM::HTMLLinkElement"
+ @current_matched_href = link.href.string
+ }
+ end
+ before = doc.createTextNode node.nodeValue.split(0)
+ matched = doc.createTextNode before.nodeValue.split(match_idx)
+ after = doc.createTextNode matched.nodeValue.split(@search_text.length)
+ DOM::CharacterData.new(DOM::Node.new after).setData DOM::DOMString.new("") \
+ if after.nodeValue.string.nil?
+ span = doc.createElement DOM::DOMString.new("span")
+ spanelt = DOM::HTMLElement.new span
+ classname = (path == caret_path) ? "foundword" : "searchword"
+ spanelt.setClassName DOM::DOMString.new(classname)
+ span.appendChild matched
+ node.parentNode.insertBefore before, node
+ node.parentNode.insertBefore span, node
+ node.parentNode.insertBefore after, node
+ @to_undo << [node.parentNode, before]
+ node.parentNode.removeChild node
+ rate = (count > 50) ? 50 : 10
+ allow_user_input = ((count+=1) % rate == 0)
+ if allow_user_input
+ Qt::Application::restoreOverrideCursor if cursor_override
+ cursor_override = false
+ @in_node_highlight = true
+ Qt::Application::eventLoop.processEvents Qt::EventLoop::AllEvents, 10
+ @in_node_highlight = false
+ if @skipped_highlight_requests
+ @timer.start 50, true
+ return false
+ end
+ @viewed.view.layout
+ end
+ }
+ if @skipped_highlight_requests
+ @timer.start 50, true
+ end
+ Qt::Application::restoreOverrideCursor if cursor_override
+ end
+
+ def undo_highlight to_undo
+ to_undo.reverse.each {
+ |pnn| pn, before = *pnn
+ mid = before.nextSibling
+ after = mid.nextSibling
+ beforetext = before.nodeValue
+ aftertext = after.nodeValue
+ pn.removeChild after
+ midtxtnode = mid.childNodes.item(0)
+ midtext = midtxtnode.nodeValue
+ str = DOM::DOMString.new ""
+ str.insert aftertext, 0
+ str.insert midtext, 0
+ str.insert beforetext, 0
+ chardata = DOM::CharacterData.new(DOM::Node.new before)
+ chardata.setData str
+ pn.removeChild mid
+ }
+ end
+
+end
+
+class SmallIconSet
+ def SmallIconSet.[] name
+ loader = KDE::Global::instance.iconLoader
+ return loader.loadIconSet name, KDE::Icon::Small, 0
+ end
+end
+
+class ProjectEditDialog < Qt::Object
+
+ slots "select_file()", "slot_ok()"
+
+ def initialize project_name, parent=nil,name=nil,caption=nil
+
+ super(parent, name)
+ @parent = parent
+
+ @dialog = KDE::DialogBase.new(parent,name, true, caption,
+ KDE::DialogBase::Ok|KDE::DialogBase::Cancel, KDE::DialogBase::Ok, false)
+
+ vbox = Qt::VBox.new @dialog
+
+ grid = Qt::Grid.new 2, Qt::Horizontal, vbox
+
+ titlelabel = Qt::Label.new "Name:", grid
+ @title = KDE::LineEdit.new grid
+ titlelabel.setBuddy @title
+
+ urllabel = Qt::Label.new "Location:", grid
+ lochbox = Qt::HBox.new grid
+ @url = KDE::LineEdit.new lochbox
+ urllabel.setBuddy @url
+ locselc = Qt::PushButton.new lochbox
+ locselc.setIconSet SmallIconSet["up"]
+
+ blub = Qt::HBox.new vbox
+ Qt::Label.new "Is main one?:", blub
+ @cb = Qt::CheckBox.new blub
+
+ enabled = @parent.projects_data.project_list.empty?
+
+ unless project_name.nil?
+ project_url = @parent.projects_data.project_list[project_name]
+ @title.setText project_name
+ @url.setText project_url
+ enabled = true if (project_name == @parent.projects_data.enabled_name)
+ end
+
+ @cb.setChecked true if enabled
+
+ Qt::Object.connect @dialog, SIGNAL("okClicked()"),
+ self, SLOT("slot_ok()")
+
+ Qt::Object.connect locselc, SIGNAL("clicked()"),
+ self, SLOT("select_file()")
+
+ @title.setFocus
+
+ @dialog.setMainWidget vbox
+
+ @modified = false
+ end
+
+ def select_file
+ s = Qt::FileDialog::getOpenFileName ENV["HOME"], "HTML Files (*.html)",
+ @parent, "open file dialog", "Choose a file"
+ @url.setText s unless s.nil?
+ end
+
+ def edit
+ @dialog.exec
+ return @modified
+ end
+
+ def new_name
+ @title.text
+ end
+
+ def new_url
+ @url.text
+ end
+
+ def new_enabled
+ @cb.isChecked
+ end
+
+ def slot_ok
+ @parent.projects_data.project_list[new_name] = new_url
+ @parent.projects_data.enabled_name = new_name if new_enabled
+ @modified = true
+ end
+
+end
+
+class ProjectSelectDialog < Qt::Object
+
+ slots "edit_selected_project()", "delete_selected_project()", "project_create_button()", "project_selected()"
+
+ def initialize parent=nil,name=nil,caption=nil
+ super(parent, name)
+ @parent = parent
+
+ @dialog = KDE::DialogBase.new parent,name, true, caption,
+ KDE::DialogBase::Ok|KDE::DialogBase::Cancel, KDE::DialogBase::Ok, false
+
+ vbox = Qt::VBox.new @dialog
+
+ @listbox = Qt::ListBox.new vbox
+
+ fill_listbox
+
+ hbox = Qt::HBox.new vbox
+ button_new = Qt::PushButton.new "New...", hbox
+ button_del = Qt::PushButton.new "Delete", hbox
+ button_edit = Qt::PushButton.new "Edit...", hbox
+
+ Qt::Object.connect button_new, SIGNAL("clicked()"),
+ self, SLOT("project_create_button()")
+
+ Qt::Object.connect button_del, SIGNAL("clicked()"),
+ self, SLOT("delete_selected_project()")
+
+ Qt::Object.connect button_edit, SIGNAL("clicked()"),
+ self, SLOT("edit_selected_project()")
+
+ Qt::Object.connect @listbox, SIGNAL("doubleClicked(QListBoxItem *)"),
+ self, SLOT("project_selected()")
+
+ @dialog.setMainWidget vbox
+ end
+
+ def project_selected
+ return if @listbox.selectedItem.nil?
+ @parent.current_project_name = @listbox.selectedItem.text
+ @parent.blah_blah
+ @dialog.reject
+ end
+
+ def fill_listbox
+ @listbox.clear
+ @parent.projects_data.project_list.keys.each {
+ |name|
+ enabled = (name == @parent.projects_data.enabled_name)
+ icon = enabled ? "forward" : "down"
+ pm = SmallIconSet[icon].pixmap(Qt::IconSet::Automatic, Qt::IconSet::Normal)
+ it = Qt::ListBoxPixmap.new pm, name
+ @listbox.insertItem it
+ }
+ end
+
+ def edit_selected_project
+ return if @listbox.selectedItem.nil?
+ oldname = @listbox.selectedItem.text
+ dialog = ProjectEditDialog.new oldname, @parent
+ mod = dialog.edit
+ if mod and oldname != dialog.new_name
+ @parent.projects_data.project_list.delete oldname
+ end
+ fill_listbox if mod
+ end
+
+ def project_create_button
+ mod = @parent.project_create
+ fill_listbox if mod
+ end
+
+ def delete_selected_project
+ return if @listbox.selectedItem.nil?
+ # TODO - confirmation dialog
+ @parent.projects_data.project_list.delete @listbox.selectedItem.text
+ fill_listbox
+ end
+
+ def select
+ @dialog.exec
+ end
+
+end
+
+module ProjectManager
+
+ def project_create
+ dialog = ProjectEditDialog.new nil, self
+ dialog.edit
+ while @projects_data.project_list.empty?
+ dialog.edit
+ end
+ end
+
+ def project_goto
+ dialog = ProjectSelectDialog.new self
+ dialog.select
+ if @projects_data.project_list.empty?
+ project_create
+ end
+ end
+
+ require 'yaml'
+
+ def yamlfname
+ ENV["HOME"] + "/.rubberdocs/projects.yaml"
+ end
+
+ PROJECT_STORE_VERSION = 0
+
+ Projects = Struct.new :project_list, :enabled_name, :version
+
+ def load_projects
+ okay = false
+ if File.exists? yamlfname
+ @projects_data = YAML::load File.open(yamlfname)
+ if (@projects_data.version rescue -1) >= PROJECT_STORE_VERSION
+ okay = true
+ end
+ end
+ if not okay or @projects_data.project_list.empty?
+ @projects_data = Projects.new({}, nil, PROJECT_STORE_VERSION)
+ project_create
+ end
+ if @projects_data.enabled_name.nil?
+ @projects_data.enabled_name = @projects_data.project_list.keys.first
+ end
+ end
+
+ def save_projects
+ File.open(yamlfname, "w+") {
+ |file|
+ file.puts @projects_data.to_yaml
+ }
+ end
+
+end
+
+class RubberDoc < Qt::VBox
+
+ slots "khtml_part_init_complete()",
+ "go_back()", "go_forward()", "go_home()", "goto_url()",
+ "goto_search()", "clicked_result(QListBoxItem*)",
+ "search(const QString&)", "update_highlight()",
+ "quit()", "open_url(const KURL&)", "index_all()",
+ "goto_prev_match()", "goto_next_match()", "clear_location()", "activated()",
+ "goto_current_match_link()", "focus_search()", "focus_and_clear_search()",
+ "project_create()", "project_goto()"
+
+ attr_accessor :back, :forward, :url, :projects_data
+
+ include LoggedDebug
+ include MyGui
+ include IndexStorage
+ include HTMLIndexer
+ include TermHighlighter
+ include ProjectManager
+
+ def init_blah
+ @index = GenericTriGramIndex.new
+ @nodeindex = GenericTriGramIndex.new
+ @textcache = {}
+ @id2uri, @id2title, @id2depth = {}, {}, {}
+
+ @history, @popped_history = [], []
+ @shown_doc_id = 0
+ @freq_sorted_idxs = nil
+ @last_highlighted_doc_id, @to_undo = nil, nil, nil
+ @search_text = nil
+ @current_matched_href = nil
+
+ @in_update_highlight = false
+ @in_node_highlight = false
+
+ @lvis = nil
+ end
+
+ def initialize parent
+ super parent
+ @main = parent
+
+ load_projects
+ @current_project_name = @projects_data.enabled_name
+
+ init_blah
+
+ init_gui
+ gui_init_proportions
+
+ @timer = Qt::Timer.new self
+ Qt::Object.connect @timer, SIGNAL("timeout()"),
+ self, SLOT("update_highlight()")
+
+ @viewed.openURL KDE::URL.new("about:blank")
+
+ @init_connected = true
+ end
+
+ def blah_blah
+ save_indexes
+ init_blah
+ khtml_part_init_complete
+ end
+
+ def quit
+ @main.close
+ end
+
+ def khtml_part_init_complete
+ Qt::Object.disconnect @viewed, SIGNAL("completed()"),
+ self, SLOT("khtml_part_init_complete()") if @init_connected
+
+ @pref = File.dirname first_url.url.gsub("file:","")
+
+ init_khtml_part_settings @viewed if @init_connected
+ index_documents
+
+ # maybe make a better choice as to the start page???
+ @shown_doc_id = 0
+ goto_url @id2uri[@shown_doc_id], false
+
+ @viewed.show
+
+ search "qlistview" if DEBUG_SEARCH || DEBUG_GOTO
+ goto_search if DEBUG_GOTO
+
+ @init_connected = false
+ end
+
+ def finish
+ save_projects
+ save_indexes
+ end
+
+ def init_khtml_part_settings khtmlpart
+ khtmlpart.setJScriptEnabled true
+ khtmlpart.setJavaEnabled false
+ khtmlpart.setPluginsEnabled false
+ khtmlpart.setAutoloadImages false
+ end
+
+ def load_page
+ @viewed.setCaretMode true
+ @viewed.setCaretVisible false
+ @viewed.document.setAsync false
+ @viewed.document.load DOM::DOMString.new @url.url
+ @viewed.setUserStyleSheet "span.searchword { background-color: yellow }
+ span.foundword { background-color: green }"
+ Qt::Application::eventLoop.processEvents Qt::EventLoop::ExcludeUserInput
+ end
+
+ attr_accessor :current_project_name
+
+ def first_url
+ return KDE::URL.new @projects_data.project_list[@current_project_name]
+ end
+
+ def search s
+ if @in_node_highlight
+ @skipped_highlight_requests = true
+ return
+ end
+ puts "search request: #{s}"
+ @search_text = s
+
+ results = @index.search(s)
+ results += @nodeindex.search(s).collect { |docref| docref.doc_idx }
+
+ idx_hash = Hash.new { |h,k| h[k] = 0 }
+ results.each {
+ |idx| idx_hash[idx] += 1
+ }
+ @freq_sorted_idxs = idx_hash.to_a.sort_by { |val| val[1] }.reverse
+
+ update_lv
+
+ hl_timeout = 150 # continuation search should be slower?
+ @timer.start hl_timeout, true unless @freq_sorted_idxs.empty?
+ end
+
+ def look_for_prefixes
+ prefixes = []
+ # TODO - fix this crappy hack
+ @id2title.values.compact.sort.each {
+ |title|
+ title.gsub! "\n", ""
+ pos = title.index ":"
+ next if pos.nil?
+ prefix = title[0..pos-1]
+ prefixes << prefix
+ new_title = title[pos+1..title.length]
+ new_title.gsub! /(\s\s+|^\s+|\s+$)/, ""
+ title.replace new_title
+ }
+ end
+
+ class ResultItem < Qt::ListBoxItem
+ def initialize header, text
+ super()
+ @text, @header = text, header
+ @font = Qt::Font.new("Helvetica", 8)
+ @flags = Qt::AlignLeft | Qt::WordBreak
+ end
+ def paint painter
+ w, h = width(listBox), height(listBox)
+ header_height = (text_height @font, @header) + 5
+ painter.setFont @font
+ painter.fillRect 5, 5, w - 10, header_height, Qt::Brush.new(Qt::Color.new 150,100,150)
+ painter.drawText 5, 5, w - 10, header_height, @flags, @header
+ painter.fillRect 5, header_height, w - 10, h - 10, Qt::Brush.new(Qt::Color.new 100,150,150)
+ painter.setFont @font
+ painter.drawText 5, header_height + 2, w - 10, h - 10, @flags, @text
+ end
+ def text_height font, text
+ fm = Qt::FontMetrics.new font
+ br = fm.boundingRect 0, 0, width(listBox) - 20, 8192, @flags, text
+ br.height
+ end
+ def height listbox
+ h = 0
+ h += text_height @font, @text
+ h += text_height @font, @header
+ return h + 10
+ end
+ def width listbox
+ listBox.width - 5
+ end
+ end
+
+ CUTOFF = 100
+ def update_lv
+ @listbox.clear
+ @lvis = {}
+ look_for_prefixes
+ return if @freq_sorted_idxs.nil?
+ @freq_sorted_idxs.each {
+ |a| idx, count = *a
+ title = @id2title[idx]
+ # we must re-search until we have a doc -> nodes list
+ matches_text = ""
+ @nodeindex.search(@search_text).each {
+ |ref|
+ break if matches_text.length > CUTOFF
+ next unless ref.doc_idx == idx
+ matches_text << @textcache[ref] << "\n"
+ }
+ matches_text = matches_text.slice 0..CUTOFF
+ lvi = ResultItem.new "(#{count}) #{title}", matches_text
+ @listbox.insertItem lvi
+ @lvis[lvi] = idx
+ }
+ end
+
+ def goto_search
+ idx, count = *(@freq_sorted_idxs.first)
+ goto_id_and_hl idx
+ end
+
+ def clicked_result i
+ return if i.nil?
+ idx = @lvis[i]
+ goto_id_and_hl idx
+ end
+
+ def goto_id_and_hl idx
+ @current_matching_node_index = 0
+ goto_url @id2uri[idx], true
+ @shown_doc_id = idx
+ update_highlight
+ end
+
+ def goto_current_match_link
+ open_url KDE::URL.new(@current_matched_href) unless @current_matched_href.nil?
+ end
+
+ def skip_matches n
+ @current_matching_node_index += n # autowraps
+ if @in_node_highlight
+ @skipped_highlight_requests = true
+ return
+ end
+ update_highlight
+ end
+
+ def goto_prev_match
+ skip_matches -1
+ end
+
+ def goto_next_match
+ skip_matches +1
+ end
+
+ def more_to_do
+ return false if @todo_links.empty?
+ lhref = @todo_links.pop
+ do_for_link lhref
+ true
+ end
+
+ def do_for_link lhref
+ idx = (lhref.string =~ /#/)
+ unless idx.nil?
+ lhref = lhref.copy
+ lhref.truncate idx
+ end
+ skip = @done.include? lhref.string
+ return [] if skip
+time_me("loading") {
+ @viewed.document.setAsync false
+ @viewed.document.load lhref
+}
+ @done << lhref.string
+ newlinks = gather_for_current_page
+ @todo_next += newlinks
+ end
+
+ def update_ui_elements
+ @forward.setEnabled !@popped_history.empty?
+ @back.setEnabled !@history.empty?
+ end
+
+ def go_back
+ @popped_history << @url
+ fail "ummm... already at the start, gui bug" if @history.empty?
+ goto_url @history.pop, false, false
+ update_loc
+ update_ui_elements
+ end
+
+ def go_forward
+ fail "history bug" if @popped_history.empty?
+ goto_url @popped_history.pop, false, false
+ @history << @url
+ update_loc
+ update_ui_elements
+ end
+
+ def update_loc
+ # @location.setText @url.prettyURL
+ end
+
+ def go_home
+ goto_url first_url
+ end
+
+ def index_all
+ @viewed.hide
+ @id2uri.keys.each {
+ |id| goto_id_and_hl id
+ }
+ @viewed.show
+ end
+
+ def goto_url url = nil, history_store = true, clear_forward = true
+ @popped_history = [] if clear_forward
+ if history_store
+ @history << @url
+ end
+ @url = KDE::URL.new(url.nil? ? @location.text : url)
+ @label.setText "Loading : #{@url.prettyURL}"
+ urlonly, = uri_anchor_split @url.url
+ id = @id2uri.invert[@url.url]
+ if id.nil? and !(should_follow? urlonly)
+ warn "link points outside indexed space!"
+ return
+ end
+ load_page
+ if id.nil?
+ gather_for_current_page
+ id = @shown_doc_id
+ index_current_document
+ else
+ @shown_doc_id = id
+ end
+ @label.setText "Ready"
+ update_loc unless url.nil?
+ update_ui_elements
+ end
+
+end
+
+m = KDE::MainWindow.new
+browser = RubberDoc.new m
+browser.update_ui_elements
+guixmlfname = Dir.pwd + "/RubberDoc.rc"
+guixmlfname = File.dirname(File.readlink $0) + "/RubberDoc.rc" unless File.exists? guixmlfname
+m.createGUI guixmlfname
+m.setCentralWidget browser
+app.setMainWidget(m)
+m.show
+app.exec()
+browser.finish
+
+__END__
+
+TESTCASE -
+w = KDE::HTMLPart # notice the missing .new
+w.begin
+=> crashes badly
+
+(RECHECK)
+./kde.rb:29:in `method_missing': Cannot handle 'const QIconSet&' as argument to QTabWidget::changeTab (ArgumentError)
+ from ./kde.rb:29:in `initialize'
+ from ./kde.rb:92:in `new'
+ from ./kde.rb:92
+for param nil given to param const QIconSet &
+occurs frequently
+
+dum di dum
+
+can't get tabwidget working. umm... wonder what i'm messing up... (RECHECK)
+
+ tabwidget = KDE::TabWidget.new browser
+ tabwidget.setTabPosition Qt::TabWidget::Top
+ @viewed = KDE::HTMLPart.new tabwidget
+ w2 = KDE::HTMLPart.new tabwidget
+ tabwidget.changeTab @viewed, Qt::IconSet.new, "blah blah"
+ tabwidget.showPage @viewed
+ tabwidget.show
+ @viewed.show
+
+# possible BUG DOM::Text.new(node).data.string # strange that this one doesn't work... (RECHECK)
+
+wierd khtml bug
+ @rightpane.setResizeMode @viewed, Qt::Splitter::KeepSize
+
+in order to use KURL's as constants one must place this KApplication init
+at the top of the file otherwise KInstance isn't init'ed before KURL usage
+
+class ProjectSelectDialog < KDE::DialogBase
+ def initialize parent=nil,name=nil,caption=nil
+ super(parent,name, true, caption,
+ KDE::DialogBase::Ok|KDE::DialogBase::Cancel, KDE::DialogBase::Ok, false, KDE::GuiItem.new)
+ blah blah
+ end
+end
+
+# painter.fillRect 5, 5, width(listBox) - 10, height(listBox) - 10, Qt::Color.new(255,0,0)
diff --git a/korundum/rubylib/examples/RubberDoc.rc b/korundum/rubylib/examples/RubberDoc.rc
new file mode 100644
index 00000000..8e544b1a
--- /dev/null
+++ b/korundum/rubylib/examples/RubberDoc.rc
@@ -0,0 +1,35 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="xmlgui" version="2">
+
+<MenuBar>
+ <Menu name="file" noMerge="1"><text>&amp;File</text>
+ <Action name="index_all"/>
+ <Separator/>
+ <Action name="file_quit"/>
+ </Menu>
+</MenuBar>
+
+<ToolBar name="projectToolbar" noMerge="1" fullWidth="true" iconText="icontextright"><text>Project Toolbar</text>
+ <Action name="project_create"/>
+ <Action name="project_delete"/>
+ <Action name="project_manage"/>
+ <Action name="project_goto"/>
+</ToolBar>
+
+<ToolBar name="mainToolBar" noMerge="1" fullWidth="true" iconText="icontextright"><text>Main Toolbar</text>
+ <Action name="back"/>
+ <Action name="forward"/>
+ <Action name="home"/>
+ <Action name="prev_match"/>
+ <Action name="next_match"/>
+ <Action name="open_match"/>
+</ToolBar>
+
+<ToolBar fullWidth="true" name="locationToolBar" newline="true"><text>Location Toolbar</text>
+ <Action name="clear_location" />
+ <Action name="location_label" />
+ <Action name="toolbar_url_combo" />
+ <Action name="go_url" />
+</ToolBar>
+
+</kpartgui>
diff --git a/korundum/rubylib/examples/dcop/dcopcall.rb b/korundum/rubylib/examples/dcop/dcopcall.rb
new file mode 100755
index 00000000..f3b532ef
--- /dev/null
+++ b/korundum/rubylib/examples/dcop/dcopcall.rb
@@ -0,0 +1,37 @@
+#!/usr/bin/env ruby
+
+require 'Korundum'
+include KDE
+
+class SenderWidget < PushButton
+ def initialize(parent, name)
+ super
+ connect(self, SIGNAL('clicked()'), self, SLOT('doit()'))
+ end
+
+ slots 'doit()'
+
+ def doit()
+ dcopRef = DCOPRef.new("dcopslot", "MyWidget")
+ #
+ # Note that there are three different ways to make a DCOP call():
+ # 1) result = dcopRef.call("getPoint(QString)", "Hello from dcopcall")
+ # 2) result = dcopRef.call("getPoint", "Hello from dcopcall")
+ # 3) result = dcopRef.getPoint("Hello from dcopcall")
+ #
+ result = dcopRef.getPoint("Hello from dcopcall")
+ if result.nil?
+ puts "DCOP call failed"
+ else
+ puts "result class: #{result.class.name} x: #{result.x} y: #{result.y}"
+ end
+ end
+end
+
+about = AboutData.new("dcopcall", "DCOP Call Test", "0.1")
+CmdLineArgs.init(ARGV, about)
+a = UniqueApplication.new
+calltest = SenderWidget.new(nil, "calltest") { setText 'DCOP Call Test' }
+a.mainWidget = calltest
+calltest.show
+a.exec
diff --git a/korundum/rubylib/examples/dcop/dcoppredicate.rb b/korundum/rubylib/examples/dcop/dcoppredicate.rb
new file mode 100755
index 00000000..82a9c8b4
--- /dev/null
+++ b/korundum/rubylib/examples/dcop/dcoppredicate.rb
@@ -0,0 +1,41 @@
+#!/usr/bin/env ruby
+
+require 'Korundum'
+include KDE
+
+class SenderWidget < PushButton
+ def initialize(parent, name)
+ super
+ connect(self, SIGNAL('clicked()'), self, SLOT('doit()'))
+ end
+
+ slots 'doit()'
+
+ def doit()
+ dcopRef = DCOPRef.new("dcopslot", "MyWidget")
+ #
+ # A synonym for isFoo()
+ result = dcopRef.foo?
+ if result.nil?
+ puts "DCOP predicate failed"
+ else
+ puts "foo? is #{result}"
+ end
+
+ # A synonym for hasBar()
+ result = dcopRef.bar?
+ if result.nil?
+ puts "DCOP predicate failed"
+ else
+ puts "bar? is #{result}"
+ end
+ end
+end
+
+about = AboutData.new("dcoppredicate", "DCOP Predicate Test", "0.1")
+CmdLineArgs.init(ARGV, about)
+a = UniqueApplication.new
+calltest = SenderWidget.new(nil, "predicatetest") { setText 'DCOP Predicate Test' }
+a.mainWidget = calltest
+calltest.show
+a.exec
diff --git a/korundum/rubylib/examples/dcop/dcopsend.rb b/korundum/rubylib/examples/dcop/dcopsend.rb
new file mode 100755
index 00000000..9365473b
--- /dev/null
+++ b/korundum/rubylib/examples/dcop/dcopsend.rb
@@ -0,0 +1,35 @@
+#!/usr/bin/env ruby
+
+require 'Korundum'
+
+class SenderWidget < KDE::PushButton
+ def initialize(parent, name)
+ super
+ Qt::Object::connect(self, SIGNAL('clicked()'), self, SLOT('doit()'))
+ end
+
+ slots 'doit()'
+
+ def doit()
+ #
+ # Note that there are three different ways to make a DCOP send():
+ # 1) dcopRef.send("mySlot(QString)", "Hello from dcopsend")
+ # 2) dcopRef.send("mySlot", "Hello from dcopsend")
+ #
+ dcopRef = KDE::DCOPRef.new("dcopslot", "MyWidget")
+ res = dcopRef.send("mySlot", "Hello from dcopsend")
+ if res
+ puts "Sent dcop message"
+ else
+ puts "DCOP send failed"
+ end
+ end
+end
+
+about = KDE::AboutData.new("dcopsend", "DCOPSendTest", "0.1")
+KDE::CmdLineArgs.init(ARGV, about)
+a = KDE::Application.new()
+sender = SenderWidget.new(nil, "senderwidget") { setText 'DCOP Send Test' }
+a.setMainWidget(sender)
+sender.show()
+a.exec()
diff --git a/korundum/rubylib/examples/dcop/dcopsignal.rb b/korundum/rubylib/examples/dcop/dcopsignal.rb
new file mode 100755
index 00000000..07a6dfee
--- /dev/null
+++ b/korundum/rubylib/examples/dcop/dcopsignal.rb
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+
+require 'Korundum'
+
+class SenderWidget < KDE::PushButton
+ k_dcop_signals 'void testEmitSignal(QString)'
+
+ def initialize(parent, name)
+ super
+ Qt::Object::connect(self, SIGNAL('clicked()'), self, SLOT('doit()'))
+ end
+
+ slots 'doit()'
+
+ def doit()
+ emit testEmitSignal("Hello DCOP Slot")
+ end
+end
+
+about = KDE::AboutData.new("dcopsignal", "DCOPSignalTest", "0.1")
+KDE::CmdLineArgs.init(ARGV, about)
+a = KDE::UniqueApplication.new()
+signaltest = SenderWidget.new(nil, "foobar") { setText 'DCOP Signal Test' }
+a.mainWidget = signaltest
+signaltest.show()
+a.exec()
diff --git a/korundum/rubylib/examples/dcop/dcopslot.rb b/korundum/rubylib/examples/dcop/dcopslot.rb
new file mode 100755
index 00000000..e600dfdb
--- /dev/null
+++ b/korundum/rubylib/examples/dcop/dcopslot.rb
@@ -0,0 +1,88 @@
+#!/usr/bin/env ruby
+
+require 'Korundum'
+
+# This is an example of a KDE class that has 'k_dcop' slots declarations, but
+# isn't a subclass of DCOPObject. The following four methods are added to your
+# class:
+#
+# interfaces()
+# functions()
+# connectDCOPSignal()
+# disconnectDCOPSignal()
+#
+# See the call to connectDCOPSignal() towards the end of the code as
+# an example. The name of the dcop object is always the name of the
+# ruby class, and they are Singletons - you can only instantiate one
+# of them.
+#
+# The petshop.rb example in this directory demonstrates more complex
+# use of korundum dcop by subclassing a DCOPObject.
+#
+class MyWidget < KDE::PushButton
+
+ k_dcop 'void mySlot(QString)',
+ 'QPoint getPoint(QString)',
+ 'QMap<QCString,DCOPRef> actionMap()',
+ 'QValueList<DCOPRef> windowList()',
+ 'QValueList<QCString> propertyNames(bool)',
+ 'KURL::List urlList()',
+ 'bool isFoo()',
+ 'bool hasBar()'
+
+ def initialize(parent, name)
+ super
+ end
+
+ def mySlot(greeting)
+ puts "greeting: #{greeting}"
+ end
+
+ def getPoint(msg)
+ puts "message: #{msg}"
+ return Qt::Point.new(50, 100)
+ end
+
+ def actionMap()
+ map = {}
+ map['foobar'] = KDE::DCOPRef.new("myapp", "myobj")
+ return map
+ end
+
+ def windowList()
+ list = []
+ list[0] = KDE::DCOPRef.new("myapp", "myobj")
+ return list
+ end
+
+ def propertyNames(b)
+ return ["thisProperty", "thatProperty"]
+ end
+
+ def urlList()
+ list = []
+ list << KDE::URL.new("http://www.kde.org/") << KDE::URL.new("http://dot.kde.org/")
+ return list
+ end
+
+ def isFoo
+ true
+ end
+
+ def hasBar
+ true
+ end
+end
+
+about = KDE::AboutData.new("dcopslot", "dcopSlotTest", "0.1")
+KDE::CmdLineArgs.init(ARGV, about)
+a = KDE::UniqueApplication.new()
+slottest = MyWidget.new(nil, "mywidget") { setText "DCOP Slot Test" }
+a.mainWidget = slottest
+slottest.caption = a.makeStdCaption("DCOP Slot Test")
+result = slottest.connectDCOPSignal("dcopsignal", "SenderWidget", "testEmitSignal(QString)", "mySlot(QString)", true)
+puts "result: #{result}"
+
+slottest.show()
+# Qt::Internal::setDebug Qt::QtDebugChannel::QTDB_ALL
+a.exec()
diff --git a/korundum/rubylib/examples/dcop/dcoptest.rb b/korundum/rubylib/examples/dcop/dcoptest.rb
new file mode 100755
index 00000000..7d42f76e
--- /dev/null
+++ b/korundum/rubylib/examples/dcop/dcoptest.rb
@@ -0,0 +1,129 @@
+#!/usr/bin/env ruby
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+
+require 'Korundum'
+
+module DCOPTest
+
+ def DCOPTest.getAnyApplication(client, appName)
+ client.registeredApplications().each do |app|
+ if app == appName or app =~ Regexp.new("^#{appName}-")
+ puts app
+ puts
+ objList = client.remoteObjects(app)
+ objList.each do |obj|
+ puts " #{obj}"
+ funcs = client.remoteFunctions(app, obj)
+ funcs.each { |f| puts " #{f}" }
+ end
+ end
+ end
+ end
+
+end
+
+#-------------------- main ------------------------------------------------
+
+description = "A basic application template"
+version = "1.0"
+aboutData = KDE::AboutData.new("testdcopext", "testdcopext",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::Application.new
+dcop = app.dcopClient
+puts "DCOP Application: #{dcop.appId} starting"
+
+# DCOPTest.getAnyApplication(dcop, "konqueror")
+
+puts "--------------------------"
+puts "The DCOPObjects for kicker:"
+
+d = KDE::DCOPRef.new('kicker')
+objs = d.interfaces()
+objs.each { |obj| puts obj }
+
+puts
+puts "get kicker panel size via DCOP"
+res = d.panelSize()
+puts res
+puts "--------------------------"
+
+puts
+puts "Call a method that doesn't exist"
+res = d.junk()
+puts (res.nil? ? "Call failed" : "Call succeeded")
+puts "--------------------------"
+
+puts
+puts
+puts "Start a kwrite instance"
+
+error = ""
+dcopService = ""
+pid = Qt::Integer.new
+
+errcode = KDE::Application.startServiceByDesktopName("kwrite", "", error, dcopService, pid)
+dcopService = "kwrite-" + pid.to_s
+puts "errcode: #{errcode.to_s} error: #{error} dcopService: #{dcopService} pid: #{pid.to_s}"
+puts "--------------------------"
+sleep(2)
+
+o1 = KDE::DCOPRef.new(dcopService, "EditInterface#1")
+#puts "Check if insertLine is a valid function"
+#puts "valid", o1.insertLine.valid
+#puts "--------------------------"
+#puts "insertLine's arg types and names"
+# puts o1.insertLine.argtypes, o1.insertLine.argnames
+puts "--------------------------"
+puts "Insert a line into the kwrite instance we launched"
+
+res = o1.insertLine(0, 'Now is the time for all good men to come to the aid of their party')
+if res.nil?
+ puts "call returns: failed"
+else
+ puts "call returns: #{res.to_s}"
+end
+
+app.exec
+
+
diff --git a/korundum/rubylib/examples/dcop/petshop.rb b/korundum/rubylib/examples/dcop/petshop.rb
new file mode 100755
index 00000000..0cce6277
--- /dev/null
+++ b/korundum/rubylib/examples/dcop/petshop.rb
@@ -0,0 +1,91 @@
+#!/usr/bin/env ruby
+
+# This is an example of a DCOP enabled application written in Ruby, using
+# Korundum. Taken from the PyKDE example_dcopexport.py example which was
+# derived from server.py example in kdebindings written by Torben Weis
+# and Julian Rockey
+
+require 'Korundum'
+
+# An object with DCOP slots needn't be a subclass of DCOPObject, but
+# this DeadParrotObject is one
+
+class DeadParrotObject < KDE::DCOPObject
+
+ k_dcop 'QString getParrotType()', 'void setParrotType(QString)',
+ 'QString squawk()', 'QStringList adjectives()',
+ 'int age()', 'void setAge(int)'
+
+ def initialize(id = 'dead parrot')
+ super(id)
+ @parrot_type = "Norwegian Blue"
+ @age = 7
+ end
+
+ def getParrotType()
+ @parrot_type
+ end
+
+ def setParrotType(parrot_type)
+ @parrot_type = parrot_type
+ end
+
+ def age()
+ @age
+ end
+
+ def setAge(a)
+ @age = a
+ end
+
+ def squawk
+ if rand(2) == 0
+ "This parrot, a #{@parrot_type}, is pining for the fjords"
+ else
+ "This parrot, #{@age} months old, is a #{@parrot_type}"
+ end
+ end
+
+ def adjectives
+ return ["passed on", "is no more", "ceased to be", "expired", "gone to meet his maker",
+ "a stiff", "bereft of life", "rests in peace", "metabolic processes are now history",
+ "off the twig", "kicked the bucket", "shuffled off his mortal coil",
+ "run down his curtain", "joined the bleedin' choir invisible", "THIS IS AN EX-PARROT"]
+ end
+end
+
+description = "A basic application template"
+version = "1.0"
+aboutData = KDE::AboutData.new("petshop", "Dead Parrot Test",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::UniqueApplication.new
+dcop = app.dcopClient
+puts "DCOP Application: #{dcop.appId} starting"
+
+parrot = DeadParrotObject.new
+another_parrot = DeadParrotObject.new('polly')
+
+message = <<EOS
+Run kdcop and look for the 'petshop' application instance.
+
+This program exports the DeadParrotObject object.
+Double-clicking those object's methods will allow you to get or set data.
+
+To end the application, in kdcop choose the MainApplication-Interface
+object and double-click the quit() method.
+EOS
+
+print message
+
+app.exec
+
+
diff --git a/korundum/rubylib/examples/kludgeror.rb b/korundum/rubylib/examples/kludgeror.rb
new file mode 100644
index 00000000..535936b2
--- /dev/null
+++ b/korundum/rubylib/examples/kludgeror.rb
@@ -0,0 +1,138 @@
+#!/usr/bin/env ruby
+# A quick and dirty web browser demonstrating the direct instantiation
+# of a KHTML part. Needless to say: this is NOT a programming paragon :)
+# -- gg.
+# AK - ported to ruby
+
+require 'Korundum'
+
+opt = [ [ "+[url]", "An URL to open at startup.", "" ],
+ [ "z", "A dummy binary option.", "" ],
+ [ "baz <file>", "A long option with arg.", "" ],
+ [ "boz <file>", "Same as above with default value", "default.txt" ],
+ ]
+
+#Qt::Internal::setDebug Qt::QtDebugChannel::QTDB_ALL
+# Qt.debug_level = Qt::DebugLevel::High
+
+about = KDE::AboutData.new("kludgeror", "Kludgeror", "0.1", "A basic web browser")
+KDE::CmdLineArgs::init(ARGV, about)
+KDE::CmdLineArgs::addCmdLineOptions opt
+args = KDE::CmdLineArgs::parsedArgs
+
+a = KDE::Application.new # BUG, application shouldn't be needed at the top, lets fix this...
+
+class PartHolder < Qt::Object
+ signals "setLocBarText(const QString&)"
+ slots "reload()", "goToURL(const QString&)", "back()", "openURL(const KURL&)" # BUG - the slots should be normalize wrt spaces by the lib
+
+ attr_accessor :part, :history
+
+ def initialize part, *k
+ super(*k)
+ @part = part
+ @history = []
+ end
+
+ def openURL url
+ @part.openURL url
+ # BUG - a non existant slot emit says horrible things, nothing interesting for user.. very confusing
+ # BUG - signal emitting is *very* wrong
+ # emit setLocBarText(url.url)
+ @history.unshift url unless url == @history[0]
+ end
+
+ def reload
+ @part.openURL @part.url
+ end
+
+ def goToURL(url)
+ url = "http://#{url}" unless url =~ /^\w*:/
+ openURL KDE::URL.new(url)
+ end
+
+ def back
+ return unless @history.length > 1
+ @history.shift
+ openURL @history[0] unless @history.empty?
+ end
+end
+
+LOC_ED = 322
+ERASE_B = 323
+BACK_B = 324
+
+url = (args.count > 1) ? args.url(0) : KDE::URL.new("http://loki:8080/xml/index.xml")
+
+puts "Dummy z option activated." if args.isSet "z"
+puts "Dummy baz option has value: #{args.getOption "baz"}" if args.isSet "baz"
+# puts "Dummy boz option has value: #{args.getOption "boz"}" if args.isSet "boz" # B0rked?
+
+toplevel = KDE::MainWindow.new
+doc = KDE::HTMLPart.new toplevel, nil, toplevel, nil, 1
+# doc = KDE::HTMLPart.new toplevel, nil, toplevel, nil, 1 # KDE::HTMLPart::BrowserViewGUI
+ph = PartHolder.new doc
+
+Qt::Object::connect doc.browserExtension, SIGNAL("openURLRequest(const KURL&, const KParts::URLArgs&)"),
+ ph, SLOT("openURL(const KURL&)") # BUG this slot must be screwing up wrt marshalling?
+
+ph.openURL url
+toplevel.setCentralWidget doc.widget
+toplevel.resize 700, 500
+
+begin
+ d, viewMenu, fileMenu, locBar, e = nil
+ d = doc.domDocument
+ viewMenu = d.documentElement.firstChild.childNodes.item(2).toElement
+ e = d.createElement "action"
+ e.setAttribute "name", "debugRenderTree"
+ viewMenu.appendChild e
+ e = d.createElement "action"
+ e.setAttribute "name", "debugDOMTree"
+ viewMenu.appendChild e
+ fileMenu = d.documentElement.firstChild.firstChild.toElement
+ fileMenu.appendChild d.createElement("separator")
+ e = d.createElement "action"
+ e.setAttribute "name", "exit"
+ fileMenu.appendChild e
+ locBar = d.createElement "toolbar"
+ locBar.setAttribute "name", "locationBar"
+ e = d.createElement "action"
+ e.setAttribute "name", "reload"
+ locBar.appendChild e
+ d.documentElement.appendChild locBar
+end
+
+a1 = KDE::Action.new( "Reload", "reload", KDE::Shortcut.new(Qt::Key_F5), ph, SLOT("reload()"), doc.actionCollection, "reload" )
+a2 = KDE::Action.new( "Exit", "exit", KDE::Shortcut.new(0), a, SLOT("quit()"), doc.actionCollection, "exit" )
+
+toplevel.guiFactory.addClient doc
+
+locBar = toplevel.toolBar("locationBar");
+locBar.insertButton "back", BACK_B, SIGNAL("clicked()"),
+ ph, SLOT("back()"), true, "Go back"
+locBar.insertLined url.url, LOC_ED, SIGNAL("returnPressed(const QString&)"), ph, SLOT("goToURL(const QString&)"), true, "Location"
+locBar.insertButton "locationbar_erase", ERASE_B, SIGNAL("clicked()"),
+ locBar.getLined(LOC_ED), SLOT("clear()"), true, "Erase the location bar's content", 2
+locBar.setItemAutoSized LOC_ED, true
+locBar.getLined(LOC_ED).createPopupMenu
+comp = locBar.getLined(LOC_ED).completionObject
+comp.setCompletionMode KDE::GlobalSettings::CompletionPopupAuto
+
+Qt::Object::connect(locBar.getLined(LOC_ED), SIGNAL("returnPressed(const QString&)"),
+ comp, SLOT("addItem(const QString&)"))
+Qt::Object::connect(ph, SIGNAL("setLocBarText(const QString&)"), # BUG - once again...
+ locBar.getLined(LOC_ED), SLOT("setText(const QString&)"))
+
+doc.setJScriptEnabled true
+doc.setJavaEnabled true
+doc.setPluginsEnabled true
+doc.setURLCursor Qt::Cursor.new(Qt::PointingHandCursor)
+
+a.setTopWidget doc.widget
+
+Qt::Object::connect doc, SIGNAL("setWindowCaption(const QString&)"),
+ doc.widget.topLevelWidget, SLOT("setCaption(const QString&)")
+toplevel.show
+
+a.exec
diff --git a/korundum/rubylib/examples/kurldemo.rb b/korundum/rubylib/examples/kurldemo.rb
new file mode 100644
index 00000000..04fb9bce
--- /dev/null
+++ b/korundum/rubylib/examples/kurldemo.rb
@@ -0,0 +1,110 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+require 'Korundum'
+
+class MainWin < KDE::MainWindow
+ def initialize(*args)
+ super
+
+ @urls = ["http://slashdot.org", "http://www.kde.org", "http://www.riverbankcomputing.co.uk", "http://yahoo.com"]
+ setGeometry(0, 0, 400, 600)
+
+ edit = KDE::TextEdit.new(self)
+ setCentralWidget(edit)
+
+ edit.insert("KURL Demo\n")
+ edit.insert("\nAdding these urls:\n\n")
+ @urls.each do |url|
+ edit.insert(" #{url}\n")
+ end
+
+ edit.insert("\nCreating KURLs (iterating to print):\n\n")
+ urlList = []
+ @urls.each do |url|
+ urlList << KDE::URL.new(url)
+ end
+
+ urlList.each do |url|
+ edit.insert(" #{url.url()}\n")
+ end
+
+ edit.insert("\nFirst url -- urlList [0]:\n\n")
+ edit.insert(" #{urlList[0].to_s}\n")
+ edit.insert(" #{urlList[0].url()}\n")
+
+ edit.insert("\nLast url -- urlList [-1]:\n\n")
+ edit.insert(" #{urlList[-1].to_s}\n")
+ edit.insert(" #{urlList[-1].url()}\n")
+
+ edit.insert("\nMiddle urls -- urlList [2,4]:\n\n")
+ ulist = urlList[2,4]
+ ulist.each do |url|
+ edit.insert(" #{url.to_s}\n")
+ edit.insert(" #{url.url()}\n")
+ end
+
+ edit.insert("\nLength of urlList -- len (urlList):\n\n")
+ edit.insert(" Length = #{urlList.length}\n")
+
+ edit.insert("\nurl in urlList? -- KURL (\"http://yahoo.com\") in urlList\n\n")
+ edit.insert(" KDE::URL.new(\"http://yahoo.com\") in urlList = ")
+ tmp = KDE::URL.new("http://yahoo.com")
+ urlList.each do |url|
+ if url.url == tmp.url
+ edit.insert("true")
+ end
+ end
+ end
+end
+
+
+#-------------------- main ------------------------------------------------
+
+description = "A basic application template"
+version = "1.0"
+aboutData = KDE::AboutData.new("", "",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show()
+app.exec()
diff --git a/korundum/rubylib/examples/menudemo.rb b/korundum/rubylib/examples/menudemo.rb
new file mode 100644
index 00000000..d5762ecd
--- /dev/null
+++ b/korundum/rubylib/examples/menudemo.rb
@@ -0,0 +1,310 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+This template constructs an application with menus, toolbar and statusbar.
+It uses KDE classes and methods that simplify the task of building and
+operating a GUI. It is recommended that this approach be used, rather
+than the primitive approach in menuapp1.py
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+require 'Korundum'
+include KDE
+
+class MainWin < MainWindow
+
+ slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()',
+ 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()',
+ 'slotSpecial()', 'slotToggle2()', 'slotZoomIn()', 'slotZoomOut()'
+
+ STATUSBAR_LEFT = 1
+ STATUSBAR_MIDDLE = 2
+ STATUSBAR_RIGHT = 3
+
+ def initialize(*args)
+ super
+
+ initActions()
+ initMenus()
+ initToolBar()
+ initStatusBar()
+
+ @saveAction.setEnabled(false)
+ @saveAsAction.setEnabled(false)
+ end
+
+ def initActions()
+ # "File" menu items
+ @newAction = StdAction.openNew(self, SLOT('slotNew()'), actionCollection())
+ @openAction = StdAction.open(self, SLOT('slotOpen()'), actionCollection())
+ @saveAction = StdAction.save(self, SLOT('slotSave()'), actionCollection())
+ @saveAsAction = StdAction.saveAs(self, SLOT('slotSaveAs()'), actionCollection())
+ @printAction = StdAction.print(self, SLOT('slotPrint()'), actionCollection())
+ @quitAction = StdAction.quit(self, SLOT('slotQuit()'), actionCollection())
+
+ # "Edit" menu items
+ @undoAction = StdAction.undo(self, SLOT('slotUndo()'), actionCollection())
+ @redoAction = StdAction.redo(self, SLOT('slotRedo()'), actionCollection())
+ @cutAction = StdAction.cut(self, SLOT('slotCut()'), actionCollection())
+ @copyAction = StdAction.copy(self, SLOT('slotCopy()'), actionCollection())
+ @pasteAction = StdAction.paste(self, SLOT('slotPaste()'), actionCollection())
+ @findAction = StdAction.find(self, SLOT('slotFind()'), actionCollection())
+ @findNextAction = StdAction.findNext(self, SLOT('slotFindNext()'), actionCollection())
+ @replaceAction = StdAction.replace(self, SLOT('slotReplace()'), actionCollection())
+ @specialAction = Action.new(i18n("Special"), Shortcut.new(), self, SLOT('slotSpecial()'), actionCollection(), "special")
+
+ # Demo menu items
+
+ # KToggleAction has an isChecked member and emits the "toggle" signal
+ @toggle1Action = ToggleAction.new("Toggle 1")
+ @toggle2Action = ToggleAction.new("Toggle 2", Shortcut.new(), self, SLOT('slotToggle2()'), nil)
+
+ # A separator - create once/use everywhere
+ @separateAction = ActionSeparator.new()
+
+ # Font stuff in menus or toolbar
+ @fontAction = FontAction.new("Font")
+ @fontSizeAction = FontSizeAction.new("Font Size")
+
+ # Need to assign an icon to actionMenu below
+ icons = IconLoader.new()
+ iconSet = Qt::IconSet.new(icons.loadIcon("viewmag", Icon::Toolbar))
+
+ # Nested menus using KActions (also nested on toolbar)
+ @actionMenu = ActionMenu.new("Action Menu")
+ @actionMenu.setIconSet(iconSet)
+ @actionMenu.insert(StdAction.zoomIn(self, SLOT('slotZoomIn()'), actionCollection()))
+ @actionMenu.insert(StdAction.zoomOut(self, SLOT('slotZoomOut()'), actionCollection()))
+
+ # Doesn't work in KDE 2.1.1
+# radio1Action = KRadioAction ("Radio 1")
+# radio1Action.setExclusiveGroup ("Radio")
+# radio2Action = KRadioAction ("Radio 2")
+# radio2Action.setExclusiveGroup ("Radio")
+# radio3Action = KRadioAction ("Radio 3")
+# radio3Action.setExclusiveGroup ("Radio")
+ end
+
+ def initMenus()
+ fileMenu = Qt::PopupMenu.new(self)
+ @newAction.plug(fileMenu)
+ @openAction.plug(fileMenu)
+ fileMenu.insertSeparator()
+ @saveAction.plug(fileMenu)
+ @saveAsAction.plug(fileMenu)
+ fileMenu.insertSeparator()
+ @printAction.plug(fileMenu)
+ fileMenu.insertSeparator()
+ @quitAction.plug(fileMenu)
+ menuBar().insertItem(i18n("&File"), fileMenu)
+
+ editMenu = Qt::PopupMenu.new(self)
+ @undoAction.plug(editMenu)
+ @redoAction.plug(editMenu)
+ editMenu.insertSeparator()
+ @cutAction.plug(editMenu)
+ @copyAction.plug(editMenu)
+ @pasteAction.plug(editMenu)
+ editMenu.insertSeparator()
+ @findAction.plug(editMenu)
+ @findNextAction.plug(editMenu)
+ @replaceAction.plug(editMenu)
+ editMenu.insertSeparator()
+ @specialAction.plug(editMenu)
+ menuBar().insertItem(i18n("&Edit"), editMenu)
+
+ demoMenu = Qt::PopupMenu.new(self)
+ @toggle1Action.plug(demoMenu)
+ @toggle2Action.plug(demoMenu)
+ @separateAction.plug(demoMenu)
+ @fontAction.plug(demoMenu)
+ @fontSizeAction.plug(demoMenu)
+ @actionMenu.plug(demoMenu)
+# radio1Action.plug(demoMenu)
+# radio2Action.plug(demoMenu)
+# radio3Action.plug(demoMenu)
+ menuBar().insertItem(i18n("&Demo"), demoMenu)
+
+ # This really belongs in Kicker, not here,
+ # but it actually works
+ # wlMenu = WindowListMenu.new(self)
+ # wlMenu.init()
+ # menuBar().insertItem(i18n("&WindowListMenu"), wlMenu)
+
+ helpMenu = helpMenu("")
+ menuBar().insertItem(i18n("&Help"), helpMenu)
+ end
+
+ def initToolBar()
+ @newAction.plug(toolBar())
+ @openAction.plug(toolBar())
+ @saveAction.plug(toolBar())
+ @cutAction.plug(toolBar())
+ @copyAction.plug(toolBar())
+ @pasteAction.plug(toolBar())
+
+ @separateAction.plug(toolBar())
+ @separateAction.plug(toolBar())
+ @separateAction.plug(toolBar())
+
+ @fontAction.plug(toolBar())
+ @separateAction.plug(toolBar())
+ @fontAction.setComboWidth(150)
+
+ @fontSizeAction.plug(toolBar())
+ @fontSizeAction.setComboWidth(75)
+
+ @separateAction.plug(toolBar())
+
+ # This works, but you have to hold down the
+ # button in the toolbar and wait a bit
+ @actionMenu.plug(toolBar())
+ # This appears to do nothing
+ @actionMenu.setDelayed(false)
+
+ # Need this to keep the font comboboxes from stretching
+ # to the full width of the toolbar when the window is
+ # maximized (comment out the next two lines to see
+ # what happens)
+ stretchlbl = Qt::Label.new("", toolBar())
+ toolBar().setStretchableWidget(stretchlbl)
+
+# toolBar().setHorizontalStretchable(false)
+ end
+
+ def initStatusBar()
+ statusBar().insertItem("", STATUSBAR_LEFT, 1000, true)
+ statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true)
+ statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true)
+ end
+
+#-------------------- slots -----------------------------------------------
+
+ def slotNew(id = -1)
+ notImpl("New")
+ end
+
+ def slotOpen(id = -1)
+ notImpl("Open")
+ end
+
+ def slotSave(id = -1)
+ notImpl("Save")
+ end
+
+ def slotSaveAs()
+ notImpl("Save As")
+ end
+
+ def slotPrint()
+ notImpl("Print")
+ end
+
+ def slotQuit()
+ notImpl("Quit")
+ end
+
+ def slotUndo()
+ notImpl("Undo")
+ end
+
+ def slotRedo()
+ notImpl("Redo")
+ end
+
+ def slotCut (id = -1)
+ notImpl("Cut")
+ end
+
+ def slotCopy(id = -1)
+ notImpl("Copy")
+ end
+
+ def slotPaste(id = -1)
+ notImpl("Paste")
+ end
+
+ def slotFind()
+ notImpl("Find")
+ end
+
+ def slotFindNext()
+ notImpl("Find Next")
+ end
+
+ def slotReplace()
+ notImpl("Replace")
+ end
+
+ def slotSpecial()
+ notImpl("Special")
+ end
+
+ def slotToggle2()
+ notImpl("Toggle")
+ end
+
+ def slotZoomIn()
+ notImpl("Zoom In")
+ end
+
+ def slotZoomOut()
+ notImpl("Zoom Out")
+ end
+
+ def notImpl(item)
+ statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT)
+ MessageBox.error(self, "#{item} not implemented", "Not Implemented")
+ statusBar().changeItem("", STATUSBAR_LEFT)
+ end
+end
+
+#-------------------- main ------------------------------------------------
+
+description = "A basic application template"
+version = "1.0"
+aboutData = AboutData.new("menudemo", "MenuDemo",
+ version, description, AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+CmdLineArgs.init(ARGV, aboutData)
+
+CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show()
+app.exec()
diff --git a/korundum/rubylib/examples/mimetype.rb b/korundum/rubylib/examples/mimetype.rb
new file mode 100644
index 00000000..9f6db85f
--- /dev/null
+++ b/korundum/rubylib/examples/mimetype.rb
@@ -0,0 +1,286 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+This program tests/demos some of the KSharedPtr related classes and
+methods (KMimeType, KService, etc). It generally tests the *::List
+methods for these classes (eg KService::List) since that also tests
+the *::Ptr mapped type code (eg KService::Ptr) at the same time.
+
+This version is suitable for KDE >= 3.0.0 (some methods not available
+in earlier versions)
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+require 'Korundum'
+include KDE
+
+class MainWin < MainWindow
+ def initialize(*k)
+ super
+
+ tabctl = KDE::TabCtl.new(self)
+ setGeometry(0, 0, 600, 400)
+ tabctl.setGeometry(10, 10, 550, 380)
+
+ tabctl.addTab(KMimeTypeTab.new(tabctl), "KMimeType")
+ tabctl.addTab(KServiceTab.new(tabctl), "KService")
+ tabctl.addTab(KSycocaEntryTab.new(tabctl), "KSycocaEntry")
+ tabctl.addTab(KServiceTypeTab.new(tabctl), "KServiceType")
+ tabctl.addTab(OfferListTab.new(tabctl), "OfferList")
+
+ tabctl.show()
+ end
+end
+
+
+class OfferListTab < Qt::Widget
+ def initialize(parent, name = "")
+ super(parent, name)
+
+ setGeometry(0, 0, 500, 370)
+ lvLbl = Qt::Label.new("Offers - text/html", self)
+ lvLbl.setGeometry(10, 10, 150, 20)
+
+ lv = Qt::ListView.new(self)
+ lv.setSorting(-1)
+ lv.addColumn("type", 75)
+ lv.addColumn("name", 100)
+ lv.addColumn("exec", 200)
+ lv.addColumn("library", 100)
+ lv.setGeometry(10, 30, 500, 300)
+ lv.setAllColumnsShowFocus(true)
+
+ # insert list items in reverse order
+
+ pref = KDE::ServiceTypeProfile.preferredService("Application", "image/jpeg")
+ Qt::ListViewItem.new(lv, pref.type(), pref.name(), pref.exec(), pref.library())
+ Qt::ListViewItem.new(lv, "Preferred", "--------", "", "")
+ Qt::ListViewItem.new(lv, "", "", "", "")
+
+ trader = KDE::Trader.self()
+ slist = trader.query("image/jpeg", "Type == 'Application'")
+# print "KTrader returned:" + slist
+ slist.each do |s|
+ lvi = Qt::ListViewItem.new(lv, s.type(), s.name(), s.exec(), s.library())
+ end
+
+ lv.show()
+ end
+end
+
+class KServiceTypeTab < Qt::Widget
+ def initialize(parent, name = "")
+ super(parent, name)
+
+ setGeometry(0, 0, 500, 370)
+ lvLbl = Qt::Label.new("All Service Types", self)
+ lvLbl.setGeometry(10, 10, 250, 20)
+
+ lv = Qt::ListView.new(self)
+ lv.addColumn("name", 150)
+ lv.addColumn("desktopEntryPath", 300)
+ lv.setGeometry(10, 30, 500, 300)
+ lv.setAllColumnsShowFocus(true)
+
+ slist = KDE::ServiceType.allServiceTypes()
+
+ slist.each do |s|
+ lvi = Qt::ListViewItem.new(lv, s.name(), s.desktopEntryPath())
+ end
+
+ lv.show()
+ end
+end
+
+class KSycocaEntryTab < Qt::Widget
+ def initialize(parent, name = "")
+ super(parent, name)
+
+ grp = KDE::ServiceGroup.baseGroup("screensavers")
+ if grp.nil?
+ return
+ end
+ setGeometry(0, 0, 500, 370)
+ lvLbl = Qt::Label.new("Entries - 'screensavers': " + grp.name(), self)
+ lvLbl.setGeometry(10, 10, 250, 20)
+
+ lv = Qt::ListView.new(self)
+ lv.addColumn("name", 150)
+ lv.addColumn("entryPath", 300)
+ lv.setGeometry(10, 30, 500, 300)
+ lv.setAllColumnsShowFocus(true)
+
+ slist = grp.entries(false, false)
+
+ slist.each do |s|
+ lvi = Qt::ListViewItem.new(lv, s.name(), s.entryPath())
+ end
+
+ lv.show()
+ end
+end
+
+class KServiceTab < Qt::Widget
+ def initialize(parent, name = "")
+ super(parent, name)
+
+ setGeometry(0, 0, 500, 370)
+ lvLbl = Qt::Label.new("All Services", self)
+ lvLbl.setGeometry(10, 10, 150, 20)
+
+ lv = Qt::ListView.new(self)
+ lv.addColumn("type", 75)
+ lv.addColumn("name", 100)
+ lv.addColumn("exec", 200)
+ lv.addColumn("library", 100)
+ lv.setGeometry(10, 30, 500, 300)
+ lv.setAllColumnsShowFocus(true)
+
+ slist = KDE::Service.allServices()
+ slist.each do |s|
+ lvi = Qt::ListViewItem.new(lv, s.type(), s.name(), s.exec(), s.library())
+ end
+
+ lv.show()
+ end
+end
+
+# svc = KService.serviceByDesktopName ("kcookiejar")
+# print svc
+# print svc.type_ ()
+# print svc.name ().latin1 ()
+# print svc.exec_ ().latin1 ()
+# print svc.library ()
+
+
+class KMimeTypeTab < Qt::Widget
+ def initialize(parent, name = "")
+ super(parent, name)
+
+ setGeometry(0, 0, 500, 370)
+ lbLbl = Qt::Label.new("All Mimetypes", self)
+ lbLbl.setGeometry(10, 10, 150, 20)
+ lb = KDE::ListBox.new(self)
+ lb.setGeometry(10, 30, 200, 300)
+ mlist = KDE::MimeType.allMimeTypes()
+ lblist = []
+ mlist.each do |mt|
+ lblist << mt.name()
+ end
+
+ lblist.sort()
+ lb.insertStringList(lblist)
+
+ lb.show()
+
+ x = 250
+ y = 10
+
+ mt = KDE::MimeType.mimeType("text/plain")
+ mtlbl = Qt::Label.new("KMimeType.mimeType('text/plain')", self)
+ mtlbl.setGeometry(x, y, 250, 20)
+ mtnamelbl = Qt::Label.new("name", self)
+ mtnamelbl.setGeometry(x + 15, y + 20, 100, 20)
+ mtname = Qt::Label.new(mt.name(), self)
+ mtname.setGeometry(x + 120, y + 20, 100, 20)
+ mtdesklbl = Qt::Label.new("desktopEntryPath", self)
+ mtdesklbl.setGeometry(x + 15, y + 40, 100, 20)
+ mtdesk = Qt::Label.new(mt.desktopEntryPath(), self)
+ mtdesk.setGeometry(x + 120, y + 40, 150, 20)
+
+ y = y + 80
+
+ fp = KDE::MimeType.findByPath("mimetype.rb")
+ fplbl = Qt::Label.new("KDE::MimeType.findByPath('mimetype.rb')", self)
+ fplbl.setGeometry(x, y, 250, 20)
+ fpnamelbl = Qt::Label.new("name", self)
+ fpnamelbl.setGeometry(x + 15, y + 20, 100, 20)
+ fpname = Qt::Label.new(fp.name(), self)
+ fpname.setGeometry(x + 120, y + 20, 100, 20)
+ fpdesklbl = Qt::Label.new("desktopEntryPath", self)
+ fpdesklbl.setGeometry(x + 15, y + 40, 100, 20)
+ fpdesk = Qt::Label.new(fp.desktopEntryPath(), self)
+ fpdesk.setGeometry(x + 120, y + 40, 150, 20)
+
+ y = y + 80
+
+ fu = KDE::MimeType.findByURL(KDE::URL.new("file://mimetype.rb"))
+ fulbl = Qt::Label.new("KDE::MimeType.findByURL('file://mimetype.rb')", self)
+ fulbl.setGeometry(x, y, 250, 20)
+ funamelbl = Qt::Label.new("name", self)
+ funamelbl.setGeometry(x + 15, y + 20, 100, 20)
+ funame = Qt::Label.new(fu.name(), self)
+ funame.setGeometry(x + 120, y + 20, 100, 20)
+ fudesklbl = Qt::Label.new("desktopEntryPath", self)
+ fudesklbl.setGeometry(x + 15, y + 40, 100, 20)
+ fudesk = Qt::Label.new(fu.desktopEntryPath(), self)
+ fudesk.setGeometry(x + 120, y + 40, 150, 20)
+
+ y = y + 80
+
+ acc = Qt::Integer.new(0) # Create a mutable integer value to pass as an 'int*' arg
+ fc = KDE::MimeType.findByFileContent("mimetype.rb", acc)
+ fclbl = Qt::Label.new("KDE::MimeType.findByFileContent('mimetype.rb')", self)
+ fclbl.setGeometry(x, y, 250, 20)
+ fcnamelbl = Qt::Label.new("name", self)
+ fcnamelbl.setGeometry(x + 15, y + 20, 100, 20)
+ fcname = Qt::Label.new(fc.name(), self)
+ fcname.setGeometry(x + 120, y + 20, 100, 20)
+ fcdesklbl = Qt::Label.new("desktopEntryPath", self)
+ fcdesklbl.setGeometry(x + 15, y + 40, 100, 20)
+ fcdesk = Qt::Label.new(fc.desktopEntryPath(), self)
+ fcdesk.setGeometry(x + 120, y + 40, 100, 20)
+ fcacclbl = Qt::Label.new("accuracy", self)
+ fcacclbl.setGeometry(x + 15, y + 60, 100, 20)
+ fcacc = Qt::Label.new(acc.to_s, self)
+ fcacc.setGeometry(x + 120, y + 60, 150, 20)
+ end
+end
+
+
+#-------------------- main ------------------------------------------------
+
+description = "Test/demo KSharedPtr related methods/classes"
+version = "1.0"
+aboutData = KDE::AboutData.new("mimetype", "MimeType",
+ version, description, KDE::AboutData.License_GPL,
+ "(C) 2003 Jim Bublitz")
+
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show()
+app.exec()
diff --git a/korundum/rubylib/examples/rbKHTMLPart.rb b/korundum/rubylib/examples/rbKHTMLPart.rb
new file mode 100644
index 00000000..e3beb927
--- /dev/null
+++ b/korundum/rubylib/examples/rbKHTMLPart.rb
@@ -0,0 +1,217 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+#
+# pyParts.py (C) 2002 Jim Bublitz <jbublitz@nwinternet.com>
+#
+
+=begin
+
+This is an extemely simple and crude example of using
+a KHTMLPart - I put it together mostly to make sure
+the openURL method worked correctly after some modifications
+done in KParts::ReadOnlyPart. It took exactly four lines
+added to a basic Korundum app framework to display a URL
+via the 'net:
+
+ w = KDE::HTMLPart.new(self, "HTMLPart", self)
+ w.openURL(KDE::URL.new("http://www.kde.org"))
+ w.view().setGeometry(30, 55, 500, 400)
+ w.show()
+
+You can play around with the commented out lines or add
+additional code to make this do something useful. The
+.rc for khtnmlpart (sorry, I never looked it up), doesn't
+seem to provide much help. Also, to follow links, you
+probably need to connect some signals to slots. I
+haven't tried it, but this should work with a plain
+KMainWindow or other widget too.
+
+The KDE website also incorporates gifs, jpegs, and
+I believe CSS too. Playing around with some other
+sites, it appears the font defaults could use some
+improvement.
+
+NOTE!!! For this to work, you (obviously) need to have
+a route to the internet established or specify a local
+URL - PyKDE/KDE will take care of everything else.
+
+Perceptive users will notice the KHTMLPart code is
+lifted from the KDE classref.
+
+=end
+
+require 'Korundum'
+
+# Note that we use KParts.MainWindow, not KMainWindow as the superclass
+# (KParts.MainWindow subclasses KMainWindow). Also, be sure the 'apply'
+# clause references KParts.MainWindow - it's a hard bug to track down
+# if it doesn't.
+
+class RbPartsMW < KParts::MainWindow
+ slots 'close()', 'optionsShowToolbar()', 'optionsShowStatusbar()', 'optionsConfigureKeys()',
+ 'optionsConfigureToolbars()'
+
+ TOOLBAR_EXIT = 0
+ TOOLBAR_OPEN = 1
+
+ def initialize(*k)
+ super
+
+ # Create the actions for our menu/toolbar to use
+ # Keep in mind that the part loaded will provide its
+ # own menu/toolbar entries
+
+ # check out KParts.MainWindow's ancestry to see where
+ # some of this and later stuff (like self.actionCollection () )
+ # comes from
+
+ quitAction = KDE::StdAction.quit(self, SLOT('close()'), actionCollection())
+
+ createStandardStatusBarAction()
+# @m_toolbarAction = KDE::StdAction.showToolbar(self, SLOT('optionsShowToolbar()'), actionCollection())
+ @m_statusbarAction = KDE::StdAction.showStatusbar(self, SLOT('optionsShowStatusbar()'), actionCollection())
+
+ KDE::StdAction.keyBindings(self, SLOT('optionsConfigureKeys()'), actionCollection())
+ KDE::StdAction.configureToolbars(self, SLOT('optionsConfigureToolbars()'), actionCollection())
+
+ path = Dir.getwd() + '/'
+ setGeometry(0, 0, 600, 500)
+
+ # point to our XML file
+ setXMLFile(path + "rbParts.rc", false)
+
+ # The next few lines are all that's necessary to
+ # create a web browser (of course you have to edit
+ # this file to change url's)
+
+ w = KDE::HTMLPart.new(self, "HTMLPart", self)
+ w.openURL(KDE::URL.new("http://www.kde.org"))
+
+ w.view().setGeometry(30, 55, 500, 400)
+
+
+# self.v = KHTMLView (self.w, self)
+
+# self.setCentralWidget (self.v)
+
+# self.createGUI (self.w)
+
+ w.show()
+ end
+
+
+
+
+ # slots for our actions
+ def optionsShowToolbar()
+ if @m_toolbarAction.isChecked()
+ toolBar().show()
+ else
+ toolBar().hide()
+ end
+ end
+
+ def optionsShowStatusbar()
+ if @m_statusbarAction.isChecked()
+ statusBar().show()
+ else
+ statusBar().hide()
+ end
+ end
+
+
+ def optionsConfigureKeys()
+ KDE::KeyDialog.configureActionKeys(actionCollection(), xmlFile())
+ end
+
+
+ def optionsConfigureToolbars()
+ dlg = KDE::EditToolbar.new(actionCollection(), xmlFile())
+ if dlg.exec()
+ createGUI(self)
+ end
+ end
+
+
+ # some boilerplate left over from pyKLess/KLess
+ def queryClose()
+ res = KDE::MessageBox.warningYesNoCancel(self,
+ i18n("Save changes to Document?<br>(Does not make sense, we know, but it is just a programming example :-)"))
+ if res == KDE::MessageBox::Yes
+ #// save document here. If saving fails, return FALSE
+ return true
+
+ elsif res == KDE::MessageBox::No
+ return true
+
+ else #// cancel
+ return false
+ end
+ end
+
+ def queryExit()
+ #// this slot is invoked in addition when the *last* window is going
+ #// to be closed. We could do some final cleanup here.
+ return true #// accept
+ end
+
+ # I'm not sure the session mgmt stuff here works
+
+ # Session management: save data
+ def saveProperties(config)
+ # This is provided just as an example.
+ # It is generally not so good to save the raw contents of an application
+ # in its configuration file (as this example does).
+ # It is preferable to save the contents in a file on the application's
+ # data zone and save an URL to it in the configuration resource.
+ config.writeEntry("text", edit.text())
+ end
+
+
+ # Session management: read data again
+ def readProperties(config)
+ # See above
+ edit.setText(config.readEntry("text"))
+ end
+end
+
+
+#------------- main ----------------------------
+
+# A Human readable description of your program
+description = "KHTMLPart - simple example"
+# The version
+version = "0.1"
+
+# stuff for the "About" menu
+aboutData = KDE::AboutData.new("rbKHTMLPart", "rbHTMLPart",
+ version, description, KDE::AboutData::License_GPL,
+ "(c) 2002, Jim Bublitz")
+
+aboutData.addAuthor("Jim Bublitz", "Example for PyKDE", "jbublitz@nwinternet.com")
+aboutData.addAuthor('Richard Dale', 'Example for Korundum', 'Richard_Dale@tipitina.demon.co.uk')
+
+# This MUST go here (before KApplication () is called)
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+app = KDE::Application.new()
+
+if app.isRestored()
+ KDE::MainWindow.kRestoreMainWindows(RbPartsMW)
+else
+ # no session management: just create one window
+ # this is our KParts::MainWindow derived class
+ parts = RbPartsMW.new(nil, "rbParts")
+ if ARGV.length > 1
+ # read kcmdlineargs.h for the full unabridged instructions
+ # on using KCmdLineArgs, it's pretty confusing at first, but it works
+ # This is pretty useless in this program - you might want to
+ # expand this in your app (to load a file, etc)
+ args = KDE::CmdLineArgs.parsedArgs()
+ end
+end
+
+parts.show()
+app.exec()
diff --git a/korundum/rubylib/examples/rbtestimage.png b/korundum/rubylib/examples/rbtestimage.png
new file mode 100644
index 00000000..550371b1
--- /dev/null
+++ b/korundum/rubylib/examples/rbtestimage.png
Binary files differ
diff --git a/korundum/rubylib/examples/systray.rb b/korundum/rubylib/examples/systray.rb
new file mode 100644
index 00000000..85b27366
--- /dev/null
+++ b/korundum/rubylib/examples/systray.rb
@@ -0,0 +1,66 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+require 'Korundum'
+
+class MainWin < KDE::MainWindow
+ def initialize(*args)
+ super
+ end
+end
+
+#-------------------- main ------------------------------------------------
+
+appName = "template"
+
+aboutData = KDE::AboutData.new("systry", "Systray test",\
+ "0.1", "Systray test", KDE::AboutData::License_GPL,\
+ "(c) 2002, Jim Bublitz")
+
+aboutData.addAuthor('Jim Bublitz', 'Example for PyKDE', 'jbublitz@nwinternet.com')
+aboutData.addAuthor('Richard Dale', 'For Korundum', 'Richard_Dale@tipitina.demon.co.uk')
+
+# This MUST go here (before KApplication () is called)
+KDE::CmdLineArgs.init(ARGV, aboutData)
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+icons = KDE::IconLoader.new()
+
+systray = KDE::SystemTray.new(mainWindow)
+systray.setPixmap(icons.loadIcon("stop", 0))
+systray.show()
+
+#mainWindow.show()
+app.exec()
+
+
diff --git a/korundum/rubylib/examples/uikmdi.rb b/korundum/rubylib/examples/uikmdi.rb
new file mode 100644
index 00000000..df7d0e1d
--- /dev/null
+++ b/korundum/rubylib/examples/uikmdi.rb
@@ -0,0 +1,187 @@
+
+=begin
+This is a ruby version of Jim Bublitz's python original. The ruby behaviour
+is 'crash for crash' identical - so the the problems described below are
+related to KMDI, and not the bindings.
+=end
+
+=begin
+A rough Python translation of the ideas presented in this KMDI tutorial:
+
+ http://web.tiscali.it/andreabergia/kmditutorial.html
+
+What does work:
+
+ IDEAlMode - yay!
+
+ Adding and closing child views
+
+ Two-way syncing between a tool widget and a matching child view
+
+All is not rosy, however:
+
+ Instances of the KmdiExample maintain a dictionary of child views. Values
+ cannot be deleted from this dictionary during a window close (causes an
+ immediate segfault).
+
+ Child views created after initialization aren't numbered correctly; given
+ the first problem, it's harder to do this than it's really worth.
+
+ The example segfaults at shutdown if the tool (on the left) is is open but
+ is not in overlap-mode.
+
+=end
+
+require 'Korundum'
+include KDE
+
+class KmdiExample < KDE::MdiMainFrm
+
+ slots 'closeChild(KMdiChildView*)',
+ 'syncFromChildView(KMdiChildView*)',
+ 'syncFromMainTool(QListBoxItem*)',
+ 'activatedMessage(KMdiChildView*)',
+ 'newView()', 'close()', 'closeActiveChild()'
+
+ def getIcon(name, group=Icon::NoGroup, size=Icon::SizeSmall)
+ # returns a kde icon by name
+ return Global.instance().iconLoader().loadIcon(name, group, size)
+ end
+
+ def initialize(parent=nil)
+ super(parent, 'KmdiExample', Mdi::IDEAlMode)
+
+ @viewIcons = ['network', 'email', 'stop', 'back', 'forward']
+ @toolIcons = ['view_icon', 'configure']
+
+ openNewAction = StdAction.openNew(self, SLOT('newView()'), actionCollection())
+ quitAction = StdAction.quit(self, SLOT('close()'), actionCollection())
+ closeAction = StdAction.close(self, SLOT('closeActiveChild()'), actionCollection())
+
+ uifilebase = Dir.getwd + '/uikmdi.rc'
+ createGUI(uifilebase)
+ # The task bar is created in the KMdiMainFrm constructor
+ # and then deleted in the createGUI() call above..
+ # So recreate it again to avoid a crash.
+ createTaskBar()
+ statusBar()
+ resize(400, 300)
+
+ @tools = {}
+ @toolIcons.each_index do |idx|
+ ico = @toolIcons[idx]
+ wid = KDE::ListBox.new(self, "list#{idx.to_s}")
+ makeTool(wid, "Tool #{idx.to_s}", ico)
+ end
+ ## smells
+ @mainToolWidget = @maintool = @tools['Tool 0'][0]
+
+ @childs = {}
+ @viewIcons.each_index do |idx|
+ ico = @viewIcons[idx]
+ makeView("View #{idx.to_s}", ico, ico)
+ end
+
+ connect(self, SIGNAL('viewActivated(KMdiChildView*)'), self, SLOT('activatedMessage(KMdiChildView*)'))
+ connect(self, SIGNAL('viewActivated(KMdiChildView*)'), self, SLOT('syncFromChildView(KMdiChildView*)'))
+ connect(@maintool, SIGNAL('selectionChanged(QListBoxItem*)'), self, SLOT('syncFromMainTool(QListBoxItem*)'))
+ syncFromChildView(activeWindow())
+ end
+
+ def syncFromMainTool(item)
+ # activate the view that matches the item text
+ activateView(findWindow(item.text()))
+ end
+
+ def syncFromChildView(child)
+ # sync the main tool to the indicated child
+ @maintool = @mainToolWidget
+ if child.nil?
+ return
+ end
+ item = @maintool.findItem(child.tabCaption())
+ if !item.nil?
+ @maintool.setSelected(item, nil)
+ end
+ end
+
+ def makeTool(widget, caption, icon, percent=50)
+ # makes a tool from the widget
+ tip = i18n("#{caption} Tool Tip")
+ dock = DockWidget::DockLeft
+ maindock = getMainDockWidget()
+ widget.setIcon(getIcon(icon))
+ tool = addToolWindow(widget, dock, maindock, percent, tip, caption)
+ @tools[caption] = [widget, tool]
+ end
+
+ def makeView(label, icon, text)
+ # makes a child view with a text label and a pixmap label
+ view = MdiChildView.new(label, self)
+ @childs[label] = view
+ view.setIcon(getIcon(icon))
+ layout = Qt::VBoxLayout.new(view)
+ layout.setAutoAdd(true)
+
+ lbl = Qt::Label.new(i18n("Label for a view with an icon named #{text}"), view)
+ pxm = Qt::Label.new('', view)
+ pxm.setPixmap(getIcon(icon, Icon::NoGroup, KDE::Icon::SizeLarge))
+ addWindow(view)
+ @mainToolWidget.insertItem(label)
+ connect(view, SIGNAL('childWindowCloseRequest(KMdiChildView*)'), self, SLOT('closeChild(KMdiChildView*)'))
+ end
+
+ def removeMainToolItem(view)
+ # remove item from the main list tool that corresponds to the view
+ @maintool = @mainToolWidget
+ @maintool.takeItem(@maintool.findItem(view.tabCaption(), 0))
+ end
+
+ def newView()
+ # make a view when the user invokes the new action
+ makeView("View ", 'network', 'A Fresh View')
+# makeView("View #{@childs.length}", 'network', 'A Fresh View')
+ syncFromChildView(activeWindow())
+ end
+
+ def closeActiveChild()
+ # close the current view
+ removeMainToolItem(activeWindow())
+ closeActiveView()
+ syncFromChildView(activeWindow())
+ end
+
+ def closeChild(which)
+ # called to close a view from its tab close button
+ caption = which.tabCaption()
+ removeMainToolItem(which)
+ which.close()
+ statusBar().message(i18n("#{caption} closed"))
+ syncFromChildView(activeWindow())
+ end
+
+ def activatedMessage(view)
+ # updates the status bar with the caption of the current view
+ statusBar().message(i18n("#{view.tabCaption()} activated"))
+ end
+end
+
+if $0 == __FILE__
+ aname = 'uikmdi'
+ desc = 'A Simple Korundum KMDI Sample'
+ ver = '1.0'
+ lic = AboutData::License_GPL
+ author = 'Troy Melhase'
+ authormail = 'troy@gci.net'
+
+ about = AboutData.new(aname, aname, ver, desc, lic, "#{authormail} (c) 2004")
+ about.addAuthor(author, 'hi, mom!', authormail)
+ about.addAuthor('Jim Bublitz', 'For PyKDE', 'jbublitz@nwinternet.com')
+ about.addAuthor('Richard Dale', 'For Korundum', 'Richard_Dale@tipitina.demon.co.uk')
+ CmdLineArgs.init(ARGV, about)
+ app = KDE::Application.new
+ mainWindow = KmdiExample.new
+ mainWindow.show
+ app.exec
+end
+
diff --git a/korundum/rubylib/examples/uikmdi.rc b/korundum/rubylib/examples/uikmdi.rc
new file mode 100644
index 00000000..a7e21969
--- /dev/null
+++ b/korundum/rubylib/examples/uikmdi.rc
@@ -0,0 +1,11 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="testfoo" version="1">
+<MenuBar>
+
+<!-- <Menu name="custom"><text>C&amp;ustom</text>
+ <Action name="custom_action" />
+ </Menu>
+-->
+
+</MenuBar>
+</kpartgui>
diff --git a/korundum/rubylib/examples/uimodules/uidialogs.rb b/korundum/rubylib/examples/uimodules/uidialogs.rb
new file mode 100644
index 00000000..2d264a4b
--- /dev/null
+++ b/korundum/rubylib/examples/uimodules/uidialogs.rb
@@ -0,0 +1,256 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+require 'Korundum'
+
+module UIDialogs
+
+class CustomDlg < KDE::Dialog
+
+ slots 'dlgClicked()', 'okClicked()', 'cancelClicked()'
+
+ def initialize(parent, name = "custom dlg", modal = false)
+ super(parent, name, modal)
+
+ x = 20
+ y = 10
+
+ rLbl = Qt::Label.new("r", self)
+ gLbl = Qt::Label.new("g", self)
+ bLbl = Qt::Label.new("b", self)
+ @rEd = Qt::LineEdit.new("64", self)
+ @gEd = Qt::LineEdit.new("64", self)
+ @bEd = Qt::LineEdit.new("64", self)
+ dlgBtn = Qt::PushButton.new("Set/Get Color", self)
+ okBtn = Qt::PushButton.new("OK", self)
+ canBtn = Qt::PushButton.new("Cancel", self)
+
+ rLbl.setGeometry(x, y, 25, 20)
+ gLbl.setGeometry(x + 30, y, 25, 20)
+ bLbl.setGeometry(x + 60, y, 25, 20)
+ y = y + 20
+ @rEd.setGeometry(x, y, 25, 20)
+ @gEd.setGeometry(x + 30, y, 25, 20)
+ @bEd.setGeometry(x + 60, y, 25, 20)
+ y = y + 30
+ dlgBtn.setGeometry(x, y, 90, 22)
+ y = y + 30
+ okBtn.setGeometry(x, y, 40, 22)
+ canBtn.setGeometry(x + 50, y, 40, 22)
+
+ connect(dlgBtn, SIGNAL("clicked()"), SLOT('dlgClicked()'))
+ connect(okBtn, SIGNAL("clicked()"), SLOT('okClicked()'))
+ connect(canBtn, SIGNAL("clicked()"), SLOT('cancelClicked()'))
+ end
+
+ def dlgClicked()
+ # get some(numerical) color values from the original dialog
+ red = @rEd.text().to_i
+ green = @gEd.text().to_i
+ blue = @bEd.text().to_I
+
+ # convert the numbers to a Qt::Color
+ color = Qt::Color.new(red, green, blue)
+
+ # invoke the dialog(getColor is a 'static' call)
+ # initialize with the colors from above(in color)
+ # color will also hold the new value chosen in the
+ # KDE::ColorDialog
+ result = KDE::ColorDialog.getColor(color, self)
+
+ # get the numerical color values back
+# red, green, blue = color.rgb()
+
+ # update the Qt::LineEdits in the original dialog
+ @rEd.setText(red.to_s)
+ @gEd.setText(green.to_s)
+ @bEd.setText(blue.to_s)
+ end
+
+ def okClicked()
+ done(1)
+ end
+
+ def cancelClicked()
+ done(0)
+ end
+end
+
+class MessageDlg < KDE::Dialog
+
+ slots 'launch(int)'
+
+ def initialize(parent, name = "message dlg", modal = false)
+ super(parent, name, modal)
+
+ buttons = ["QuestionYesNo", "WarningYesNo", "WarningContinueCancel", "WarningYesNoCancel",
+ "Information", "SSLMessageBox", "Sorry", "Error", "QuestionYesNoCancel"]
+
+ n = buttons.length
+
+ grp = Qt::ButtonGroup.new(n, Qt::Vertical, "MessageBoxes", self, "button grp")
+ grp.setGeometry(10, 10, 200, 30*n)
+ (0...n).each { |i| Qt::RadioButton.new(buttons[i], grp) }
+
+ connect(grp, SIGNAL("clicked(int)"), SLOT('launch(int)'))
+ end
+
+ def launch(which)
+ which += 1 # Qt::ButtonGroup id's start at 0, but the KDE::MessageBox enum starts at 1
+
+ if which == KDE::MessageBox::QuestionYesNo
+ KDE::MessageBox.questionYesNo(self, "This is a questionYesNo message box\nThere is also a list version of this dialog",\
+ "questionYesNo")
+
+ elsif which == KDE::MessageBox::WarningYesNo
+ KDE::MessageBox.warningYesNo(self, "This is a warningYesNo message box", "warningYesNo")
+
+ elsif which == KDE::MessageBox::WarningContinueCancel
+ KDE::MessageBox.warningContinueCancel(self, "This is a warningContinueCancel message box", "warningContinueCancel");
+
+ elsif which == KDE::MessageBox::WarningYesNoCancel
+ KDE::MessageBox.warningYesNoCancel(self, "This is a warningYesNoCancel message box", "warningYesNoCancel")
+
+ elsif which == KDE::MessageBox::Information
+ KDE::MessageBox.information(self, "This is an information message box", "Information")
+
+# elsif which == KDE::MessageBox::SSLMessageBox
+# KDE::MessageBox.SSLMessageBox(self, "This is an SSLMessageBox message box", "not implemented yet")
+
+ elsif which == KDE::MessageBox::Sorry
+ KDE::MessageBox.sorry(self, "This is a 'sorry' message box", "Sorry")
+
+ elsif which == KDE::MessageBox::Error
+ KDE::MessageBox.error(self, "No - this isn't really an error\nIt's an error message box\n", "Error")
+
+ elsif which == KDE::MessageBox::QuestionYesNoCancel
+ KDE::MessageBox.questionYesNoCancel(self, "No - this isn't really an error\nIt's an QuestionYesNoCancel message box\n", "QuestionYesNoCancel")
+ end
+ end
+end
+
+
+def UIDialogs.dlgKAboutDialog(parent)
+ dlg = KDE::AboutDialog.new(parent, 'about dialog', false)
+ dlg.setLogo(Qt::Pixmap.new("rbtestimage.png"))
+ dlg.setTitle("UISampler for Korundum")
+ dlg.setAuthor("Jim Bublitz", "jbublitz@nwinternet.com", "http://www.riverbankcomputing.co.uk",
+ "\n\nPyKDE -- Python bindings\n\tfor KDE")
+ dlg.setMaintainer("Richard Dale", "Richard_Dale@tipitina.demon.co.uk", "http://developer.kde.org/language-bindings/ruby/",\
+ "\n\nKorundum -- Ruby bindings\n\tfor KDE")
+ dlg.addContributor("KDE bindings list", "kde-bindings@kde.org", nil, nil)
+
+ dlg.show()
+end
+
+
+def UIDialogs.dlgKBugReport(parent)
+ dlg = KDE::BugReport.new(parent)
+ dlg.exec()
+end
+
+def UIDialogs.dlgKAboutKDE(parent)
+ dlg = KDE::AboutKDE.new(parent, "about kde", false)
+ dlg.show()
+end
+
+def UIDialogs.dlgKColorDialog(parent)
+ dlg = KDE::ColorDialog.new(parent, "color dlg", false)
+ dlg.show()
+end
+
+def UIDialogs.dlgKDialog(parent)
+ dlg = CustomDlg.new(parent)
+ dlg.show()
+end
+
+def UIDialogs.dlgKDialogBase(parent)
+ caption = "KDialogBase sample"
+ text_ = "This is a KDialogBase example"
+ dlg = KDE::DialogBase.new(parent, "sample_dialog", false, caption,
+ KDE::DialogBase::Ok | KDE::DialogBase::Cancel, KDE::DialogBase::Ok, true )
+
+ page = dlg.makeVBoxMainWidget();
+
+ # making 'page' the parent inserts the widgets in
+ # the VBox created above
+ label = Qt::Label.new( caption, page, "caption" );
+
+ lineedit = Qt::LineEdit.new(text_, page, "lineedit" );
+ lineedit.setMinimumWidth(dlg.fontMetrics().maxWidth()*20);
+
+ label0 = Qt::Label.new("Border widths", page)
+# widths = dlg.getBorderWidths()
+# labelA = Qt::Label.new("Upper Left X: " + widths[0].to_s, page)
+# labelB = Qt::Label.new("Upper Left Y: " + widths[0].to_s, page)
+# labelC = Qt::Label.new("Lower Right X: " + str(c), page)
+# labelD = Qt::Label.new("Lower Right Y: " + str(d), page)
+
+ dlg.show()
+end
+
+def UIDialogs.dlgKFontDialog(parent)
+ dlg = KDE::FontDialog.new(parent, "font dlg", false, false)
+ dlg.show()
+end
+
+def UIDialogs.dlgKKeyDialog(parent)
+ # This really doesn't do anything except pop up the dlg
+ keys = KDE::Accel.new(parent)
+# keys.insertItem( i18n( "Zoom in" ), "Zoom in", "+" )
+ keys.readSettings();
+ KDE::KeyDialog.configure(keys, true)
+end
+
+def UIDialogs.dlgKInputDialog(parent)
+ ok = Qt::Boolean.new
+ result = KDE::InputDialog.getText("Enter text", "", "<Your input here>", ok)
+# puts "result: %s" % result
+# puts "ok: %s" % ok
+
+ # pop up another dlg to show what happened in the KDE::LineEditDlg
+ if !ok.nil?
+ KDE::MessageBox.information(parent, "OK was pressed\nText: " + result, "KDE::InputDialog result")
+ else
+ KDE::MessageBox.information(parent, "Cancel pressed\nText", "KDE::InputDialog result")
+ end
+end
+
+def UIDialogs.dlgKMessageBox(parent)
+ dlg = MessageDlg.new(parent)
+ dlg.show()
+end
+
+def UIDialogs.dlgKPasswordDialog(parent)
+ password = ""
+ result = KDE::PasswordDialog.getPassword(password, "Enter password(just a test)")
+ puts "password: #{password}"
+end
+
+def UIDialogs.dlgKWizard(parent)
+ wiz = KDE::Wizard.new(parent)
+
+ page1 = Qt::Widget.new(wiz)
+ p1Lbl = Qt::Label.new("This is page 1", page1)
+ p1Lbl.setGeometry(20, 20, 100, 20)
+ page2 = Qt::Widget.new(wiz)
+ p2Lbl = Qt::Label.new("This is page 2", page2)
+ p2Lbl.setGeometry(50, 20, 100, 20)
+ page3 = Qt::Widget.new(wiz)
+ p3Lbl = Qt::Label.new("This is page 3", page3)
+ p3Lbl.setGeometry(80, 20, 100, 20)
+
+ wiz.addPage(page1, "Page 1")
+ wiz.addPage(page2, "Page 2")
+ wiz.addPage(page3, "Page 3")
+ wiz.show()
+end
+
+if $0 == __FILE__
+ puts
+ puts "Please run uisampler.rb"
+ puts
+end
+
+end
diff --git a/korundum/rubylib/examples/uimodules/uimenus.rb b/korundum/rubylib/examples/uimodules/uimenus.rb
new file mode 100644
index 00000000..4a8ff523
--- /dev/null
+++ b/korundum/rubylib/examples/uimodules/uimenus.rb
@@ -0,0 +1,137 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+require 'Korundum'
+
+module UIMenus
+
+class PageLaunch
+ def initialize(parent)
+ page = parent.addPage()
+
+ x = 10
+ y = 10
+
+ launchLbl = Qt::Label.new("Launching application ... please wait\n\nClose launched application to continue", page)
+ launchLbl.setGeometry(x, y, 300, 80)
+ launchLbl.show()
+
+ page.show()
+
+ $kapp.processEvents()
+ end
+end
+
+
+class PageNotImpl
+ def initialize(parent)
+ page = parent.addPage()
+
+ x = 10
+ y = 10
+
+ niLbl = Qt::Label.new("Nothing is currently implemented for this widget", page)
+ niLbl.setGeometry(x, y, 300, 20)
+ niLbl.show()
+ end
+end
+
+def UIMenus.menuKAccelGen(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMenus.menuKAccelMenu(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMenus.menuKAction(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby menudemo.rb")
+end
+
+def UIMenus.menuKActionMenu(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby menudemo.rb")
+end
+
+def UIMenus.menuKActionSeparator(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby menudemo.rb")
+end
+
+def UIMenus.menuKContextMenuManager(parent)
+# pass
+end
+
+def UIMenus.menuKDCOPActionProxy(parent)
+# pass
+end
+
+def UIMenus.menuKHelpMenu(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby menudemo.rb")
+end
+
+def UIMenus.menuKMenuBar(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby menudemo.rb")
+end
+
+def UIMenus.menuKPanelApplet(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMenus.menuKPanelExtension(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMenus.menuKPanelMenu(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMenus.menuKPopupFrame(parent)
+# pass
+end
+
+def UIMenus.menuKPopupMenu(parent)
+# pass
+end
+
+def UIMenus.menuKPopupTitle(parent)
+# pass
+end
+
+def UIMenus.menuKStatusBar(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby menudemo.rb")
+end
+
+def UIMenus.menuKStatusBarLabel(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby menudemo.rb")
+end
+
+def UIMenus.menuKStdAction(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby menudemo.rb")
+end
+
+def UIMenus.menuKToolBar(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby menudemo.rb")
+end
+
+def UIMenus.menuKWindowListMenu(parent)
+# pass
+end
+
+
+if $0 == __FILE__
+ puts
+ puts "Please run uisampler.rb"
+ puts
+end
+
+end
+
diff --git a/korundum/rubylib/examples/uimodules/uimisc.rb b/korundum/rubylib/examples/uimodules/uimisc.rb
new file mode 100644
index 00000000..f9d70161
--- /dev/null
+++ b/korundum/rubylib/examples/uimodules/uimisc.rb
@@ -0,0 +1,273 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+require 'Korundum'
+
+module UIMisc
+
+class Page3 < Qt::Object
+ slots 'ivChanged()', 'fvChanged()', 'dvChanged()'
+
+ def initialize(parent)
+ super
+ page = parent.addPage()
+ x = 10
+ y = 15
+
+ green = Qt::Color.new(0, 255, 0)
+ yellow = Qt::Color.new(255, 255, 0)
+ red = Qt::Color.new(255, 0, 0)
+
+ ivLbl = Qt::Label.new("KIntValidator", page)
+ ivLbl.setGeometry(x, y, 100, 20)
+ ivLbl.show()
+
+ @iv = KDE::LineEdit.new(page)
+ @iv.setGeometry(x, y + 20, 100, 20)
+ @iv.show()
+ connect(@iv, SIGNAL("textChanged(const QString&)"), SLOT('ivChanged()'))
+
+ @ivVal = KDE::IntValidator.new(page)
+ @ivVal.setRange(20, 50)
+
+ ivRngLbl = Qt::Label.new("Range is 20 - 50", page)
+ ivRngLbl.setGeometry(x, y + 45, 100, 20)
+ ivRngLbl.show()
+
+ ivAccLbl = Qt::Label.new("Acceptable", page)
+ ivAccLbl.setGeometry(x + 125, y + 45, 85, 20)
+ ivAccLbl.show()
+ ivInterLbl = Qt::Label.new("Intermediate", page)
+ ivInterLbl.setGeometry(x + 125, y + 20, 85, 20)
+ ivInterLbl.show()
+ ivInvalLbl = Qt::Label.new("Invalid", page)
+ ivInvalLbl.setGeometry(x + 125, y - 5, 85, 20)
+ ivInvalLbl.show()
+ @ivInvalLed = KDE::Led.new(red, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page)
+ @ivInvalLed.setGeometry(x + 215, y - 5, 18, 18)
+ @ivInvalLed.show()
+ @ivInterLed = KDE::Led.new(yellow, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page)
+ @ivInterLed.setGeometry(x + 215, y + 20, 18, 18)
+ @ivInterLed.show()
+ @ivAccLed = KDE::Led.new(green, KDE::Led::On, KDE::Led::Sunken, KDE::Led::Circular,page)
+ @ivAccLed.setGeometry(x + 215, y + 45, 18, 18)
+ @ivAccLed.show()
+
+ y = y + 100
+
+ fvLbl = Qt::Label.new("KDoubleValidator", page)
+ fvLbl.setGeometry(x, y, 100, 20)
+ fvLbl.show()
+
+ @fv = KDE::LineEdit.new(page)
+ @fv.setGeometry(x, y + 20, 100, 20)
+ @fv.show()
+ connect(@fv, SIGNAL("textChanged(const QString&)"), SLOT('fvChanged()'))
+
+ @fvVal = KDE::DoubleValidator.new(page)
+ @fvVal.setRange(10.0, 40.0)
+
+ fvRngLbl = Qt::Label.new("Range is 10.0 - 40.0", page)
+ fvRngLbl.setGeometry(x, y + 45, 100, 20)
+ fvRngLbl.show()
+
+ fvAccLbl = Qt::Label.new("Acceptable", page)
+ fvAccLbl.setGeometry(x + 125, y + 45, 85, 20)
+ fvAccLbl.show()
+ fvInterLbl = Qt::Label.new("Intermediate", page)
+ fvInterLbl.setGeometry(x + 125, y + 20, 95, 20)
+ fvInterLbl.show()
+ fvInvalLbl = Qt::Label.new("Invalid", page)
+ fvInvalLbl.setGeometry(x + 125, y - 5, 85, 20)
+ fvInvalLbl.show()
+ @fvInvalLed = KDE::Led.new(red, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page)
+ @fvInvalLed.setGeometry(x + 215, y - 5, 18, 18)
+ @fvInvalLed.show()
+ @fvInterLed = KDE::Led.new(yellow, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page)
+ @fvInterLed.setGeometry(x + 215, y + 20, 18, 18)
+ @fvInterLed.show()
+ @fvAccLed = KDE::Led.new(green, KDE::Led::On, KDE::Led::Sunken, KDE::Led::Circular,page)
+ @fvAccLed.setGeometry(x + 215, y + 45, 18, 18)
+ @fvAccLed.show()
+
+ y = y + 100
+
+ dvLbl = Qt::Label.new("KDateValidator", page)
+ dvLbl.setGeometry(x, y, 100, 20)
+ dvLbl.show()
+
+ @dv = KDE::LineEdit.new(page)
+ @dv.setGeometry(x, y + 20, 100, 20)
+ @dv.show()
+# connect(dv, SIGNAL("textChanged(const QString&)"), SLOT('dvChanged()'))
+
+ @dvVal = KDE::DateValidator.new(page)
+# dvVal.setRange(10.0, 40.0)
+
+# dvRngLbl = Qt::Label.new("Range is 10.0 - 40.0", page)
+# dvRngLbl.setGeometry(x, y + 45, 100, 20)
+# dvRngLbl.show()
+
+ dvBtn = Qt::PushButton.new("Validate", page)
+ dvBtn.setGeometry(x, y + 45, 60, 22)
+ dvBtn.show()
+ connect(dvBtn, SIGNAL("clicked()"), SLOT('dvChanged()'))
+
+ dvNoteLbl = Qt::Label.new("Format is locale dependent\nShort date only\nTry DD-MM-YY", page)
+ dvNoteLbl.setGeometry(x, y + 70, 150, 60)
+ dvNoteLbl.show()
+
+ dvAccLbl = Qt::Label.new("Acceptable", page)
+ dvAccLbl.setGeometry(x + 125, y + 45, 85, 20)
+ dvAccLbl.show()
+ dvInterLbl = Qt::Label.new("Intermediate", page)
+ dvInterLbl.setGeometry(x + 125, y + 20, 85, 20)
+ dvInterLbl.show()
+ dvInvalLbl = Qt::Label.new("Invalid", page)
+ dvInvalLbl.setGeometry(x + 125, y - 5, 85, 20)
+ dvInvalLbl.show()
+ @dvInvalLed = KDE::Led.new(red, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page)
+ @dvInvalLed.setGeometry(x + 215, y - 5, 18, 18)
+ @dvInvalLed.show()
+ @dvInterLed = KDE::Led.new(yellow, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page)
+ @dvInterLed.setGeometry(x + 215, y + 20, 18, 18)
+ @dvInterLed.show()
+ @dvAccLed = KDE::Led.new(green, KDE::Led::On, KDE::Led::Sunken, KDE::Led::Circular,page)
+ @dvAccLed.setGeometry(x + 215, y + 45, 18, 18)
+ @dvAccLed.show()
+ end
+
+ def ivChanged()
+ @ivInvalLed.off()
+ @ivInterLed.off()
+ @ivAccLed.off()
+
+ i = Qt::Integer.new(0)
+ state = @ivVal.validate(@iv.text(), i)
+
+ if state == Qt::Validator::Acceptable
+ @ivAccLed.on()
+ elsif state == Qt::Validator::Intermediate
+ @ivInterLed.on()
+ else
+ @ivInvalLed.on()
+ end
+ end
+
+ def fvChanged()
+ @fvInvalLed.off()
+ @fvInterLed.off()
+ @fvAccLed.off()
+
+ i = Qt::Integer.new(0)
+ state = @fvVal.validate(@fv.text(), i)
+
+ if state == Qt::Validator::Acceptable
+ @fvAccLed.on()
+ elsif state == Qt::Validator::Intermediate
+ @fvInterLed.on()
+ else
+ @fvInvalLed.on()
+ end
+ end
+
+ def dvChanged()
+ @dvInvalLed.off()
+ @dvInterLed.off()
+ @dvAccLed.off()
+
+ i = Qt::Integer.new(0)
+ state = @dvVal.validate(@dv.text(), i)
+
+ if state == Qt::Validator::Acceptable
+ @dvAccLed.on()
+ elsif state == Qt::Validator::Intermediate
+ @dvInterLed.on()
+ else
+ @dvInvalLed.on()
+ end
+ end
+end
+
+class PageNotImpl
+ def initialize(parent)
+ page = parent.addPage()
+
+ x = 10
+ y = 10
+
+ niLbl = Qt::Label.new("Nothing is currently implemented for this widget", page)
+ niLbl.setGeometry(x, y, 300, 20)
+ niLbl.show()
+ end
+end
+
+def UIMisc.miscKAlphaPainter(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMisc.miscKCModule(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMisc.miscKColor(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMisc.miscKColorDrag(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMisc.miscKCommand(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMisc.miscKCommandHistory(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMisc.miscKDockWindow(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMisc.miscKDoubleValidator(parent)
+ parent.currentPageObj = Page3.new(parent)
+end
+
+def UIMisc.miscKDateValidator(parent)
+ parent.currentPageObj = Page3.new(parent)
+end
+
+def UIMisc.miscKIntValidator(parent)
+ parent.currentPageObj = Page3.new(parent)
+end
+
+def UIMisc.miscKPixmapIO(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMisc.miscKSharedPixmap(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMisc.miscKSystemTray(parent)
+ KDE::MessageBox.information(parent, "See the systray.rb example in the templates/ subdirectories")
+end
+
+def UIMisc.miscKThemeBase(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIMisc.miscQXEmbed(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+if $0 == __FILE__
+ puts
+ puts "Please run uisampler.rb"
+ puts
+end
+
+end
+
diff --git a/korundum/rubylib/examples/uimodules/uiwidgets.rb b/korundum/rubylib/examples/uimodules/uiwidgets.rb
new file mode 100644
index 00000000..8dd79d49
--- /dev/null
+++ b/korundum/rubylib/examples/uimodules/uiwidgets.rb
@@ -0,0 +1,827 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+require 'Korundum'
+
+module UIWidgets
+
+class Page1 < Qt::Object
+ slots 'restrict(int)'
+
+ def initialize(parent)
+ super
+ page = parent.addPage()
+
+ x = 10
+ y = 10
+
+ editLbl = Qt::Label.new("KTextEdit", page)
+ editLbl.setGeometry(x, y, 50, 20)
+ editLbl.show()
+
+ textList = ["Now is the winter of our discontent\n",
+ "made glorious summer by this sun of York;\n",
+ "and all the clouds that lour'd upon our house\n",
+ "in the deep bosom of the ocean buried.\n"]
+
+ parent.edit = KDE::TextEdit.new(page)
+ parent.edit.setGeometry(x, y + 20, 300, 100)
+ textList.each do |line|
+ parent.edit.insert(line)
+ end
+ parent.edit.show()
+
+ y = y + 125
+ searchBtn = Qt::PushButton.new("Search", page)
+ replaceBtn = Qt::PushButton.new("Replace", page)
+ gotoBtn = Qt::PushButton.new("GoTo Line", page)
+
+ searchBtn.setGeometry(x, y, 60, 22)
+ replaceBtn.setGeometry(x + 90, y, 60, 22)
+ gotoBtn.setGeometry(x + 180, y, 60, 22)
+
+# page.connect(searchBtn, SIGNAL("clicked()"), parent.edit, SLOT('search()'))
+# page.connect(replaceBtn, SIGNAL("clicked()"), parent.edit, SLOT('replace()'))
+# page.connect(gotoBtn, SIGNAL("clicked()"), parent.edit, SLOT('doGotoLine()'))
+
+ searchBtn.show()
+ replaceBtn.show()
+ gotoBtn.show()
+
+ y = y + 35
+
+ lineeditLbl = Qt::Label.new("KLineEdit", page)
+ lineeditLbl.setGeometry(x, y, 70, 20)
+ lineeditLbl.show()
+
+ lineedit = KDE::LineEdit.new(page)
+ lineedit.setGeometry(x, y + 20, 100, 20)
+ lineedit.show()
+
+ intLbl = Qt::Label.new("KIntNumInput", page)
+ intLbl.setGeometry(x + 195, y + 35, 95, 20)
+ intLbl.show()
+
+ intNum = KDE::IntNumInput.new(5, page)
+ intNum.setGeometry(x + 195, y + 55, 175, 50)
+# intNum.setSuffix(" GB")
+# intNum.setPrefix("hdc ")
+ intNum.setLabel("Capacity")
+ intNum.setRange(0, 10, 1, true)
+ intNum.show()
+
+ y = y + 50
+
+ dblLbl = Qt::Label.new("KDoubleNumInput", page)
+ dblLbl.setGeometry(x + 195, y + 80, 115, 20)
+ dblLbl.show()
+
+ dblNum = KDE::DoubleNumInput.new(page)
+ dblNum.setValue(2.5)
+ dblNum.setGeometry(x + 195, y + 100, 175, 50)
+ dblNum.setLabel("Variable")
+ dblNum.setRange(0.0, 10.0, 0.5, true)
+ dblNum.show()
+
+ restricteditLbl = Qt::Label.new("KRestrictedLine", page)
+ restricteditLbl.setGeometry(x, y, 95, 20)
+ restricteditLbl.show()
+
+ @restrictlineedit = KDE::RestrictedLine.new(page)
+ @restrictlineedit.setGeometry(x, y + 20, 100, 20)
+ @restrictlineedit.show()
+
+ buttons = ["Numbers Only", "Upper Case Only", "Lower Case Only"]
+
+ n = buttons.length
+
+ @validLbl = Qt::Label.new("", page)
+ @validLbl.setGeometry(x, y + 50, 250, 20)
+ @validLbl.show()
+
+ grp = Qt::ButtonGroup.new(n, Qt::Vertical, "Select valid chars", page, "button grp")
+ grp.setGeometry(x, y + 75, 150, 5+30*n)
+
+ (0...n).each { |i| Qt::RadioButton.new(buttons[i], grp) }
+
+ connect(grp, SIGNAL("clicked(int)"), SLOT('restrict(int)'))
+
+ grp.find(0).setChecked(true)
+ restrict(0)
+
+ grp.show()
+
+ page.show()
+ $kapp.processEvents()
+
+ y = y + 195
+ sqzLbl = Qt::Label.new("This text is too long to fit in the label below", page)
+ sqzLbl.setGeometry(x, y, 350, 20)
+ sqzLbl.show()
+
+ sqzLbl1 = Qt::Label.new("KSqueezedTxtLabel:", page)
+ sqzLbl1.setGeometry(x, y + 20, 120, 20)
+ sqzLbl1.show()
+
+ squeeze = KDE::SqueezedTextLabel.new("This text is too long to fit in the label below", page)
+ squeeze.setGeometry(x + 125, y + 20, 125, 20)
+ squeeze.setBackgroundMode(Qt::Widget::PaletteBase)
+ squeeze.show()
+ end
+
+ def restrict(which)
+ r = {0 => "0123456789", 1 => "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 2 => "abcdefghijklmnopqrstuvwxyz"}
+ @restrictlineedit.setValidChars(r[which])
+ @validLbl.setText("Valid: " + @restrictlineedit.validChars())
+ end
+end
+
+class Page2
+ def initialize(parent)
+ page = parent.addPage()
+
+ x1 = 10
+ y1 = 10
+ x2 = 240
+ y2 = 100
+
+ cbLbl = Qt::Label.new("KComboBox", page)
+ cbLbl.setGeometry(x1, y1, 75, 20)
+ cbLbl.show()
+
+ combo = KDE::ComboBox.new(page)
+ combo.insertStringList(["One", "Two", "Three"])
+ combo.setGeometry(x1, y1 + 20, 100, 25)
+ combo.show()
+
+ ccbLbl = Qt::Label.new("KColorCombo", page)
+ ccbLbl.setGeometry(x2, y1, 100, 20)
+ ccbLbl.show()
+
+ colorCombo = KDE::ColorCombo.new(page)
+ colorCombo.setGeometry(x2, y1 + 20, 100, 25)
+ colorCombo.show()
+
+ editListBox = KDE::EditListBox.new("KEditListBox", page)
+ editListBox.setGeometry(x1, y2, 220, 175)
+ editListBox.insertStringList(["One", "Two", "Three"])
+ editListBox.show()
+
+ lbLbl = Qt::Label.new("KListBox", page)
+ lbLbl.setGeometry(x2, y2, 100, 20)
+ lbLbl.show()
+
+ listBox = KDE::ListBox.new(page)
+ listBox.setGeometry(x2, y2 + 20, 100, 100)
+ listBox.insertStringList(["One", "Two", "Three"])
+ listBox.show()
+ end
+end
+
+class Page3
+ def initialize(parent)
+ page = parent.addPage()
+
+ x = 10
+ y = 10
+
+ fontLbl = Qt::Label.new("KFontChooser", page)
+ fontLbl.setGeometry(x, y, 95, 20)
+ fontLbl.show()
+
+ fontChoose = KDE::FontChooser.new(page)
+ fontChoose.setGeometry(x, y + 20, 375, 300)
+ fontChoose.show()
+
+ y = y + 330
+ end
+end
+
+class Page4
+ def initialize(parent)
+ page = parent.addPage()
+
+ x = 10
+ y = 10
+
+ cbLbl = Qt::Label.new("KColorButton", page)
+ cbLbl.setGeometry(x, y, 75, 20)
+ cbLbl.show()
+
+ cb = KDE::ColorButton.new(page)
+ cb.setColor(Qt::Color.new(255, 0, 0))
+ cb.setGeometry(x, y + 20, 30, 30)
+ cb.show()
+
+ ccbLbl = Qt::Label.new("KColorCombo", page)
+ ccbLbl.setGeometry(x + 150, y, 100, 20)
+ ccbLbl.show()
+
+ colorCombo = KDE::ColorCombo.new(page)
+ colorCombo.setGeometry(x + 150, y + 20, 100, 25)
+ colorCombo.show()
+
+ y = y + 60
+
+ cpLbl = Qt::Label.new("KColorPatch", page)
+ cpLbl.setGeometry(x, y, 75, 20)
+ cpLbl.show()
+
+ cp = KDE::ColorPatch.new(page)
+ cp.setColor(Qt::Color.new(255, 0, 0))
+ cp.setGeometry(x, y + 20, 20, 20)
+ cp.show()
+
+ x = x + 150
+
+ ccLbl = Qt::Label.new("KColorCells", page)
+ ccLbl.setGeometry(x, y, 75, 20)
+ ccLbl.show()
+
+ cc = KDE::ColorCells.new(page, 1, 5)
+ cc.setColor(0, Qt::Color.new(0, 0, 0))
+ cc.setColor(1, Qt::Color.new(255, 0, 0))
+ cc.setColor(2, Qt::Color.new(0, 255, 0))
+ cc.setColor(3, Qt::Color.new(0, 0, 255))
+ cc.setColor(4, Qt::Color.new(255, 255, 255))
+ cc.setGeometry(x, y + 20, 100, 20)
+ cc.show()
+
+ x = 10
+ y = y + 50
+
+ dcLbl = Qt::Label.new("KDualColorButton", page)
+ dcLbl.setGeometry(x, y, 105, 20)
+ dcLbl.show()
+
+ dc = KDE::DualColorButton.new(Qt::Color.new(255, 0, 0), Qt::Color.new(0, 0, 0), page)
+ dc.setGeometry(x, y + 20, 40, 40)
+ dc.show()
+
+ gsLbl = Qt::Label.new("KGradientSelector", page)
+ gsLbl.setGeometry(x + 80, y + 30, 110, 20)
+ gsLbl.show()
+
+ gs = KDE::GradientSelector.new(page)
+ gs.setGeometry(x + 80, y + 50, 250, 20)
+ gs.setColors(Qt::Color.new(255, 0, 0), Qt::Color.new(255, 255, 0))
+ gs.show()
+
+ y = y + 80
+
+ hsLbl = Qt::Label.new("KHSSelector", page)
+ hsLbl.setGeometry(x, y, 95, 20)
+ hsLbl.show()
+
+ hs = KDE::HSSelector.new(page)
+ hs.setGeometry(x, y + 20, 350, 80)
+ hs.show()
+
+ y = y + 110
+
+ ptLbl = Qt::Label.new("KPaletteTable", page)
+ ptLbl.setGeometry(x, y, 95, 20)
+ ptLbl.show()
+
+ pt = KDE::PaletteTable.new(page, 340, 24)
+ pt.setPalette("Royal")
+ pt.setGeometry(x, y + 20, 340, 40)
+ pt.show()
+ end
+end
+
+class Page5
+ def initialize(parent)
+ page = parent.addPage()
+
+ x = 10
+ y = 10
+
+ rpLbl = Qt::Label.new("KRootPermsIcon", page)
+ rpLbl.setGeometry(x, y, 95, 20)
+ rpLbl.show()
+
+ rp = KDE::RootPermsIcon.new(page)
+ rp.setGeometry(x, y + 20, 32, 32)
+ rp.show()
+
+ wpLbl = Qt::Label.new("KWritePermsIcon", page)
+ wpLbl.setGeometry(x + 125, y, 95, 20)
+ wpLbl.show()
+
+ wp = KDE::WritePermsIcon.new("/usr/bin/gcc", page)
+ wp.setGeometry(x + 125, y + 20, 32, 32)
+ wp.show()
+
+ y = y + 75
+
+ pw1Lbl = Qt::Label.new("KPasswordEdit - echo *", page)
+ pw1Lbl.setGeometry(x, y, 150, 20)
+ pw1Lbl.show()
+
+ pw1 = KDE::PasswordEdit.new(KDE::PasswordEdit::OneStar, page, "")
+ pw1.setGeometry(x, y + 20, 100, 20)
+ pw1.show()
+
+ y = y + 50
+
+ pw2Lbl = Qt::Label.new("KPasswordEdit - echo ***", page)
+ pw2Lbl.setGeometry(x, y, 150, 20)
+ pw2Lbl.show()
+
+ pw2 = KDE::PasswordEdit.new(KDE::PasswordEdit::ThreeStars, page, "")
+ pw2.setGeometry(x, y + 20, 100, 20)
+ pw2.show()
+
+ y = y + 50
+
+ pw3Lbl = Qt::Label.new("KPasswordEdit - no echo", page)
+ pw3Lbl.setGeometry(x, y, 150, 20)
+ pw3Lbl.show()
+
+ pw3 = KDE::PasswordEdit.new(KDE::PasswordEdit::NoEcho, page, "")
+ pw3.setGeometry(x, y + 20, 100, 20)
+ pw3.show()
+
+ y = y + 50
+
+ urlLbl = Qt::Label.new("KURLLabel", page)
+ urlLbl.setGeometry(x, y, 100, 20)
+ urlLbl.show()
+
+ url = KDE::URLLabel.new("http://developer.kde.org/language-bindings/ruby/", "Korundum", page)
+ url.setGeometry(x, y + 20, 100, 20)
+ url.setUseTips(true)
+ url.setTipText("http://developer.kde.org/language-bindings/ruby/")
+ url.show()
+
+ x = 70
+ y = y + 50
+
+ bbLbl = Qt::Label.new("KButtonBox", page)
+ bbLbl.setGeometry(x, y, 75, 20)
+ bbLbl.show()
+
+ bbox = KDE::ButtonBox.new(page, Qt::Horizontal)
+ bbox.setGeometry(x, y + 20, 300, 22)
+ bbox.addButton("Button 1")
+ bbox.addButton("Button 2")
+ bbox.addButton("Button 3")
+ bbox.show()
+
+ y = y + 50
+
+# dbLbl = Qt::Label.new("KDirectionButton", page)
+# dbLbl.setGeometry(x, y, 95, 20)
+# dbLbl.show()
+
+# dbUp = KDE::DirectionButton.new(Qt::t::UpArrow, page)
+# dbDown = KDE::DirectionButton.new(Qt::t::DownArrow, page)
+# dbRight = KDE::DirectionButton.new(Qt::t::RightArrow, page)
+# dbLeft = KDE::DirectionButton.new(Qt::t::LeftArrow, page)
+
+# dbUp.setGeometry(x, y + 20, 22, 22)
+# dbDown.setGeometry(x + 30, y + 20, 22, 22)
+# dbRight.setGeometry(x + 60, y + 20, 22, 22)
+# dbLeft.setGeometry(x + 90, y + 20, 22, 22)
+
+# dbUp.show()
+# dbDown.show()
+# dbRight.show()
+# dbLeft.show()
+
+ x = x + 150
+
+# kbLbl = Qt::Label.new("KKeyButton", page)
+# kbLbl.setGeometry(x, y, 95, 20)
+# kbLbl.show()
+
+# kb = KDE::KeyButton.new(page)
+# kb.setText("Enter")
+# kb.setGeometry(x, y + 20, 50, 32)
+# kb.show()
+
+ x = 70
+ y = y + 50
+
+# tbLbl = Qt::Label.new("KTabButton", page)
+# tbLbl.setGeometry(x, y, 95, 20)
+# tbLbl.show()
+
+# tbUp = KDE::TabButton.new(Qt::t::UpArrow, page)
+# tbDown = KDE::TabButton.new(Qt::t::DownArrow, page)
+# tbRight = KDE::TabButton.new(Qt::t::RightArrow, page)
+# tbLeft = KDE::TabButton.new(Qt::t::LeftArrow, page)
+
+# tbUp.setGeometry(x, y + 20, 22, 25)
+# tbDown.setGeometry(x + 30, y + 20, 22, 25)
+# tbRight.setGeometry(x + 60, y + 20, 22, 25)
+# tbLeft.setGeometry(x + 90, y + 20, 22, 25)
+
+# tbUp.show()
+# tbDown.show()
+# tbRight.show()
+# tbLeft.show()
+ end
+end
+
+class Page6 < Qt::Object
+ slots 'toggleClicked()'
+
+ def initialize(parent)
+ super
+ page = parent.addPage()
+
+ x = 20
+ y = 10
+
+ red = Qt::Color.new(255, 0, 0)
+ green = Qt::Color.new(0, 255, 0)
+ yellow = Qt::Color.new(255, 255, 0)
+ blue = Qt::Color.new(0, 0, 255)
+
+ ledcolor = [red, green, yellow, blue]
+ ledshape = [KDE::Led::Rectangular, KDE::Led::Circular]
+ ledlook = [KDE::Led::Flat, KDE::Led::Raised, KDE::Led::Sunken]
+ ledsize = [10, 18, 25]
+ @ledlist = []
+
+ ledlook.each do |look|
+ ledcolor.each do |color|
+ ledshape.each do |shape|
+ ledsize.each do |size|
+ led = KDE::Led.new(color, KDE::Led::On, look, shape, page)
+ led.setGeometry(x, y, size, size)
+ @ledlist << led
+ led.show()
+ x = x + 50
+ end
+ x = x + 50
+ end
+ x = 20
+ y = y + 30
+ end
+ y = y + 10
+ end
+
+ toggle = Qt::PushButton.new("Toggle", page)
+ toggle.setGeometry(150, 400, 60, 22)
+ toggle.show()
+
+ connect(toggle, SIGNAL("clicked()"), SLOT('toggleClicked()'))
+
+ page.show()
+ end
+
+ def toggleClicked()
+ @ledlist.each { |led| led.toggle() }
+ end
+end
+
+class Page7 < Qt::Object
+ slots 'add1()'
+
+ def initialize(parent)
+ super
+ page = parent.addPage()
+
+ x = 10
+ y = 10
+
+ tabLbl = Qt::Label.new("KTabCtl", page)
+ tabLbl.setGeometry(x, y, 95, 20)
+ tabLbl.show()
+
+ tab = KDE::TabCtl.new(page)
+ tab.setGeometry(x, y + 20, 300, 100)
+
+ page1 = Qt::Widget.new(tab)
+ p1Lbl = Qt::Label.new("This is page 1", page1)
+ p1Lbl.setGeometry(20, 20, 100, 20)
+ page2 = Qt::Widget.new(tab)
+ p2Lbl = Qt::Label.new("This is page 2", page2)
+ p2Lbl.setGeometry(50, 20, 100, 20)
+ page3 = Qt::Widget.new(tab)
+ p3Lbl = Qt::Label.new("This is page 3", page3)
+ p3Lbl.setGeometry(20, 50, 100, 20)
+
+ tab.addTab(page1, "Tab 1")
+ tab.addTab(page2, "Tab 2")
+ tab.addTab(page3, "Tab 3")
+ tab.show()
+
+ x = 10
+ y = 150
+
+ progLbl = Qt::Label.new("KProgress", page)
+ progLbl.setGeometry(x, y + 50, 95, 20)
+ progLbl.show()
+
+ @p1 = KDE::Progress.new(page)
+ @p2 = KDE::Progress.new(15, page)
+ @p1.setTotalSteps(25)
+ @p2.setTotalSteps(25)
+
+ @p1.setGeometry(x, y + 80, 125, 20)
+ @p2.setGeometry(x, y + 120, 125, 20)
+
+ @p2.setPercentageVisible(false)
+
+ @p1.show()
+ @p2.show()
+
+ @total = 0
+
+ y = y + 150
+ sepLbl = Qt::Label.new("KSeparator", page)
+ sepLbl.setGeometry(x, y, 95, 20)
+ sepLbl.show()
+
+ sep = KDE::Separator.new(Qt::Frame::HLine, page)
+ sep.setGeometry(x, y + 20, 75, 10)
+ sep.show()
+
+ page.show()
+
+ @timer = Qt::Timer.new(page)
+ connect(@timer, SIGNAL('timeout()'), SLOT('add1()'))
+ @timer.start(100)
+
+ add1()
+ end
+
+ def add1()
+ @total = @total + 1
+ @p1.advance(1)
+ @p2.advance(1)
+
+ if @total == 26
+ @timer.stop
+ end
+ end
+end
+
+class Page8
+ def initialize(parent)
+ page = parent.addPage()
+
+ x = 40
+ y = 10
+
+ dpLbl = Qt::Label.new("KDatePicker", page)
+ dpLbl.setGeometry(x, y, 95, 20)
+ dpLbl.show()
+
+ dp = KDE::DatePicker.new(page)
+ dp.setGeometry(x, y + 20, 300, 170)
+ dp.show()
+
+ y = y + 210
+
+ dtLbl = Qt::Label.new("KDateTable", page)
+ dtLbl.setGeometry(x, y, 95, 20)
+ dtLbl.show()
+
+ dt = KDE::DateTable.new(page)
+ dt.setGeometry(x, y + 20, 300, 130)
+ dt.show()
+ end
+end
+
+class PageThisApp
+ def initialize(parent)
+ page = parent.addPage()
+
+ x = 10
+ y = 10
+
+ taLbl = Qt::Label.new("This application uses KMainWindow as its top level widget\n and KListView in the"\
+ " left-hand panel", page)
+ taLbl.setGeometry(x, y, 300, 60)
+ taLbl.show()
+ end
+end
+
+class PageNotImpl
+ def initialize(parent)
+ page = parent.addPage()
+
+ x = 10
+ y = 10
+
+ niLbl = Qt::Label.new("Nothing is currently implemented for this widget", page)
+ niLbl.setGeometry(x, y, 300, 20)
+ niLbl.show()
+ end
+end
+
+class CSDlg < KDE::Dialog
+ slots 'closeClicked()'
+
+ def initialize(parent, name = "char select dlg", modal = false)
+ super(parent, name, modal)
+
+ setGeometry(150, 50, 700, 320)
+ x = 10
+ y = 10
+
+ csLbl = Qt::Label.new("KCharSelect", self)
+ csLbl.setGeometry(x, y, 95, 20)
+ csLbl.show()
+ cs = KDE::CharSelect.new(self, "chselect", nil, Qt::Char.new(0), 0)
+ cs.setGeometry(x, y + 20, 680, 250)
+ cs.show()
+
+ closeBtn = Qt::PushButton.new("Close", self)
+ closeBtn.setGeometry( 610, 280, 60, 22)
+ closeBtn.show()
+
+ connect(closeBtn, SIGNAL("clicked()"), SLOT('closeClicked()'))
+ end
+
+ def closeClicked()
+ done(1)
+ end
+end
+
+def UIWidgets.widKAnimWidget(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIWidgets.widKAuthIcon(parent)
+ parent.currentPageObj = Page5.new(parent)
+end
+
+def UIWidgets.widKButtonBox(parent)
+ parent.currentPageObj = Page5.new(parent)
+end
+
+def UIWidgets.widKCharSelect(parent)
+ dlg = CSDlg.new(parent)
+ dlg.show()
+end
+
+def UIWidgets.widKColorButton(parent)
+ parent.currentPageObj = Page4.new(parent)
+end
+
+def UIWidgets.widKColorCells(parent)
+ parent.currentPageObj = Page4.new(parent)
+end
+
+def UIWidgets.widKColorCombo(parent)
+ parent.currentPageObj = Page2.new(parent)
+end
+
+def UIWidgets.widKColorPatch(parent)
+ parent.currentPageObj = Page4.new(parent)
+end
+
+def UIWidgets.widKComboBox(parent)
+ parent.currentPageObj = Page2.new(parent)
+end
+
+def UIWidgets.widKCompletionBox(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIWidgets.widKContainerLayout(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIWidgets.widKCursor(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIWidgets.widKDatePicker(parent)
+ parent.currentPageObj = Page8.new(parent)
+end
+
+def UIWidgets.widKDateTable(parent)
+ parent.currentPageObj = Page8.new(parent)
+end
+
+def UIWidgets.widKDirectionButton(parent)
+ parent.currentPageObj = Page5.new(parent)
+end
+
+def UIWidgets.widKDualColorButton(parent)
+ parent.currentPageObj = Page4.new(parent)
+end
+
+def UIWidgets.widKTextEdit(parent)
+ parent.currentPageObj = Page1.new(parent)
+end
+
+def UIWidgets.widKEditListBox(parent)
+ parent.currentPageObj = Page2.new(parent)
+end
+
+def UIWidgets.widKFontChooser(parent)
+ parent.currentPageObj = Page3.new(parent)
+end
+
+def UIWidgets.widKHSSelector(parent)
+ parent.currentPageObj = Page4.new(parent)
+end
+
+def UIWidgets.widKIconView(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIWidgets.widKJanusWidget(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+#def UIWidgets.widKKeyButton(parent)
+# parent.currentPageObj = Page5.new(parent)
+
+def UIWidgets.widKKeyChooser(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIWidgets.widKLed(parent)
+ parent.currentPageObj = Page6.new(parent)
+end
+
+def UIWidgets.widKLineEdit(parent)
+ parent.currentPageObj = Page1.new(parent)
+end
+
+def UIWidgets.widKListBox(parent)
+ parent.currentPageObj = Page2.new(parent)
+end
+
+def UIWidgets.widKListView(parent)
+ parent.currentPageObj = PageThisApp.new(parent)
+end
+
+def UIWidgets.widKNumInput(parent)
+ parent.currentPageObj = Page1.new(parent)
+end
+
+def UIWidgets.widKPaletteTable(parent)
+ parent.currentPageObj = Page4.new(parent)
+end
+
+def UIWidgets.widKPasswordEdit(parent)
+ parent.currentPageObj = Page5.new(parent)
+end
+
+def UIWidgets.widKProgress(parent)
+ parent.currentPageObj = Page7.new(parent)
+end
+
+def UIWidgets.widKRootPixmap(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIWidgets.widKMainWindow(parent)
+ parent.currentPageObj = PageThisApp.new(parent)
+end
+
+def UIWidgets.widKRestrictedLine(parent)
+ parent.currentPageObj = Page1.new(parent)
+end
+
+def UIWidgets.widKRuler(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIWidgets.widKSelector(parent)
+ parent.currentPageObj = Page4.new(parent)
+end
+
+def UIWidgets.widKSeparator(parent)
+ parent.currentPageObj = Page7.new(parent)
+end
+
+def UIWidgets.widKSqueezedTextLabel(parent)
+ parent.currentPageObj = Page1.new(parent)
+end
+
+def UIWidgets.widKTabButton(parent)
+ parent.currentPageObj = Page5.new(parent)
+end
+
+def UIWidgets.widKTabCtl(parent)
+ parent.currentPageObj = Page7.new(parent)
+end
+
+def UIWidgets.widKTextBrowser(parent)
+ parent.currentPageObj = PageNotImpl.new(parent)
+end
+
+def UIWidgets.widKURLLabel(parent)
+ parent.currentPageObj = Page5.new(parent)
+end
+
+
+if $0 == __FILE__
+ puts
+ puts "Please run uisampler.rb"
+ puts
+end
+
+end
diff --git a/korundum/rubylib/examples/uimodules/uixml.rb b/korundum/rubylib/examples/uimodules/uixml.rb
new file mode 100644
index 00000000..67be21ac
--- /dev/null
+++ b/korundum/rubylib/examples/uimodules/uixml.rb
@@ -0,0 +1,56 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+require 'Korundum'
+
+module UIXML
+
+class PageLaunch
+ def initialize(parent)
+ page = parent.addPage()
+
+ x = 10
+ y = 10
+
+ launchLbl = Qt::Label.new("Launching application ... please wait\n\nClose launched application to continue", page)
+ launchLbl.setGeometry(x, y, 300, 80)
+ launchLbl.show()
+
+ page.show()
+
+ $kapp.processEvents()
+ end
+end
+
+def UIXML.xmlKActionCollection(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby xmlmenudemo.rb")
+end
+
+def UIXML.xmlKEditToolbar(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby xmlmenudemo.rb")
+end
+
+def UIXML.xmlKEditToolbarWidget(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby xmlmenudemo.rb")
+end
+
+def UIXML.xmlKXMLGUIBuilder(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby xmlmenudemo.rb")
+end
+
+def UIXML.xmlKXMLGUIClient(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby xmlmenudemo.rb")
+end
+
+def UIXML.xmlKXMLGUIFactory(parent)
+ parent.currentPageObj = PageLaunch.new(parent)
+ system("ruby xmlmenudemo.rb")
+end
+
+end
diff --git a/korundum/rubylib/examples/uisampler.rb b/korundum/rubylib/examples/uisampler.rb
new file mode 100644
index 00000000..10af08de
--- /dev/null
+++ b/korundum/rubylib/examples/uisampler.rb
@@ -0,0 +1,238 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+require 'Korundum'
+
+require 'uimodules/uiwidgets.rb'
+require 'uimodules/uidialogs.rb'
+require 'uimodules/uimenus.rb'
+require 'uimodules/uimisc.rb'
+require 'uimodules/uixml.rb'
+
+$listItems = {"Dialogs" =>
+ {"KDE::AboutDialog" => ["KDE::AboutApplication", "KDE::AboutContainer", "KDE::ImageTrackLabel",
+ "KDE::AboutContainerBase", "KDE::AboutContributor", "KDE::AboutWidget"],
+ "KDE::AboutKDE" => [],
+ "KDE::BugReport" => [],
+ "KDE::ColorDialog" => [],
+ "KDE::Dialog" => [],
+ "KDE::DialogBase" => ["KDE::DialogBaseButton", "KDE::DialogBase::SButton", "KDE::DialogBaseTile"],
+ "KDE::FontDialog" => [],
+ "KDE::KeyDialog" => [],
+ "KDE::InputDialog" => [],
+ "KDE::MessageBox" => [],
+ "KDE::PasswordDialog" => [],
+ "KDE::Wizard" => []},
+ "Widgets" =>
+ {"KDE::AnimWidget" => [],
+ "KDE::AuthIcon" => ["KDE::RootPermsIcon", "KDE::WritePermsIcon"],
+ "KDE::ButtonBox" => [],
+ "KDE::CharSelect" => ["KDE::CharSelectTable"],
+ "KDE::ColorButton" => [],
+ "KDE::ColorCells" => [],
+ "KDE::ColorCombo" => [],
+ "KDE::ColorPatch" => [],
+ "KDE::ComboBox" => [],
+ "KDE::CompletionBox" => [],
+ "KDE::ContainerLayout" => ["KDE::ContainerLayout::KContainerLayoutItem"],
+ "KDE::Cursor" => [],
+ "KDE::DatePicker" => ["KDE::DateInternalMonthPicker", "KDE::DateInternalYearSelector"],
+ "KDE::DateTable" => [],
+ "KDE::DualColorButton" => [],
+ "KDE::EditListBox" => [],
+ "KDE::FontChooser" => [],
+ "KDE::HSSelector" => [],
+ "KDE::IconView" => [],
+ "KDE::JanusWidget" => ["KDE::JanusWidget::IconListBox"],
+ "KDE::KeyChooser" => [],
+ "KDE::Led" => [],
+ "KDE::LineEdit" => [],
+ "KDE::ListBox" => [],
+ "KDE::ListView" => [],
+ "KDE::NumInput" => ["KDE::DoubleNumInput", "KDE::IntNumInput"],
+ "KDE::PaletteTable" => [],
+ "KDE::PasswordEdit" => [],
+ "KDE::Progress" => [],
+ "KDE::RootPixmap" => [],
+ "KDE::MainWindow" => [],
+ "KDE::RestrictedLine" => [],
+ "KDE::Ruler" => [],
+ "KDE::Selector" => ["KDE::GradientSelector", "KDE::ValueSelector", "KDE::HSSelector", "KDE::XYSelector"],
+ "KDE::Separator" => [],
+ "KDE::SqueezedTextLabel" => [],
+ "KDE::TabCtl" => [],
+ "KDE::TextBrowser" => [],
+ "KDE::TextEdit" => ["KDE::EdFind", "KDE::EdGotoLine", "KDE::EdReplace"],
+ "KDE::URLLabel" => []},
+ "XML" =>
+ {"KDE::ActionCollection" => [],
+ "KDE::EditToolbar" => [],
+ "KDE::EditToolbarWidget" => [],
+ "KDE::XMLGUIBuilder" => [],
+ "KDE::XMLGUIClient" => ["KDE::XMLGUIClient::DocStruct"],
+ "KDE::XMLGUIFactory" => []},
+ "Menus/Toolbars" =>
+ {"KDE::AccelMenu" => [],
+ "KDE::Action" => ["KDE::FontAction", "KDE::FontSizeAction", "KDE::ListAction", "KDE::RecentFilesAction", "KDE::RadioAction",
+ "KDE::SelectAction", "KDE::ToggleAction"],
+ "KDE::ActionMenu" => [],
+ "KDE::ActionSeparator" => [],
+ "KDE::ContextMenuManager" => [],
+ "KDE::DCOPActionProxy" => [],
+ "KDE::HelpMenu" => [],
+ "KDE::MenuBar" => [],
+ "KDE::PanelApplet" => [],
+ "KDE::PanelExtension" => [],
+ "KDE::PanelMenu" => [],
+ "KDE::PopupFrame" => [],
+ "KDE::PopupMenu" => [],
+ "KDE::PopupTitle" => [],
+ "KDE::StatusBar" => [],
+ "KDE::StatusBarLabel" => [],
+ "KDE::StdAction" => [],
+ "KDE::ToolBar" => ["KDE::ToolBarButton", "KDE::ToolBarButtonList", "KDE::ToolBarPopupAction",
+ "KDE::ToolBarRadioGroup", "KDE::ToolBarSeparator"],
+ "KDE::WindowListMenu" => []},
+ "Other" =>
+ {"KDE::AlphaPainter" => [],
+ "KDE::CModule" => [],
+ "KDE::Color" => [],
+ "KDE::ColorDrag" => [],
+ "KDE::Command" => ["KDE::MacroCommand"],
+ "KDE::CommandHistory" => [],
+ "KDE::DateValidator" => [],
+ "KDE::DockWindow" => ["KDE::DockButton_Private - KPanelMenu", "KDE::DockButton_Private",
+ "KDE::DockSplitter", "KDE::DockTabCtl_PrivateStruct", "KDE::DockWidgetAbstractHeader",
+ "KDE::DockWidgetAbstractHeaderDrag", "KDE::DockWidgetHeader",
+ "KDE::DockWidgetHeaderDrag", "KDE::DockWidgetPrivate"],
+ "KDE::DoubleValidator" => [],
+ "KDE::IntValidator" => [],
+ "KDE::PixmapIO" => [],
+ "KDE::SharedPixmap" => [],
+ "KDE::SystemTray" => [],
+ "KDE::ThemeBase" => ["KDE::ThemeCache", "KDE::ThemePixmap", "KDE::ThemeStyle"],
+ "QXEmbed" => []}}
+
+BLANK_MSG = <<END_OF_STRING
+<b>UISampler</b> - provides examples of <b>Korundum</b> widgets<p>
+Select a dialog/widget/menu/etc example from the tree at left
+END_OF_STRING
+
+
+class MainWin < KDE::MainWindow
+ TREE_WIDTH = 220
+
+ slots 'lvClicked(QListViewItem*)'
+
+ attr_accessor :edit, :currentPageObj
+
+ def initialize(*args)
+ super
+
+ setCaption("Samples of Korundum widget usage")
+ # The following leave about 375 x 390 for the rt hand panel
+ mainGeom = Qt::Rect.new(0, 0, 640, 500)
+ setGeometry(mainGeom)
+
+ # create the main view - list view on the left and an
+ # area to display frames on the right
+ @mainView = Qt::Splitter.new(self, "main view")
+ @tree = KDE::ListView.new(@mainView, "tree")
+ @page = Qt::WidgetStack.new(@mainView, "page")
+ blankPage = Qt::Widget.new(@page, "blank")
+ blankPage.setGeometry(0, 0, 375, 390)
+ blankPage.setBackgroundMode(Qt::Widget::PaletteBase)
+
+ blankLbl = Qt::Label.new(BLANK_MSG, blankPage)
+ blankLbl.setGeometry(40, 10, 380, 150)
+ blankLbl.setBackgroundMode(Qt::Widget::PaletteBase)
+
+ blankPM = Qt::Pixmap.new("rbtestimage.png")
+ pmLbl = Qt::Label.new("", blankPage)
+ pmLbl.setPixmap(blankPM)
+ pmLbl.setGeometry(40, 160, 300, 200)
+ pmLbl.setBackgroundMode(Qt::Widget::PaletteBase)
+
+ @page.addWidget(blankPage, 1)
+ @page.raiseWidget(1)
+
+ setCentralWidget(@mainView)
+
+ initListView()
+ connect(@tree, SIGNAL("clicked(QListViewItem*)"), self, SLOT('lvClicked(QListViewItem*)'))
+
+ @edit = nil
+ @currentPageObj = nil
+ @prefix = {"Dialogs" => "UIDialogs::dlg", "Widgets" => "UIWidgets::wid", "XML" => "UIXML::xml",
+ "Menus/Toolbars" => "UIMenus::menu", "Other" => "UIMisc::misc"}
+ end
+
+ def initListView()
+ @tree.addColumn("Category", TREE_WIDTH - 21)
+# tree.setMaximumWidth(treeWidth)
+ @mainView.setSizes([TREE_WIDTH, 375])
+ @tree.setRootIsDecorated(true)
+ @tree.setVScrollBarMode(Qt::ScrollView::AlwaysOn)
+ topLevel = $listItems.keys()
+ topLevel.each do |item_1|
+ parent = Qt::ListViewItem.new(@tree, String.new(item_1))
+ secondLevel = $listItems[item_1].keys()
+ secondLevel.each do |item_2|
+ child = Qt::ListViewItem.new(parent, String.new(item_2))
+ $listItems[item_1][item_2].each do |item_3|
+ Qt::ListViewItem.new(child, String.new(item_3))
+ end
+ end
+ end
+ end
+
+ def lvClicked(lvItem)
+ if lvItem.nil?
+ return
+ end
+
+ if $listItems.keys().include?(lvItem.text(0))
+ return
+ end
+
+ p = lvItem.parent()
+ if $listItems.keys().include?(p.text(0))
+ pfx = @prefix[p.text(0)]
+ funcCall = pfx + lvItem.text(0).sub("KDE::","K") + "(self)"
+ else
+ pfx = @prefix[p.parent().text(0)]
+ funcCall = pfx + lvItem.parent().text(0).sub("KDE::","K") + "(self)"
+ end
+ eval funcCall
+ end
+
+ def addPage()
+ @edit = nil
+ @currentPageObj = nil
+ current = @page.widget(2)
+ if !current.nil?
+ @page.removeWidget(current)
+ current.dispose
+ end
+
+ newPage = Qt::Widget.new(@page)
+ newPage.setGeometry(0, 0, 375, 390)
+# newPage.setBackgroundMode(QWidget.PaletteBase)
+ @page.addWidget(newPage, 2)
+ @page.raiseWidget(2)
+
+ return newPage
+ end
+end
+
+#-------------------- main ------------------------------------------------
+
+appName = "UISampler"
+about = KDE::AboutData.new("uisampler", appName, "0.1")
+KDE::CmdLineArgs.init(ARGV, about)
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show
+app.exec
+
diff --git a/korundum/rubylib/examples/xmlgui.rb b/korundum/rubylib/examples/xmlgui.rb
new file mode 100755
index 00000000..8f021ccf
--- /dev/null
+++ b/korundum/rubylib/examples/xmlgui.rb
@@ -0,0 +1,42 @@
+#!/usr/bin/env ruby
+
+require 'Korundum'
+require 'tempfile'
+
+about = KDE::AboutData.new("one", "two", "three")
+#KDE::CmdLineArgs.init(about)
+KDE::CmdLineArgs.init(ARGV, about)
+app = KDE::Application.new()
+
+class Receiver < Qt::Object
+ slots "pressed_up()", "close()", "quit()"
+ def initialize main, *k
+ super(*k)
+ @main = main
+ end
+ def quit
+ @main.close
+ end
+end
+
+RAction = Struct.new :xmlgui_name, :string, :accel, :something
+class RAction
+ def create receiver, slot, action_collection
+ p self.string
+ KDE::Action.new self.string, self.accel, receiver, slot, action_collection, self.xmlgui_name
+ end
+end
+
+# { Quit, KStdAccel::Quit, "file_quit", I18N_NOOP("&Quit"), 0, "exit" },
+std_actions = { :quit => RAction.new( "file_quit", ("&Quit"), KDE::Shortcut.new(), "exit" ) }
+
+begin
+ m = KDE::MainWindow.new
+ @r = Receiver.new m
+ mActionCollection = m.actionCollection
+ action = std_actions[:quit].create @r, SLOT("quit()"), mActionCollection
+ m.createGUI Dir.pwd + "/xmlgui.rc"
+ app.setMainWidget(m)
+ m.show
+ app.exec()
+end
diff --git a/korundum/rubylib/examples/xmlgui.rc b/korundum/rubylib/examples/xmlgui.rc
new file mode 100644
index 00000000..1c5d03fc
--- /dev/null
+++ b/korundum/rubylib/examples/xmlgui.rc
@@ -0,0 +1,18 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="xmlgui" version="1">
+
+<MenuBar>
+
+ <Menu name="file" noMerge="1"><text>&amp;File</text>
+ <Action name="file_open"/>
+ <Action name="file_save"/>
+ <Action name="file_save_as"/>
+ <Separator/>
+ <Action name="file_print"/>
+ <Separator/>
+ <Action name="file_quit"/>
+ </Menu>
+
+</MenuBar>
+
+</kpartgui>
diff --git a/korundum/rubylib/examples/xmlmenudemo.rb b/korundum/rubylib/examples/xmlmenudemo.rb
new file mode 100644
index 00000000..a246ac25
--- /dev/null
+++ b/korundum/rubylib/examples/xmlmenudemo.rb
@@ -0,0 +1,314 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+This template constructs an application with menus, toolbar and statusbar.
+It uses KDE classes and methods that simplify the task of building and
+operating a GUI. It is recommended that this approach be used, rather
+than the primitive approach in menuapp1.py
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+require 'Korundum'
+
+class MainWin < KDE::MainWindow
+
+ STATUSBAR_LEFT = 1
+ STATUSBAR_MIDDLE = 2
+ STATUSBAR_RIGHT = 3
+
+ slots 'slotFake()', 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotRadio()',
+ 'slotQuit()', 'slotUndo()', 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()',
+ 'slotFindNext()', 'slotReplace()', 'slotSpecial()', 'slotToggle2()', 'slotZoomIn()', 'slotZoomOut()'
+
+ def initialize(*args)
+ super
+
+ initActions()
+ setGeometry(0, 0, 350, 200)
+
+ # The second arg of createGUI needs to be 0(or false)
+ # to enable XMLGUI features like ActionList(in 'dynamicActions')
+ # If the default is used(true), the dynamic actions will not
+ # appear in the menus
+ uifilebase = Dir.getwd + '/xmlmenudemoui.rc'
+ createGUI(uifilebase, false)
+
+ dynamicActions()
+
+ # Can't do this until the toolBar has been created in createGUI
+ stretchlbl = Qt::Label.new("", toolBar())
+ toolBar().setStretchableWidget(stretchlbl)
+
+ initStatusBar()
+
+ @saveAction.setEnabled(false)
+ @saveAsAction.setEnabled(false)
+ end
+
+ def initActions()
+ # This is used in all of the KDE::Action/KDE::StdAction constructors --
+ # Seems more efficient to only do the call once
+ acts = actionCollection()
+
+ # "File" menu items
+ newAction = KDE::StdAction.openNew(self, SLOT('slotNew()'), acts)
+ openAction = KDE::StdAction.open(self, SLOT('slotOpen()'), acts)
+ @saveAction = KDE::StdAction.save(self, SLOT('slotSave()'), acts)
+ @saveAsAction = KDE::StdAction.saveAs(self, SLOT('slotSaveAs()'), acts)
+ printAction = KDE::StdAction.print(self, SLOT('slotPrint()'), acts)
+ quitAction = KDE::StdAction.quit(self, SLOT('slotQuit()'), acts)
+
+ # "Edit" menu items
+ undoAction = KDE::StdAction.undo(self, SLOT('slotUndo()'), acts)
+ redoAction = KDE::StdAction.redo(self, SLOT('slotRedo()'), acts)
+ cutAction = KDE::StdAction.cut(self, SLOT('slotCut()'), acts)
+ copyAction = KDE::StdAction.copy(self, SLOT('slotCopy()'), acts)
+ pasteAction = KDE::StdAction.paste(self, SLOT('slotPaste()'), acts)
+ findAction = KDE::StdAction.find(self, SLOT('slotFind()'), acts)
+ findNextAction = KDE::StdAction.findNext(self, SLOT('slotFindNext()'), acts)
+ replaceAction = KDE::StdAction.replace(self, SLOT('slotReplace()'), acts)
+
+ # NOTE!!!! You must specify a parent and name for the action object in its constructor
+ # Normally in a constructor like
+ #
+ # someObject(Qt::Widget *parent = 0, const char *name = 0)
+ #
+ # the parent may or may not be assigned, but widgets usually ignore the
+ # name argument. For an action of *any* type(other than KDE::StdAction),
+ # the 'name' argument is what is used to load the action into the menus
+ # and toolBar(in the line below, "specialActionName"). The XMLGUI mechanism
+ # has no way to find out about the action objects except through their
+ # object names - the variable the object is assigned to('specialAction')
+ # has no meaning in XNLGUI terms except through the objects 'name' member value
+
+ specialAction = KDE::Action.new(i18n("Special"), KDE::Shortcut.new(0), self, SLOT('slotSpecial()'), acts, "specialActionName")
+
+ # Demo menu items
+
+ # KDE::ToggleAction has an isChecked member and emits the "toggle" signal
+ toggle1Action = KDE::ToggleAction.new("Toggle 1", KDE::Shortcut.new(0), acts, "toggle1Action")
+ toggle2Action = KDE::ToggleAction.new("Toggle 2", KDE::Shortcut.new(0), self, SLOT('slotToggle2()'), acts, "toggle2Action")
+
+ # A separator - create once/use everywhere
+ separateAction = KDE::ActionSeparator.new(acts, "separateAction")
+
+ # Font stuff in menus or toolbar
+ fontAction = KDE::FontAction.new("Font", KDE::Shortcut.new(0), acts, "fontAction")
+ fontSizeAction = KDE::FontSizeAction.new("Font Size", KDE::Shortcut.new(0), acts, "fontSizeAction")
+
+ fontAction.setComboWidth(150)
+ fontSizeAction.setComboWidth(75)
+
+ # Need to assign an icon to actionMenu below
+ icons = KDE::IconLoader.new()
+ iconSet = Qt::IconSet.new(icons.loadIcon("viewmag", KDE::Icon::Toolbar))
+
+ # Nested menus using KDE::Actions.new(also nested on toolbar)
+ actionMenu = KDE::ActionMenu.new("Action Menu", acts, "actionMenu")
+ actionMenu.setIconSet(iconSet)
+
+ # By using KDE::StdAction here, the XMLGUI mechanism will automatically
+ # create a 'View' menu and insert "Zoom In" and "Zoom Out" objects
+ # in it. This happens because before parsing our *ui.rc file,
+ # the standard KDE::DE file config/ui/ui_standards.rc is parsed, and
+ # then our *ui.rc file is merged with the result - this gives KDE::DE
+ # menus and toolBars a standard "look" and item placement(including
+ # separators). Creating the KDE::StdActions alone is sufficient - you
+ # could delete their references from the *ui.rc file and the menu
+ # items would still be created via ui_standards.rc
+ actionMenu.insert(KDE::StdAction.zoomIn(self, SLOT('slotZoomIn()'), acts))
+ actionMenu.insert(KDE::StdAction.zoomOut(self, SLOT('slotZoomOut()'), acts))
+
+ radio1Action = KDE::RadioAction.new("Radio 1", KDE::Shortcut.new(0), self, SLOT('slotRadio()'), acts, "radio1")
+ radio1Action.setExclusiveGroup("Radio")
+ radio1Action.setChecked(true)
+ radio2Action = KDE::RadioAction.new("Radio 2", KDE::Shortcut.new(0), self, SLOT('slotRadio()'), acts, "radio2")
+ radio2Action.setExclusiveGroup("Radio")
+ radio3Action = KDE::RadioAction.new("Radio 3", KDE::Shortcut.new(0), self, SLOT('slotRadio()'), acts, "radio3")
+ radio3Action.setExclusiveGroup("Radio")
+ end
+
+
+ def initStatusBar()
+ statusBar().insertItem("", STATUSBAR_LEFT, 1000, true)
+ statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true)
+ statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true)
+ end
+
+ def dynamicActions()
+ # This creates something like a 'recent files list' in the 'File' menu
+ # (There is a KDE::RecentFilesAction that probably should be used instead,
+ # but this demos the use of action lists)
+ # The code here corresponds to the <ActionList name="recent"/> entry
+ # in the rc file
+
+ # Just fake some filenames for now
+ fakeFiles = ["kaction.sip", "kxmlguiclient.sip"]
+
+ # Clear the old entries, so we don't end up accumulating entries in the menu
+ unplugActionList("recent");
+ dynamicActionsList = []
+
+ # Create a KDE::Action for each entry and store the KDE::Actions in a list
+ # Use 'nil' for the KDE::ActionCollection argument in the KDE::Action constructor
+ # in this case only
+ (0...fakeFiles.length).each do |i|
+ act = KDE::Action.new(i18n(" &#{i.to_s} #{fakeFiles[i]}"), KDE::Shortcut.new(0),
+ self, SLOT('slotFake()'), nil, fakeFiles[i].sub(/.sip$/,'') + "open")
+ dynamicActionsList << act
+ end
+
+ # Update the menu with the most recent KDE::Actions
+ plugActionList("recent", dynamicActionsList)
+ end
+
+
+#-------------------- slots -----------------------------------------------
+
+ def slotFake()
+ # sender() should be called before anything else
+ # (including "notImpl") so the correct sender
+ # value is returned
+ sender = sender().name()
+ notImpl("Recent files(#{sender})")
+ end
+
+ # 'id' is for toolbar button signals - ignored for menu signals
+ def slotNew(id = -1)
+ notImpl("New")
+ end
+
+ def slotOpen(id = -1)
+ notImpl("Open")
+ end
+
+ def slotSave(id = -1)
+ notImpl("Save")
+ end
+
+ def slotSaveAs()
+ notImpl("Save As")
+ end
+
+ def slotPrint()
+ notImpl("Print")
+ end
+
+ def slotQuit()
+ notImpl("Quit")
+ end
+
+ def slotUndo()
+ notImpl("Undo")
+ end
+
+ def slotRedo()
+ notImpl("Redo")
+ end
+
+ def slotCut(id = -1)
+ notImpl("Cut")
+ end
+
+ def slotCopy(id = -1)
+ notImpl("Copy")
+ end
+
+ def slotPaste(id = -1)
+ notImpl("Paste")
+ end
+
+ def slotFind()
+ notImpl("Find")
+ end
+
+ def slotFindNext()
+ notImpl("Find Next")
+ end
+
+ def slotReplace()
+ notImpl("Replace")
+ end
+
+ def slotSpecial()
+ notImpl("Special")
+ end
+
+ def slotToggle2()
+ notImpl("Toggle")
+ end
+
+ def slotZoomIn()
+ notImpl("Zoom In")
+ end
+
+ def slotZoomOut()
+ notImpl("Zoom Out")
+ end
+
+ def slotRadio()
+ sender = sender().name()
+ notImpl("Radio #{sender}")
+ end
+
+ def notImpl(item = "Feature")
+ statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT)
+ KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented")
+ statusBar().changeItem("", STATUSBAR_LEFT)
+ end
+end
+
+
+#-------------------- main ------------------------------------------------
+
+description = "A basic application template"
+version = "1.0"
+
+# The appName(xmlmenudemo - first argument) is required
+# if the program is to automatically locate it *ui.rc file
+aboutData = KDE::AboutData.new("xmlmenudemo", "xmlmenudemo",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+# mainpath = os.path.dirname(os.path.abspath(sys.argv[0]))
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show
+app.exec
diff --git a/korundum/rubylib/examples/xmlmenudemoui.rc b/korundum/rubylib/examples/xmlmenudemoui.rc
new file mode 100644
index 00000000..58f07cf6
--- /dev/null
+++ b/korundum/rubylib/examples/xmlmenudemoui.rc
@@ -0,0 +1,49 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd" ><kpartgui name="xmlmenudemo" version="1">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="newAction"/>
+ <Action name="openAction"/>
+ <Action name="saveAction"/>
+ <Action name="saveAsAction"/>
+ <Action name="printAction"/>
+ <Action name="quitAction"/>
+ <ActionList name="recent" />
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="undoAction"/>
+ <Action name="redoAction"/>
+ <Action name="cutAction"/>
+ <Action name="copyAction"/>
+ <Action name="pasteAction"/>
+ <Action name="findAction"/>
+ <Action name="findNextAction"/>
+ <Action name="replaceAction"/>
+ <Action name="specialActionName"/>
+ </Menu>
+ <Menu name="demo"><text>&amp;Demo</text>
+ <Action name="toggle1Action"/>
+ <Action name="toggle2Action"/>
+ <Action name="separateAction"/>
+ <Action name="fontAction"/>
+ <Action name="fontSizeAction"/>
+ <Action name="separateAction"/>
+ <Action name="actionMenu"/>
+ <Action name="radio1"/>
+ <Action name="radio2"/>
+ <Action name="radio3"/>
+ </Menu>
+</MenuBar>
+<ToolBar name="mainToolBar">
+ <Action name="actionMenu"/>
+ <Action name="separateAction"/>
+ <Action name="separateAction"/>
+ <Action name="fontAction"/>
+ <Action name="separateAction"/>
+ <Action name="fontSizeAction" comboWidth="75"/>
+ <Action name="radio1"/>
+ <Action name="radio2"/>
+ <Action name="radio3"/>
+ <Merge/>
+</ToolBar>
+<ActionProperties />
+</kpartgui>
diff --git a/korundum/rubylib/korundum/Korundum.cpp b/korundum/rubylib/korundum/Korundum.cpp
new file mode 100644
index 00000000..6cd3045a
--- /dev/null
+++ b/korundum/rubylib/korundum/Korundum.cpp
@@ -0,0 +1,1183 @@
+/***************************************************************************
+ Korundum.cpp - Runtime for KDE services, DCOP etc
+ -------------------
+ begin : Sun Sep 28 2003
+ copyright : (C) 2003-2004 by Richard Dale
+ email : Richard_Dale@tipitina.demon.co.uk
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qmap.h>
+#include <qdatastream.h>
+
+#include <kdeversion.h>
+#include <dcopclient.h>
+#include <dcopobject.h>
+#include <dcopref.h>
+#include <kapplication.h>
+#include <kurl.h>
+#if KDE_VERSION >= 0x030200
+#include <kconfigskeleton.h>
+#endif
+#include <kio/global.h>
+#include <kparts/browserextension.h>
+#include <kde_terminal_interface.h>
+
+#include <ruby.h>
+
+#include <marshall.h>
+#include <qtruby.h>
+#include <smokeruby.h>
+#include <smoke.h>
+
+extern "C" {
+extern VALUE qt_internal_module;
+extern VALUE kconfigskeleton_class;
+extern VALUE kconfigskeleton_itemenum_choice_class;
+extern VALUE kio_udsatom_class;
+extern VALUE konsole_part_class;
+extern VALUE set_obj_info(const char * className, smokeruby_object * o);
+extern void set_kde_resolve_classname(const char * (*kde_resolve_classname) (Smoke*, int, void *));
+extern const char * kde_resolve_classname(Smoke* smoke, int classId, void * ptr);
+};
+
+extern TypeHandler KDE_handlers[];
+extern void install_handlers(TypeHandler *);
+extern Smoke *qt_Smoke;
+
+
+static VALUE kde_internal_module;
+Marshall::HandlerFn getMarshallFn(const SmokeType &type);
+
+/*
+ Copy items from the stack to the stream, each item has a corresponding description in the
+ args array of MocArguments. Used for marshalling the args to DCOP calls and sends, emitting
+ DCOP signals, and converting the return value of a DCOP slot to a stream.
+*/
+static void
+smokeStackToStream(Marshall *m, Smoke::Stack stack, QDataStream* stream, int items, MocArgument* args)
+{
+ for(int i = 0; i < items; i++) {
+ switch(args[i].argType) {
+ case xmoc_bool:
+ *stream << stack[i].s_bool;
+ break;
+ case xmoc_int:
+ *stream << stack[i].s_int;
+ break;
+ case xmoc_double:
+ *stream << stack[i].s_double;
+ break;
+ case xmoc_charstar:
+ *stream << (char *) stack[i].s_voidp;
+ break;
+ case xmoc_QString:
+ {
+ QString temp((const QString&) *((QString *) stack[i].s_voidp));
+ *stream << temp;
+ }
+ break;
+ default:
+ {
+ const SmokeType &t = args[i].st;
+ switch(t.elem()) {
+ case Smoke::t_bool:
+ *stream << stack[i].s_bool;
+ break;
+ case Smoke::t_char:
+ *stream << stack[i].s_char;
+ break;
+ case Smoke::t_uchar:
+ *stream << stack[i].s_uchar;
+ break;
+ case Smoke::t_short:
+ *stream << stack[i].s_short;
+ break;
+ case Smoke::t_ushort:
+ *stream << stack[i].s_ushort;
+ break;
+ case Smoke::t_int:
+ *stream << stack[i].s_int;
+ break;
+ case Smoke::t_uint:
+ *stream << stack[i].s_uint;
+ break;
+ case Smoke::t_long:
+ *stream << stack[i].s_long;
+ break;
+ case Smoke::t_ulong:
+ *stream << stack[i].s_ulong;
+ break;
+ case Smoke::t_float:
+ *stream << stack[i].s_float;
+ break;
+ case Smoke::t_double:
+ *stream << stack[i].s_double;
+ break;
+ case Smoke::t_enum:
+ m->unsupported();
+ break;
+ case Smoke::t_class:
+ case Smoke::t_voidp:
+ {
+ // Special case any types which are in the Smoke runtime, but
+ // don't have QDataStream '<<' methods
+ if (strcmp(t.name(), "QCString") == 0) {
+ QCString temp((const QCString&) *((QCString *) stack[i].s_voidp));
+ *stream << temp;
+ break;
+ } else if (strcmp(t.name(), "QCStringList") == 0) {
+ QCStringList temp((const QCStringList&) *((QCStringList *) stack[i].s_voidp));
+ *stream << temp;
+ break;
+ } else if (strcmp(t.name(), "QStringList") == 0) {
+ QStringList temp((const QStringList&) *((QStringList *) stack[i].s_voidp));
+ *stream << temp;
+ break;
+ } else if (strcmp(t.name(), "KURL::List") == 0) {
+ KURL::List temp((const KURL::List&) *((KURL::List *) stack[i].s_voidp));
+ *stream << temp;
+ break;
+ } else if (strcmp(t.name(), "QMap<QCString,DCOPRef>") == 0) {
+ QMap<QCString,DCOPRef> temp((const QMap<QCString,DCOPRef>&) *((QMap<QCString,DCOPRef>*) stack[i].s_voidp));
+ *stream << temp;
+ break;
+ }
+
+ // Look for methods of the form: QDataStream & operator<<(QDataStream&, const MyClass&)
+ Smoke::Index meth = t.smoke()->findMethod("QGlobalSpace", "operator<<##");
+ Smoke::Index ix;
+ if (meth > 0) {
+ ix = t.smoke()->methodMaps[meth].method;
+ ix = -ix; // turn into ambiguousMethodList index
+ while (t.smoke()->ambiguousMethodList[ix]) {
+ Smoke::Method &method = t.smoke()->methods[t.smoke()->ambiguousMethodList[ix]];
+ QString refType("const ");
+ refType += t.name();
+ refType += "&";
+ if ( strcmp( "QDataStream&",
+ t.smoke()->types[t.smoke()->argumentList[method.args+0]].name ) == 0
+ && strcmp( refType.latin1(),
+ t.smoke()->types[t.smoke()->argumentList[method.args+1]].name ) == 0 )
+ {
+ Smoke::ClassFn fn = t.smoke()->classes[method.classId].classFn;
+ Smoke::StackItem local_stack[3];
+ local_stack[1].s_voidp = stream;
+ local_stack[2].s_voidp = stack[i].s_voidp;
+ // Call the QDataStream marshaller write method
+ // with the instance to be marshalled
+ (*fn)(method.method, 0, local_stack);
+ break;
+ }
+ ix++;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ return;
+}
+
+/*
+ Copy items from the stream to the stack, each item has a corresponding description in the
+ args array of MocArguments. Used for marshalling the arguments to a DCOP slot invocation,
+ and for converting a dcop reply to a ruby value.
+*/
+static void
+smokeStackFromStream(Marshall *m, Smoke::Stack stack, QDataStream* stream, int items, MocArgument* args)
+{
+ for(int i = 0; i < items; i++) {
+ switch(args[i].argType) {
+ case xmoc_bool:
+ {
+ *stream >> stack[i].s_bool;
+ break;
+ }
+ case xmoc_int:
+ {
+ *stream >> stack[i].s_int;
+ break;
+ }
+ case xmoc_double:
+ *stream >> stack[i].s_double;
+ break;
+ case xmoc_charstar:
+ *stream >> (char *&) stack[i].s_voidp;
+ break;
+ case xmoc_QString:
+ {
+ QString temp;
+ *stream >> temp;
+ stack[i].s_voidp = new QString(temp);
+ }
+ break;
+ default: // case xmoc_ptr:
+ {
+ const SmokeType &t = args[i].st;
+ switch(t.elem()) {
+ case Smoke::t_bool:
+ {
+ *stream >> stack[i].s_bool;
+ break;
+ }
+ case Smoke::t_char:
+ {
+ *stream >> stack[i].s_char;
+ break;
+ }
+ case Smoke::t_uchar:
+ {
+ *stream >> stack[i].s_uchar;
+ break;
+ }
+ case Smoke::t_short:
+ {
+ *stream >> stack[i].s_short;
+ break;
+ }
+ case Smoke::t_ushort:
+ {
+ *stream >> stack[i].s_ushort;
+ break;
+ }
+ case Smoke::t_int:
+ {
+ *stream >> stack[i].s_int;
+ break;
+ }
+ case Smoke::t_uint:
+ {
+ *stream >> stack[i].s_uint;
+ break;
+ }
+ case Smoke::t_long:
+ {
+ *stream >> stack[i].s_long;
+ break;
+ }
+ case Smoke::t_ulong:
+ {
+ *stream >> stack[i].s_ulong;
+ break;
+ }
+ case Smoke::t_float:
+ *stream >> stack[i].s_float;
+ break;
+ case Smoke::t_double:
+ *stream >> stack[i].s_double;
+ break;
+ case Smoke::t_enum:
+ m->unsupported();
+ break;
+ case Smoke::t_class:
+ case Smoke::t_voidp:
+ {
+ // Special case any types which are in the Smoke runtime, but
+ // don't have QDataStream '>>' methods
+ if (strcmp(t.name(), "QCString") == 0) {
+ QCString temp;
+ *stream >> temp;
+ stack[i].s_voidp = new QCString(temp);
+ break;
+ } else if (strcmp(t.name(), "QCStringList") == 0) {
+ QCStringList temp;
+ *stream >> temp;
+ stack[i].s_voidp = new QCStringList(temp);
+ break;
+ } else if (strcmp(t.name(), "QStringList") == 0) {
+ QStringList temp;
+ *stream >> temp;
+ stack[i].s_voidp = new QStringList(temp);
+ break;
+ } else if (strcmp(t.name(), "KURL::List") == 0) {
+ KURL::List temp;
+ *stream >> temp;
+ stack[i].s_voidp = new KURL::List(temp);
+ break;
+ } else if (strcmp(t.name(), "QMap<QCString,DCOPRef>") == 0) {
+ QMap<QCString,DCOPRef> temp;
+ *stream >> temp;
+ stack[i].s_voidp = new QMap<QCString,DCOPRef>(temp);
+ break;
+ }
+
+ // First construct an instance to read the QDataStream into,
+ // so look for a no args constructor
+ Smoke::Index ctorId = t.smoke()->idMethodName(t.name());
+ Smoke::Index ctorMeth = t.smoke()->findMethod(t.classId(), ctorId);
+ Smoke::Index ctor = t.smoke()->methodMaps[ctorMeth].method;
+ if(ctor < 1) {
+ stack[i].s_voidp = 0;
+ m->unsupported();
+ break; // Ambiguous or non-existent method, shouldn't happen with a no arg constructor
+ }
+ // Okay, ctor is the constructor. Time to call it.
+ Smoke::StackItem ctor_stack[1];
+ ctor_stack[0].s_voidp = 0;
+ Smoke::ClassFn classfn = t.smoke()->classes[t.classId()].classFn;
+ (*classfn)(t.smoke()->methods[ctor].method, 0, ctor_stack);
+ stack[i].s_voidp = ctor_stack[0].s_voidp;
+
+ // Look for methods of the form: QDataStream & operator>>(QDataStream&, MyClass&)
+ Smoke::Index meth = t.smoke()->findMethod("QGlobalSpace", "operator>>##");
+ Smoke::Index ix;
+ if (meth > 0) {
+ ix = t.smoke()->methodMaps[meth].method;
+ ix = -ix; // turn into ambiguousMethodList index
+ while (t.smoke()->ambiguousMethodList[ix]) {
+ Smoke::Method &method = t.smoke()->methods[t.smoke()->ambiguousMethodList[ix]];
+ QString refType(t.name());
+ refType += "&";
+ if ( strcmp( "QDataStream&",
+ t.smoke()->types[t.smoke()->argumentList[method.args+0]].name ) == 0
+ && strcmp( refType.latin1(),
+ t.smoke()->types[t.smoke()->argumentList[method.args+1]].name ) == 0 )
+ {
+ Smoke::ClassFn fn = t.smoke()->classes[method.classId].classFn;
+ Smoke::StackItem local_stack[3];
+ local_stack[1].s_voidp = stream;
+ local_stack[2].s_voidp = stack[i].s_voidp;
+ // Call the QDataStream marshaller read method
+ // on the instance to be marshalled
+ (*fn)(method.method, 0, local_stack);
+ break;
+ }
+ ix++;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*
+ Converts a QByteArray returned from a DCOP call to a ruby value.
+*/
+class DCOPReturn : public Marshall {
+ MocArgument * _replyType;
+ Smoke::Stack _stack;
+ VALUE * _result;
+public:
+ DCOPReturn(QDataStream & retval, VALUE * result, VALUE replyType)
+ {
+ _result = result;
+ VALUE temp = rb_funcall(qt_internal_module, rb_intern("getMocArguments"), 1, replyType);
+ Data_Get_Struct(rb_ary_entry(temp, 1), MocArgument, _replyType);
+ _stack = new Smoke::StackItem[1];
+ smokeStackFromStream(this, _stack, &retval, 1, _replyType);
+ Marshall::HandlerFn fn = getMarshallFn(type());
+ (*fn)(this);
+ }
+
+ SmokeType type() {
+ return _replyType[0].st;
+ }
+ Marshall::Action action() { return Marshall::ToVALUE; }
+ Smoke::StackItem &item() { return _stack[0]; }
+ VALUE * var() {
+ return _result;
+ }
+
+ void unsupported()
+ {
+ rb_raise(rb_eArgError, "Cannot handle '%s' as DCOP return-type", type().name());
+ }
+ Smoke *smoke() { return type().smoke(); }
+
+ void next() {}
+
+ bool cleanup() { return false; }
+
+ ~DCOPReturn()
+ {
+ delete[] _stack;
+ }
+};
+
+class DCOPCall : public Marshall {
+ VALUE _obj;
+ QCString & _remFun;
+ int _items;
+ VALUE *_sp;
+ QByteArray *_data;
+ QDataStream *_stream;
+ int _id;
+ MocArgument *_args;
+ bool _useEventLoop;
+ int _timeout;
+ int _cur;
+ Smoke::Stack _stack;
+ VALUE _result;
+ bool _called;
+public:
+ DCOPCall(VALUE obj, QCString & remFun, int items, VALUE *sp, VALUE args, bool useEventLoop, int timeout) :
+ _obj(obj), _remFun(remFun), _items(items), _sp(sp),
+ _useEventLoop(useEventLoop), _timeout(timeout), _cur(-1), _called(false)
+ {
+ _data = new QByteArray();
+ _stream = new QDataStream(*_data, IO_WriteOnly);
+ Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args);
+ _stack = new Smoke::StackItem[_items];
+ _result = Qnil;
+ }
+
+ ~DCOPCall()
+ {
+ delete[] _stack;
+ delete _data;
+ delete _stream;
+ }
+ const MocArgument &arg() { return _args[_cur]; }
+ SmokeType type() { return arg().st; }
+ Marshall::Action action() { return Marshall::FromVALUE; }
+ Smoke::StackItem &item() { return _stack[_cur]; }
+ VALUE * var() {
+ if(_cur < 0) return &_result;
+ return _sp + _cur;
+ }
+
+ void unsupported()
+ {
+ rb_raise(rb_eArgError, "Cannot handle '%s' as a DCOP call argument", type().name());
+ }
+
+ Smoke *smoke() { return type().smoke(); }
+
+ void dcopCall()
+ {
+ if(_called) return;
+ _called = true;
+
+ smokeStackToStream(this, _stack, _stream, _items, _args);
+ smokeruby_object *o = value_obj_info(_obj);
+ DCOPRef * dcopRef = (DCOPRef *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("DCOPRef"));
+ DCOPClient* dc = dcopRef->dcopClient();
+ QCString replyType;
+ QByteArray dataReceived;
+#if KDE_VERSION >= 0x030200
+ bool ok = dc->call(dcopRef->app(), dcopRef->obj(), _remFun, *_data, replyType, dataReceived, _useEventLoop, _timeout);
+#else
+ bool ok = dc->call(dcopRef->app(), dcopRef->obj(), _remFun, *_data, replyType, dataReceived, _useEventLoop);
+#endif
+
+ if (!ok) {
+ // Note that a failed dcop call returns 'nil', not 'false'
+ _result = Qnil;
+ return;
+ } else if (replyType == "void" || replyType == "ASYNC") {
+ _result = Qtrue;
+ return;
+ }
+
+ QDataStream ds(dataReceived, IO_ReadOnly);
+
+ if (replyType == "QValueList<DCOPRef>") {
+ // Special case QValueList<DCOPRef> as a QDataStream marshaller
+ // isn't in the Smoke runtime
+ QValueList<DCOPRef> valuelist;
+ ds >> valuelist;
+ _result = rb_ary_new();
+ for (QValueListIterator<DCOPRef> it = valuelist.begin(); it != valuelist.end(); ++it) {
+ void *p = new DCOPRef(*it);
+ VALUE obj = getPointerObject(p);
+
+ if (obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->classId = qt_Smoke->idClass("DCOPRef");
+ o->smoke = qt_Smoke;
+ o->ptr = p;
+ o->allocated = true;
+ obj = set_obj_info("KDE::DCOPRef", o);
+ }
+
+ rb_ary_push(_result, obj);
+ }
+ } else if (replyType == "QValueList<QCString>") {
+ // And special case this type too
+ QValueList<QCString> propertyList;
+ ds >> propertyList;
+ _result = rb_ary_new();
+ for (QValueListIterator<QCString> it = propertyList.begin(); it != propertyList.end(); ++it) {
+ rb_ary_push(_result, rb_str_new2((const char *) *it));
+ }
+ } else if (replyType == "QValueList<int>") {
+ // And special case this type too
+ QValueList<int> propertyList;
+ ds >> propertyList;
+ _result = rb_ary_new();
+ for (QValueListIterator<int> it = propertyList.begin(); it != propertyList.end(); ++it) {
+ rb_ary_push(_result, INT2NUM(*it));
+ }
+ } else if (replyType == "QMap<QString,DCOPRef>") {
+ // And another..
+ QMap<QString,DCOPRef> actionMap;
+ ds >> actionMap;
+ _result = rb_hash_new();
+
+ QMap<QString,DCOPRef>::Iterator it;
+ for (it = actionMap.begin(); it != actionMap.end(); ++it) {
+ void *p = new DCOPRef(it.data());
+ VALUE obj = getPointerObject(p);
+
+ if (obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->classId = qt_Smoke->idClass("DCOPRef");
+ o->smoke = qt_Smoke;
+ o->ptr = p;
+ o->allocated = true;
+ obj = set_obj_info("KDE::DCOPRef", o);
+ }
+
+ rb_hash_aset(_result, rb_str_new2(it.key().latin1()), obj);
+ }
+ } else {
+ DCOPReturn dcopReturn(ds, &_result, rb_str_new2((const char *) replyType));
+ }
+ }
+
+ void next()
+ {
+ int oldcur = _cur;
+ _cur++;
+
+ while(!_called && _cur < _items) {
+ Marshall::HandlerFn fn = getMarshallFn(type());
+ (*fn)(this);
+ _cur++;
+ }
+
+ dcopCall();
+ _cur = oldcur;
+ }
+
+ bool cleanup() { return true; }
+};
+
+class DCOPSend : public Marshall {
+ VALUE _obj;
+ QCString & _remFun;
+ QByteArray *_data;
+ QDataStream *_stream;
+ int _id;
+ MocArgument *_args;
+ int _items;
+ VALUE *_sp;
+ int _cur;
+ VALUE * _result;
+ Smoke::Stack _stack;
+ bool _called;
+public:
+ DCOPSend(VALUE obj, QCString & remFun, int items, VALUE *sp, VALUE args, VALUE * result) :
+ _obj(obj), _remFun(remFun), _items(items), _sp(sp), _cur(-1), _result(result), _called(false)
+ {
+ _data = new QByteArray();
+ _stream = new QDataStream(*_data, IO_WriteOnly);
+ Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args);
+ _stack = new Smoke::StackItem[_items];
+ }
+
+ ~DCOPSend()
+ {
+ delete[] _stack;
+ delete _data;
+ delete _stream;
+ }
+ const MocArgument &arg() { return _args[_cur]; }
+ SmokeType type() { return arg().st; }
+ Marshall::Action action() { return Marshall::FromVALUE; }
+ Smoke::StackItem &item() { return _stack[_cur]; }
+ VALUE * var() { return _sp + _cur; }
+
+ void unsupported()
+ {
+ rb_raise(rb_eArgError, "Cannot handle '%s' as a DCOP send argument", type().name());
+ }
+
+ Smoke *smoke() { return type().smoke(); }
+
+ void dcopSend()
+ {
+ if(_called) return;
+ _called = true;
+
+ smokeStackToStream(this, _stack, _stream, _items, _args);
+ smokeruby_object *o = value_obj_info(_obj);
+ DCOPRef * dcopRef = (DCOPRef *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("DCOPRef"));
+ DCOPClient* dc = dcopRef->dcopClient();
+ bool ok = dc->send(dcopRef->app(), dcopRef->obj(), _remFun, *_data);
+ *_result = (ok ? Qtrue : Qfalse);
+ }
+
+ void next()
+ {
+ int oldcur = _cur;
+ _cur++;
+
+ while(!_called && _cur < _items) {
+ Marshall::HandlerFn fn = getMarshallFn(type());
+ (*fn)(this);
+ _cur++;
+ }
+
+ dcopSend();
+ _cur = oldcur;
+ }
+
+ bool cleanup() { return true; }
+};
+
+class EmitDCOPSignal : public Marshall {
+ VALUE _obj;
+ const char * _signalName;
+ QByteArray *_data;
+ QDataStream *_stream;
+ int _id;
+ MocArgument *_args;
+ VALUE *_sp;
+ int _items;
+ int _cur;
+ Smoke::Stack _stack;
+ bool _called;
+public:
+ EmitDCOPSignal(VALUE obj, const char * signalName, int items, VALUE *sp, VALUE args) :
+ _obj(obj), _signalName(signalName), _sp(sp), _items(items), _cur(-1), _called(false)
+ {
+ _data = new QByteArray();
+ _stream = new QDataStream(*_data, IO_WriteOnly);
+ Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args);
+ _stack = new Smoke::StackItem[_items];
+ }
+
+ ~EmitDCOPSignal()
+ {
+ delete[] _stack;
+ delete _stream;
+ delete _data;
+ }
+ const MocArgument &arg() { return _args[_cur]; }
+ SmokeType type() { return arg().st; }
+ Marshall::Action action() { return Marshall::FromVALUE; }
+ Smoke::StackItem &item() { return _stack[_cur]; }
+ VALUE * var() { return _sp + _cur; }
+
+ void unsupported()
+ {
+ rb_raise(rb_eArgError, "Cannot handle '%s' as a DCOP signal argument", type().name());
+ }
+
+ Smoke *smoke() { return type().smoke(); }
+
+ void emitSignal()
+ {
+ if(_called) return;
+ _called = true;
+
+ smokeStackToStream(this, _stack, _stream, _items, _args);
+ smokeruby_object *o = value_obj_info(_obj);
+ DCOPObject * dcopObject = (DCOPObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("DCOPObject"));
+ dcopObject->emitDCOPSignal(_signalName, *_data);
+ }
+
+ void next()
+ {
+ int oldcur = _cur;
+ _cur++;
+
+ while(!_called && _cur < _items) {
+ Marshall::HandlerFn fn = getMarshallFn(type());
+ (*fn)(this);
+ _cur++;
+ }
+
+ emitSignal();
+ _cur = oldcur;
+ }
+
+ bool cleanup() { return true; }
+};
+
+/*
+ Converts a ruby value returned by a DCOP slot invocation to a QByteArray
+*/
+class DCOPReplyValue : public Marshall {
+ MocArgument * _replyType;
+ Smoke::Stack _stack;
+ VALUE * _result;
+public:
+ DCOPReplyValue(QByteArray & retval, VALUE * result, VALUE replyType)
+ {
+ QDataStream _retval(retval, IO_WriteOnly);
+ _result = result;
+ Data_Get_Struct(rb_ary_entry(replyType, 1), MocArgument, _replyType);
+ _stack = new Smoke::StackItem[1];
+ Marshall::HandlerFn fn = getMarshallFn(type());
+ (*fn)(this);
+ smokeStackToStream(this, _stack, &_retval, 1, _replyType);
+ }
+
+ SmokeType type() {
+ return _replyType[0].st;
+ }
+ Marshall::Action action() { return Marshall::FromVALUE; }
+ Smoke::StackItem &item() { return _stack[0]; }
+ VALUE * var() {
+ return _result;
+ }
+
+ void unsupported()
+ {
+ rb_raise(rb_eArgError, "Cannot handle '%s' as DCOP reply-type", type().name());
+ }
+ Smoke *smoke() { return type().smoke(); }
+
+ void next() {}
+
+ bool cleanup() { return false; }
+
+ ~DCOPReplyValue() {
+ delete[] _stack;
+ }
+};
+
+class InvokeDCOPSlot : public Marshall {
+ VALUE _obj;
+ ID _slotname;
+ int _items;
+ MocArgument * _args;
+ QDataStream * _stream;
+ const char * _replyTypeName;
+ VALUE _replyType;
+ QByteArray * _retval;
+ int _cur;
+ bool _called;
+ VALUE * _sp;
+ Smoke::Stack _stack;
+public:
+ const MocArgument &arg() { return _args[_cur]; }
+ SmokeType type() { return arg().st; }
+ Marshall::Action action() { return Marshall::ToVALUE; }
+ Smoke::StackItem &item() { return _stack[_cur]; }
+ VALUE * var() { return _sp + _cur; }
+ Smoke *smoke() { return type().smoke(); }
+ bool cleanup() { return false; }
+
+ void unsupported()
+ {
+ rb_raise(rb_eArgError, "Cannot handle '%s' as DCOP slot argument\n", type().name());
+ }
+
+ void copyArguments()
+ {
+ smokeStackFromStream(this, _stack, _stream, _items, _args);
+ return;
+ }
+
+ void invokeSlot()
+ {
+ if (_called) {
+ return;
+ }
+ _called = true;
+ VALUE result = rb_funcall2(_obj, _slotname, _items, _sp);
+
+ if ( strcmp(_replyTypeName, "QValueList<DCOPRef>") == 0
+ && TYPE(result) == T_ARRAY )
+ {
+ // Special case QValueList<DCOPRef> as a QDataStream marshaller
+ // isn't in the Smoke runtime
+ QValueList<DCOPRef> windowList;
+
+ for (long i = 0; i < RARRAY(result)->len; i++) {
+ VALUE item = rb_ary_entry(result, i);
+ smokeruby_object *o = value_obj_info(item);
+ if( !o || !o->ptr)
+ continue;
+ void * ptr = o->ptr;
+ ptr = o->smoke->cast(ptr, o->classId, o->smoke->idClass("DCOPRef"));
+ windowList.append((DCOPRef)*(DCOPRef*)ptr);
+ }
+ QDataStream retval(*_retval, IO_WriteOnly);
+ retval << windowList;
+ } else if ( strcmp(_replyTypeName, "QValueList<QCString>") == 0
+ && TYPE(result) == T_ARRAY )
+ {
+ // And special case this type too
+ QValueList<QCString> propertyList;
+
+ for (long i = 0; i < RARRAY(result)->len; i++) {
+ VALUE item = rb_ary_entry(result, i);
+ propertyList.append(QCString(StringValuePtr(item)));
+ }
+ QDataStream retval(*_retval, IO_WriteOnly);
+ retval << propertyList;
+ } else if ( strcmp(_replyTypeName, "QMap<QString,DCOPRef>") == 0
+ && TYPE(result) == T_HASH )
+ {
+ // And another..
+ QMap<QString,DCOPRef> actionMap;
+ // Convert the ruby hash to an array of key/value arrays
+ VALUE temp = rb_funcall(result, rb_intern("to_a"), 0);
+
+ for (long i = 0; i < RARRAY(temp)->len; i++) {
+ VALUE action = rb_ary_entry(rb_ary_entry(temp, i), 0);
+ VALUE item = rb_ary_entry(rb_ary_entry(temp, i), 1);
+
+ smokeruby_object *o = value_obj_info(item);
+ if( !o || !o->ptr)
+ continue;
+ void * ptr = o->ptr;
+ ptr = o->smoke->cast(ptr, o->classId, o->smoke->idClass("DCOPRef"));
+
+ actionMap[QString(StringValuePtr(action))] = (DCOPRef)*(DCOPRef*)ptr;
+ }
+ QDataStream retval(*_retval, IO_WriteOnly);
+ retval << actionMap;
+ } else if (_replyType != Qnil) {
+ DCOPReplyValue dcopReply(*_retval, &result, _replyType);
+ }
+ }
+
+ void next()
+ {
+ int oldcur = _cur;
+ _cur++;
+
+ while(!_called && _cur < _items) {
+ Marshall::HandlerFn fn = getMarshallFn(type());
+ (*fn)(this);
+ _cur++;
+ }
+
+ invokeSlot();
+ _cur = oldcur;
+ }
+
+ InvokeDCOPSlot(VALUE obj, ID slotname, VALUE args, QByteArray& data, VALUE replyTypeName, VALUE replyType, QByteArray& returnValue) :
+ _obj(obj), _slotname(slotname), _replyType(replyType), _cur(-1), _called(false)
+ {
+ _replyTypeName = StringValuePtr(replyTypeName);
+ _items = NUM2INT(rb_ary_entry(args, 0));
+ _stream = new QDataStream(data, IO_ReadOnly);
+ _retval = &returnValue;
+
+ Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args);
+ _sp = ALLOC_N(VALUE, _items);
+ _stack = new Smoke::StackItem[_items];
+
+ copyArguments();
+ }
+
+ ~InvokeDCOPSlot() {
+ delete[] _stack;
+ delete _stream;
+ for(int i=0;i<_items;++i) {
+ free(_sp++);
+ }
+ }
+};
+
+extern "C" {
+extern void Init_qtruby();
+extern void set_new_kde(VALUE (*new_kde) (int, VALUE *, VALUE));
+extern void set_kconfigskeletonitem_immutable(VALUE (*kconfigskeletonitem_immutable) (VALUE));
+extern void set_kde_resolve_classname(const char * (*kde_resolve_classname) (Smoke*, int, void *));
+extern const char * kde_resolve_classname(Smoke* smoke, int classId, void * ptr);
+extern VALUE new_qt(int argc, VALUE * argv, VALUE klass);
+extern VALUE qt_module;
+extern VALUE qt_internal_module;
+extern VALUE qt_base_class;
+extern VALUE kde_module;
+extern VALUE kio_module;
+extern VALUE kparts_module;
+extern VALUE khtml_module;
+
+VALUE
+getdcopinfo(VALUE self, QString & signalname)
+{
+ VALUE member = rb_funcall( kde_internal_module,
+ rb_intern("fullSignalName"),
+ 2, self, rb_str_new2(signalname) );
+ signalname.setLatin1(StringValuePtr(member));
+ return rb_funcall( qt_internal_module,
+ rb_intern("getMocArguments"),
+ 1, member );
+}
+
+VALUE
+k_dcop_signal(int argc, VALUE * argv, VALUE self)
+{
+ VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self);
+
+ QString signalname(rb_id2name(rb_frame_last_func()));
+ VALUE args = getdcopinfo(self, signalname);
+
+ if(args == Qnil) return Qfalse;
+
+ EmitDCOPSignal signal(dcopObject, signalname.latin1(), argc, argv, args);
+ signal.next();
+
+ return Qtrue;
+}
+
+static VALUE
+dcop_functions(VALUE self)
+{
+ VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self);
+ return rb_funcall(dcopObject, rb_intern("functions"), 0);
+}
+
+static VALUE
+dcop_interfaces(VALUE self)
+{
+ VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self);
+ return rb_funcall(dcopObject, rb_intern("interfaces"), 0);
+}
+
+static VALUE
+dcop_connect_signal(VALUE self, VALUE sender, VALUE senderObj, VALUE signal, VALUE slot, VALUE volatile_connect)
+{
+ VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self);
+ return rb_funcall(dcopObject, rb_intern("connectDCOPSignal"), 5, sender, senderObj, signal, slot, volatile_connect);
+}
+
+static VALUE
+dcop_disconnect_signal(VALUE self, VALUE sender, VALUE senderObj, VALUE signal, VALUE slot)
+{
+ VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self);
+ return rb_funcall(dcopObject, rb_intern("disconnectDCOPSignal"), 4, sender, senderObj, signal, slot);
+}
+
+static VALUE
+dcop_process(VALUE /*self*/, VALUE target, VALUE slotname, VALUE args, VALUE data, VALUE replyTypeName, VALUE replyType, VALUE replyData)
+{
+ smokeruby_object *o = value_obj_info(data);
+ if (o == 0 || o->ptr == 0) {
+ return Qfalse;
+ }
+ QByteArray * dataArray = (QByteArray*) o->ptr;
+
+ o = value_obj_info(replyData);
+ if (o == 0 || o->ptr == 0) {
+ return Qfalse;
+ }
+ QByteArray * replyArray = (QByteArray*) o->ptr;
+
+ InvokeDCOPSlot dcopSlot(target, rb_intern(StringValuePtr(slotname)), args, *dataArray, replyTypeName, replyType, *replyArray);
+ dcopSlot.next();
+
+ return Qtrue;
+}
+
+static VALUE
+dcop_call(int argc, VALUE * argv, VALUE /*self*/)
+{
+ QCString fun(StringValuePtr(argv[1]));
+ VALUE args = argv[2];
+ bool useEventLoop = (argv[argc-2] == Qtrue ? true : false);
+ int timeout = NUM2INT(argv[argc-1]);
+
+ DCOPCall dcopCall(argv[0], fun, argc-5, argv+3, args, useEventLoop, timeout);
+ dcopCall.next();
+
+ return *(dcopCall.var());
+}
+
+static VALUE
+dcop_send(int argc, VALUE * argv, VALUE /*self*/)
+{
+ QCString fun(StringValuePtr(argv[1]));
+ VALUE args = argv[2];
+ VALUE result = Qnil;
+
+ DCOPSend dcopSend(argv[0], fun, argc-3, argv+3, args, &result);
+ dcopSend.next();
+
+ return result;
+}
+
+static VALUE
+new_kde(int argc, VALUE * argv, VALUE klass)
+{
+ VALUE instance = new_qt(argc, argv, klass);
+
+ if (rb_funcall(kde_module, rb_intern("hasDCOPSignals"), 1, klass) == Qtrue) {
+ VALUE signalNames = rb_funcall(kde_module, rb_intern("getDCOPSignalNames"), 1, klass);
+ for (long index = 0; index < RARRAY(signalNames)->len; index++) {
+ VALUE signal = rb_ary_entry(signalNames, index);
+ rb_define_method(klass, StringValuePtr(signal), (VALUE (*) (...)) k_dcop_signal, -1);
+ }
+ }
+
+ if ( rb_funcall(kde_module, rb_intern("hasDCOPSlots"), 1, klass) == Qtrue
+ || rb_funcall(kde_module, rb_intern("hasDCOPSignals"), 1, klass) == Qtrue )
+ {
+ VALUE dcop_object = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, instance);
+ if (dcop_object != Qnil) {
+ rb_define_method(klass, "interfaces", (VALUE (*) (...)) dcop_interfaces, 0);
+ rb_define_method(klass, "functions", (VALUE (*) (...)) dcop_functions, 0);
+ rb_define_method(klass, "connectDCOPSignal", (VALUE (*) (...)) dcop_connect_signal, 5);
+ rb_define_method(klass, "disconnectDCOPSignal", (VALUE (*) (...)) dcop_disconnect_signal, 4);
+ }
+ }
+
+ return instance;
+}
+
+#if KDE_VERSION >= 0x030200
+
+static VALUE
+kconfigskeletonitem_immutable(VALUE self)
+{
+ smokeruby_object *o = value_obj_info(self);
+ KConfigSkeletonItem * item = (KConfigSkeletonItem *) o->ptr;
+ return item->isImmutable() ? Qtrue : Qfalse;
+}
+
+static VALUE
+config_additem(int argc, VALUE * argv, VALUE self)
+{
+ smokeruby_object *o = value_obj_info(self);
+ KConfigSkeleton * config = (KConfigSkeleton *) o->ptr;
+
+ if (argc < 1 || argc > 2) {
+ rb_raise(rb_eArgError, "wrong number of arguments(%d for 2)\n", argc);
+ }
+
+ if (TYPE(argv[0]) != T_DATA) {
+ rb_raise(rb_eArgError, "wrong argument type, expected KDE::ConfigSkeletonItem\n", argc);
+ }
+
+ smokeruby_object *c = value_obj_info(argv[0]);
+ KConfigSkeletonItem * item = (KConfigSkeletonItem *) c->ptr;
+
+ if (argc == 1) {
+ config->addItem(item);
+ } else {
+ config->addItem(item, QString(StringValuePtr(argv[1])));
+ }
+
+ return self;
+}
+
+#endif
+
+static VALUE
+konsole_part_startprogram(VALUE self, VALUE value_program, VALUE value_args)
+{
+ smokeruby_object * o = value_obj_info(self);
+ TerminalInterface * t = static_cast<TerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("TerminalInterface"));
+
+ QStrList *args = new QStrList;
+
+ if (value_args != Qnil) {
+ for (long i = 0; i < RARRAY(value_args)->len; i++) {
+ VALUE item = rb_ary_entry(value_args, i);
+ args->append(QString::fromLatin1(StringValuePtr(item), RSTRING(item)->len));
+ }
+ }
+
+ t->startProgram(QString::fromLatin1(StringValuePtr(value_program)), args);
+ return self;
+}
+
+static VALUE
+konsole_part_showshellindir(VALUE self, VALUE value_dir)
+{
+ smokeruby_object * o = value_obj_info(self);
+ TerminalInterface * t = static_cast<TerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("TerminalInterface"));
+ t->showShellInDir(StringValuePtr(value_dir));
+ return self;
+}
+
+static VALUE
+konsole_part_sendinput(VALUE self, VALUE value_text)
+{
+ smokeruby_object * o = value_obj_info(self);
+ TerminalInterface * t = static_cast<TerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("TerminalInterface"));
+ t->sendInput(StringValuePtr(value_text));
+ return self;
+}
+
+#if KDE_VERSION >= 0x030500
+static VALUE
+konsole_part_setautostartshell(VALUE self, VALUE enabled)
+{
+ smokeruby_object * o = value_obj_info(self);
+ ExtTerminalInterface * t = static_cast<ExtTerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("ExtTerminalInterface"));
+ t->setAutoStartShell(enabled == Qtrue);
+ return self;
+}
+
+static VALUE
+konsole_part_setautodestroy(VALUE self, VALUE enabled)
+{
+ smokeruby_object * o = value_obj_info(self);
+ ExtTerminalInterface * t = static_cast<ExtTerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("ExtTerminalInterface"));
+ t->setAutoDestroy(enabled == Qtrue);
+ return self;
+}
+#endif
+
+void
+Init_korundum()
+{
+ if (qt_internal_module != Qnil) {
+ rb_fatal("require 'Korundum' must not follow require 'Qt'\n");
+ return;
+ }
+
+ set_new_kde(new_kde);
+#if KDE_VERSION >= 0x030200
+ set_kconfigskeletonitem_immutable(kconfigskeletonitem_immutable);
+#endif
+ set_kde_resolve_classname(kde_resolve_classname);
+
+ // The Qt extension is linked against libsmokeqt.so, but Korundum links against
+ // libsmokekde.so only. Specifying both a 'require Qt' and a 'require Korundum',
+ // would give a link error (see the rb_fatal() error above).
+ // So call the Init_qtruby() initialization function explicitely, not via 'require Qt'
+ // (Qt.o is linked into libqtruby.so, as well as the Qt.so extension).
+ Init_qtruby();
+ install_handlers(KDE_handlers);
+
+ kde_internal_module = rb_define_module_under(kde_module, "Internal");
+ rb_define_singleton_method(kde_module, "dcop_process", (VALUE (*) (...)) dcop_process, 7);
+ rb_define_singleton_method(kde_module, "dcop_call", (VALUE (*) (...)) dcop_call, -1);
+ rb_define_singleton_method(kde_module, "dcop_send", (VALUE (*) (...)) dcop_send, -1);
+
+#if KDE_VERSION >= 0x030200
+ rb_define_method(kconfigskeleton_class, "addItem", (VALUE (*) (...)) config_additem, -1);
+#endif
+
+ rb_define_method(konsole_part_class, "startProgram", (VALUE (*) (...)) konsole_part_startprogram, 2);
+ rb_define_method(konsole_part_class, "showShellInDir", (VALUE (*) (...)) konsole_part_showshellindir, 1);
+ rb_define_method(konsole_part_class, "sendInput", (VALUE (*) (...)) konsole_part_sendinput, 1);
+#if KDE_VERSION >= 0x030500
+ rb_define_method(konsole_part_class, "setAutoStartShell", (VALUE (*) (...)) konsole_part_setautostartshell, 1);
+ rb_define_method(konsole_part_class, "autoStartShell=", (VALUE (*) (...)) konsole_part_setautostartshell, 1);
+ rb_define_method(konsole_part_class, "setAutoDestroy", (VALUE (*) (...)) konsole_part_setautodestroy, 1);
+ rb_define_method(konsole_part_class, "autoDestroy=", (VALUE (*) (...)) konsole_part_setautodestroy, 1);
+#endif
+
+ rb_require("KDE/korundum.rb");
+}
+
+};
diff --git a/korundum/rubylib/korundum/Makefile.am b/korundum/rubylib/korundum/Makefile.am
new file mode 100644
index 00000000..c135f4e9
--- /dev/null
+++ b/korundum/rubylib/korundum/Makefile.am
@@ -0,0 +1,10 @@
+INCLUDES = -I$(top_srcdir)/smoke -I$(top_srcdir)/qtruby/rubylib/qtruby $(all_includes) -I$(RUBY_ARCHDIR)
+
+rubylibdir = $(RUBY_SITEARCHDIR)
+rubylib_LTLIBRARIES = korundum.la
+korundum_la_LDFLAGS = -module $(all_libraries) -version-info 0:0:0
+korundum_la_METASOURCES = AUTO
+korundum_la_SOURCES = Korundum.cpp kdehandlers.cpp
+korundum_la_LIBADD = $(LIB_KDE) $(top_builddir)/smoke/kde/libsmokekde.la $(top_builddir)/qtruby/rubylib/qtruby/libqtrubyinternal.la
+
+SUBDIRS = lib
diff --git a/korundum/rubylib/korundum/configure.in.in b/korundum/rubylib/korundum/configure.in.in
new file mode 100644
index 00000000..de265e6d
--- /dev/null
+++ b/korundum/rubylib/korundum/configure.in.in
@@ -0,0 +1,15 @@
+AC_CHECK_PROG(RUBY, ruby, ruby)
+
+if test -z "$RUBY"; then
+ DO_NOT_COMPILE="$DO_NOT_COMPILE korundum"
+else
+ AC_MSG_CHECKING(for ruby dirs)
+ RUBY_ARCHDIR=`ruby -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"archdir"@:>@)'`
+ RUBY_SITEARCHDIR=`ruby -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitearchdir"@:>@)'`
+ RUBY_SITEDIR=`ruby -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitelibdir"@:>@)'`
+ AC_MSG_RESULT([archdir $RUBY_ARCHDIR, sitearchdir $RUBY_SITEARCHDIR, sitedir $RUBY_SITEDIR])
+ AC_SUBST(RUBY_ARCHDIR)
+ AC_SUBST(RUBY_SITEARCHDIR)
+ AC_SUBST(RUBY_SITEDIR)
+fi
+
diff --git a/korundum/rubylib/korundum/kdehandlers.cpp b/korundum/rubylib/korundum/kdehandlers.cpp
new file mode 100644
index 00000000..4d8d5741
--- /dev/null
+++ b/korundum/rubylib/korundum/kdehandlers.cpp
@@ -0,0 +1,1428 @@
+/***************************************************************************
+ kdehandlers.cpp - KDE specific marshallers
+ -------------------
+ begin : Sun Sep 28 2003
+ copyright : (C) 2003 by Richard Dale
+ email : Richard_Dale@tipitina.demon.co.uk
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qtruby.h>
+#include <smokeruby.h>
+
+#include <kdeversion.h>
+#include <dcopclient.h>
+#include <dcopobject.h>
+#include <dcopref.h>
+#include <qptrlist.h>
+#include <ktrader.h>
+#include <kservicegroup.h>
+#include <kservice.h>
+#include <ksycocatype.h>
+#include <kmainwindow.h>
+#include <kfile.h>
+#include <kfileview.h>
+#include <kurl.h>
+#include <kcmdlineargs.h>
+#include <kaction.h>
+#include <kdockwidget.h>
+#include <kfiletreebranch.h>
+#include <kfiletreeviewitem.h>
+#include <khtml_part.h>
+#include <kparts/plugin.h>
+#include <kuserprofile.h>
+#include <kaboutdata.h>
+#include <karchive.h>
+#if KDE_VERSION >= 0x030200
+#include <kconfigskeleton.h>
+#include <kplugininfo.h>
+#include <kmountpoint.h>
+#endif
+#include <kio/jobclasses.h>
+#include <dom/dom_node.h>
+#include <dom/dom_element.h>
+#include <dom/dom_string.h>
+#include <dom/html_element.h>
+
+extern "C" {
+extern VALUE set_obj_info(const char * className, smokeruby_object * o);
+};
+
+extern bool isDerivedFromByName(Smoke *smoke, const char *className, const char *baseClassName);
+
+extern "C" {
+/*
+ * Given an approximate classname and a kde instance, try to improve the resolution of the name
+ * by using the various KDE rtti mechanisms
+ */
+const char *
+kde_resolve_classname(Smoke * smoke, int classId, void * ptr)
+{
+ if (isDerivedFromByName(smoke, smoke->classes[classId].className, "KArchiveEntry")) {
+ KArchiveEntry * entry = (KArchiveEntry *) smoke->cast(ptr, classId, smoke->idClass("KArchiveEntry"));
+ if (entry->isDirectory()) {
+ return "KDE::ArchiveDirectory";
+ } else {
+ return "KDE::ArchiveFile";
+ }
+ } else if (strcmp(smoke->classes[classId].className, "DOM::Node") == 0) {
+ DOM::Node * node = (DOM::Node *) smoke->cast(ptr, classId, smoke->idClass("DOM::Node"));
+ switch (node->nodeType()) {
+ case DOM::Node::ELEMENT_NODE:
+ if (((DOM::Element*)node)->isHTMLElement()) {
+ return "DOM::HTMLElement";
+ } else {
+ return "DOM::Element";
+ }
+ case DOM::Node::ATTRIBUTE_NODE:
+ return "DOM::Attr";
+ case DOM::Node::TEXT_NODE:
+ return "DOM::Text";
+ case DOM::Node::CDATA_SECTION_NODE:
+ return "DOM::CDATASection";
+ case DOM::Node::ENTITY_REFERENCE_NODE:
+ return "DOM::EntityReference";
+ case DOM::Node::ENTITY_NODE:
+ return "DOM::Entity";
+ case DOM::Node::PROCESSING_INSTRUCTION_NODE:
+ return "DOM::ProcessingInstruction";
+ case DOM::Node::COMMENT_NODE:
+ return "DOM::Comment";
+ case DOM::Node::DOCUMENT_NODE:
+ return "DOM::Document";
+ case DOM::Node::DOCUMENT_TYPE_NODE:
+ return "DOM::DocumentType";
+ case DOM::Node::DOCUMENT_FRAGMENT_NODE:
+ return "DOM::DocumentFragment";
+ case DOM::Node::NOTATION_NODE:
+ return "DOM::Notation";
+ }
+ }
+
+ return smoke->binding->className(classId);
+}
+
+};
+
+void marshall_QCStringList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ VALUE list = *(m->var());
+ if (TYPE(list) != T_ARRAY) {
+ m->item().s_voidp = 0;
+ break;
+ }
+
+ int count = RARRAY(list)->len;
+ QCStringList *stringlist = new QCStringList;
+
+ for(long i = 0; i < count; i++) {
+ VALUE item = rb_ary_entry(list, i);
+ if(TYPE(item) != T_STRING) {
+ stringlist->append(QCString());
+ continue;
+ }
+ stringlist->append(QCString(StringValuePtr(item), RSTRING(item)->len + 1));
+ }
+
+ m->item().s_voidp = stringlist;
+ m->next();
+
+ if(m->cleanup()) {
+ rb_ary_clear(list);
+ for(QCStringList::Iterator it = stringlist->begin(); it != stringlist->end(); ++it)
+ rb_ary_push(list, rb_str_new2(static_cast<const char *>(*it)));
+ delete stringlist;
+ }
+ break;
+ }
+ case Marshall::ToVALUE:
+ {
+ QCStringList *stringlist = static_cast<QCStringList *>(m->item().s_voidp);
+ if(!stringlist) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+ for(QCStringList::Iterator it = stringlist->begin(); it != stringlist->end(); ++it) {
+ VALUE rv = rb_str_new2(static_cast<const char *>((*it)));
+ rb_ary_push(av, rv);
+ }
+
+ if(m->cleanup())
+ delete stringlist;
+
+ *(m->var()) = av;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+#if defined (__i386__) && defined (__GNUC__) && __GNUC__ >= 2
+# define BREAKPOINT { __asm__ __volatile__ ("int $03"); }
+#else
+# define BREAKPOINT { fprintf(stderr, "hit ctrl-c\n"); int b = 0; while (b == 0) { ; } }
+#endif
+
+void marshall_KCmdLineOptions(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ VALUE optionslist = *(m->var());
+ if (optionslist == Qnil
+ || TYPE(optionslist) != T_ARRAY
+ || RARRAY(optionslist)->len == 0 )
+ {
+ m->item().s_voidp = 0;
+ break;
+ }
+
+ // Allocate 'length + 1' entries, to include an all NULLs last entry
+ KCmdLineOptions *cmdLineOptions = (KCmdLineOptions *) calloc( RARRAY(optionslist)->len + 1,
+ sizeof(struct KCmdLineOptions) );
+
+ VALUE options;
+ long i;
+ for(i = 0; i < RARRAY(optionslist)->len; i++) {
+ options = rb_ary_entry(optionslist, i);
+ VALUE temp = rb_ary_entry(options, 0);
+ cmdLineOptions[i].name = StringValuePtr(temp);
+ temp = rb_ary_entry(options, 1);
+ cmdLineOptions[i].description = StringValuePtr(temp);
+ temp = rb_ary_entry(options, 2);
+ cmdLineOptions[i].def = StringValuePtr(temp);
+ }
+ cmdLineOptions[i].name = 0;
+ cmdLineOptions[i].description = 0;
+ cmdLineOptions[i].def = 0;
+
+
+ m->item().s_voidp = cmdLineOptions;
+ m->next();
+ /*
+ if(m->cleanup()) {
+ rb_ary_clear(optionslist);
+ for(i = 0; cmdLineOptions[i].name; i++)
+ options = rb_ary_new();
+ rb_ary_push(options, rb_str_new2(cmdLineOptions[i].name));
+ rb_ary_push(options, rb_str_new2(cmdLineOptions[i].description));
+ rb_ary_push(options, rb_str_new2(cmdLineOptions[i].def));
+ rb_ary_push(optionslist, options);
+ }
+ */
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_WIdList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ VALUE list = *(m->var());
+ if (TYPE(list) != T_ARRAY) {
+ m->item().s_voidp = 0;
+ break;
+ }
+ int count = RARRAY(list)->len;
+ QValueList<WId> *valuelist = new QValueList<WId>;
+ long i;
+ for(i = 0; i < count; i++) {
+ VALUE item = rb_ary_entry(list, i);
+ if(TYPE(item) != T_FIXNUM && TYPE(item) != T_BIGNUM) {
+ valuelist->append(0);
+ continue;
+ }
+ valuelist->append(NUM2LONG(item));
+ }
+
+ m->item().s_voidp = valuelist;
+ m->next();
+
+ if (!m->type().isConst()) {
+ rb_ary_clear(list);
+ for(QValueListIterator<WId> it = valuelist->begin();
+ it != valuelist->end();
+ ++it)
+ rb_ary_push(list, LONG2NUM((int)*it));
+ }
+
+ if (m->cleanup()) {
+ delete valuelist;
+ }
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ QValueList<WId> *valuelist = (QValueList<WId>*)m->item().s_voidp;
+ if(!valuelist) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ for(QValueListIterator<WId> it = valuelist->begin();
+ it != valuelist->end();
+ ++it)
+ rb_ary_push(av, LONG2NUM(*it));
+
+ *(m->var()) = av;
+
+ if(m->cleanup())
+ delete valuelist;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_KMimeTypeList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KMimeType::List *offerList = (KMimeType::List*)m->item().s_voidp;
+ if(!offerList) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ for(KMimeType::List::Iterator it = offerList->begin();
+ it != offerList->end();
+ ++it) {
+ KMimeType * item = new KMimeType (*(KMimeType*)((KMimeType::Ptr)(*it)).data());
+
+ VALUE obj = getPointerObject(item);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = m->smoke()->idClass("KMimeType");
+ o->ptr = item;
+ o->allocated = true;
+ obj = set_obj_info("KDE::MimeType", o);
+ }
+ rb_ary_push(av, obj);
+ }
+
+ *(m->var()) = av;
+
+ if(m->cleanup())
+ delete offerList;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_KMimeTypePtr(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KMimeType::Ptr ptr(*(KMimeType::Ptr*)m->item().s_voidp);
+ if(ptr == 0) {
+ *(m->var()) = Qnil;
+ break;
+ }
+ KMimeType * mimeType = new KMimeType(*(KMimeType*)ptr);
+
+ VALUE obj = getPointerObject(mimeType);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = m->smoke()->idClass("KMimeType");
+ o->ptr = mimeType;
+ o->allocated = true;
+ obj = set_obj_info("KDE::MimeType", o);
+ }
+
+ *(m->var()) = obj;
+
+ if(m->cleanup())
+ ;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_KServicePtr(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KSharedPtr<KService> *ptr = new KSharedPtr<KService>(*(KSharedPtr<KService>*)m->item().s_voidp);
+ if(ptr == 0) {
+ *(m->var()) = Qnil;
+ break;
+ }
+ KService * service = ptr->data();
+
+ VALUE obj = getPointerObject(service);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = m->smoke()->idClass("KService");
+ o->ptr = service;
+ o->allocated = true;
+ obj = set_obj_info("KDE::Service", o);
+ }
+
+ *(m->var()) = obj;
+
+ if(m->cleanup())
+ ;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_KServiceList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KService::List *offerList = (KService::List*)m->item().s_voidp;
+ if(!offerList) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ for(KService::List::Iterator it = offerList->begin();
+ it != offerList->end();
+ ++it) {
+ KSharedPtr<KService> *ptr = new KSharedPtr<KService>(*it);
+ KService * currentOffer = ptr->data();
+
+ VALUE obj = getPointerObject(currentOffer);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = m->smoke()->idClass("KService");
+ o->ptr = currentOffer;
+ o->allocated = false;
+ obj = set_obj_info("KDE::Service", o);
+ }
+ rb_ary_push(av, obj);
+ }
+
+ *(m->var()) = av;
+
+ if(m->cleanup())
+ delete offerList;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_KServiceGroupPtr(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KServiceGroup::Ptr ptr(*(KServiceGroup::Ptr*)m->item().s_voidp);
+ if(ptr == 0) {
+ *(m->var()) = Qnil;
+ break;
+ }
+ KServiceGroup * serviceGroup = new KServiceGroup(*(KServiceGroup*)ptr);
+
+ VALUE obj = getPointerObject(serviceGroup);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = m->smoke()->idClass("KServiceGroup");
+ o->ptr = serviceGroup;
+ o->allocated = true;
+ obj = set_obj_info("KDE::ServiceGroup", o);
+ }
+
+ *(m->var()) = obj;
+
+ if(m->cleanup())
+ ;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_KServiceTypeList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KServiceType::List *offerList = (KServiceType::List*)m->item().s_voidp;
+ if(!offerList) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ for(KServiceType::List::Iterator it = offerList->begin();
+ it != offerList->end();
+ ++it) {
+ KServiceType * currentOffer = new KServiceType(*((KServiceType*)*it));
+
+ VALUE obj = getPointerObject(currentOffer);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = m->smoke()->idClass("KServiceType");
+ o->ptr = currentOffer;
+ o->allocated = true;
+ obj = set_obj_info("KDE::ServiceType", o);
+ }
+ rb_ary_push(av, obj);
+ }
+
+ *(m->var()) = av;
+
+ if(m->cleanup())
+ delete offerList;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_KServiceGroupList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KServiceGroup::List *offerList = (KServiceGroup::List*)m->item().s_voidp;
+ if(!offerList) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ for(KServiceGroup::List::ConstIterator it = offerList->begin();
+ it != offerList->end();
+ ++it) {
+ KSycocaEntry *p = (*it);
+ VALUE obj = Qnil;
+ if (p->isType(KST_KService)) {
+ KService *s = static_cast<KService *>(p);
+ obj = getPointerObject(s);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = m->smoke()->idClass("KService");
+ o->ptr = s;
+ o->allocated = true;
+ obj = set_obj_info("KDE::Service", o);
+ }
+ } else if (p->isType(KST_KServiceGroup)) {
+ KServiceGroup *g = static_cast<KServiceGroup *>(p);
+ obj = getPointerObject(g);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = m->smoke()->idClass("KServiceGroup");
+ o->ptr = g;
+ o->allocated = true;
+ obj = set_obj_info("KDE::ServiceGroup", o);
+ }
+ }
+
+ rb_ary_push(av, obj);
+ }
+
+ *(m->var()) = av;
+
+ if(m->cleanup())
+ delete offerList;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+#if KDE_VERSION >= 0x030200
+void marshall_KMountPointList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KMountPoint::List *list = (KMountPoint::List*)m->item().s_voidp;
+ if(!list) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ for(KMountPoint::List::Iterator it = list->begin();
+ it != list->end();
+ ++it) {
+ KMountPoint * item = new KMountPoint(*((KMountPoint*)*it));
+
+ VALUE obj = getPointerObject(item);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = m->smoke()->idClass("KMountPoint");
+ o->ptr = item;
+ o->allocated = true;
+ obj = set_obj_info("KDE::MountPoint", o);
+ }
+ rb_ary_push(av, obj);
+ }
+
+ *(m->var()) = av;
+
+ if(m->cleanup())
+ delete list;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_KPluginInfoList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KPluginInfo::List *valuelist = (KPluginInfo::List*)m->item().s_voidp;
+ if(!valuelist) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ int ix = m->smoke()->idClass("KPluginInfo");
+ const char * className = m->smoke()->binding->className(ix);
+
+ for(KPluginInfo::List::Iterator it = valuelist->begin();
+ it != valuelist->end();
+ ++it) {
+ void *p = (*it);
+
+ if(m->item().s_voidp == 0) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE obj = getPointerObject(p);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = o->smoke->idClass("KPluginInfo");
+ o->ptr = p;
+ o->allocated = false;
+ obj = set_obj_info(className, o);
+ }
+ rb_ary_push(av, obj);
+ }
+
+ if(m->cleanup())
+ delete valuelist;
+ else
+ *(m->var()) = av;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+#endif
+
+void marshall_KActionPtrList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KActionPtrList *valuelist = (KActionPtrList*)m->item().s_voidp;
+ if (!valuelist) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ int ix = m->smoke()->idClass("KAction");
+ const char * className = m->smoke()->binding->className(ix);
+
+ for ( KActionPtrList::Iterator it = valuelist->begin();
+ it != valuelist->end();
+ ++it )
+ {
+ void *p = (*it);
+
+ if (m->item().s_voidp == 0) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE obj = getPointerObject(p);
+ if (obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = o->smoke->idClass("KAction");
+ o->ptr = p;
+ o->allocated = false;
+ obj = set_obj_info(className, o);
+ }
+ rb_ary_push(av, obj);
+ }
+
+ if (m->cleanup())
+ delete valuelist;
+ else
+ *(m->var()) = av;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_KTraderOfferList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KTrader::OfferList *offerList = (KTrader::OfferList*)m->item().s_voidp;
+ if(!offerList) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ for(KTrader::OfferList::Iterator it = offerList->begin();
+ it != offerList->end();
+ ++it) {
+ KSharedPtr<KService> *ptr = new KSharedPtr<KService>(*it);
+ KService * currentOffer = ptr->data();
+
+ VALUE obj = getPointerObject(currentOffer);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = m->smoke()->idClass("KService");
+ o->ptr = currentOffer;
+ o->allocated = false;
+ obj = set_obj_info("KDE::Service", o);
+ }
+ rb_ary_push(av, obj);
+ }
+
+ *(m->var()) = av;
+
+ if(m->cleanup())
+ delete offerList;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_KURLList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ VALUE list = *(m->var());
+ if (TYPE(list) != T_ARRAY) {
+ m->item().s_voidp = 0;
+ break;
+ }
+ int count = RARRAY(list)->len;
+ KURL::List *kurllist = new KURL::List;
+ long i;
+ for(i = 0; i < count; i++) {
+ VALUE item = rb_ary_entry(list, i);
+ // TODO do type checking!
+ smokeruby_object *o = value_obj_info(item);
+ if(!o || !o->ptr)
+ continue;
+ void *ptr = o->ptr;
+ ptr = o->smoke->cast(
+ ptr, // pointer
+ o->classId, // from
+ o->smoke->idClass("KURL") // to
+ );
+ kurllist->append((KURL&)*(KURL*)ptr);
+ }
+
+ m->item().s_voidp = kurllist;
+ m->next();
+
+ rb_ary_clear(list);
+ int ix = m->smoke()->idClass("KURL");
+ const char * className = m->smoke()->binding->className(ix);
+ for ( KURL::List::Iterator it = kurllist->begin();
+ it != kurllist->end();
+ ++it )
+ {
+ void *p = new KURL(*it);
+ VALUE obj = getPointerObject(p);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = ix;
+ o->ptr = p;
+ o->allocated = true;
+ obj = set_obj_info(className, o);
+ }
+ rb_ary_push(list, obj);
+ }
+
+ if(m->cleanup()) {
+ delete kurllist;
+ }
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KURL::List *kurllist = (KURL::List*)m->item().s_voidp;
+ if(!kurllist) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ int ix = m->smoke()->idClass("KURL");
+ const char * className = m->smoke()->binding->className(ix);
+
+ for(KURL::List::Iterator it = kurllist->begin();
+ it != kurllist->end();
+ ++it) {
+ void *p = new KURL(*it);
+
+ VALUE obj = getPointerObject(p);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = ix;
+ o->ptr = p;
+ o->allocated = true;
+ obj = set_obj_info(className, o);
+ }
+ rb_ary_push(av, obj);
+ }
+
+ *(m->var()) = av;
+
+ if(m->cleanup()) {
+ delete kurllist;
+ }
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+void marshall_UDSEntryList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ VALUE list = *(m->var());
+ if (TYPE(list) != T_ARRAY) {
+ m->item().s_voidp = 0;
+ break;
+ }
+
+ KIO::UDSEntryList *cpplist = new KIO::UDSEntryList;
+
+ for(long i = 0; i < RARRAY(list)->len; i++) {
+ VALUE item = rb_ary_entry(list, i);
+ KIO::UDSEntry *cppsublist = new KIO::UDSEntry;
+
+ for (int j = 0; j < RARRAY(item)->len; j++) {
+ VALUE subitem = rb_ary_entry(item, j);
+ smokeruby_object *o = value_obj_info(subitem);
+ if(!o || !o->ptr)
+ continue;
+ void *ptr = o->ptr;
+ ptr = o->smoke->cast(ptr, o->classId, o->smoke->idClass("KIO::UDSAtom"));
+ cppsublist->append(*(KIO::UDSAtom*)ptr);
+ }
+
+ cpplist->append(*cppsublist);
+ }
+
+ m->item().s_voidp = cpplist;
+ m->next();
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ KIO::UDSEntryList *valuelist = (KIO::UDSEntryList*)m->item().s_voidp;
+ if (!valuelist) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ int ix = m->smoke()->idClass("KIO::UDSAtom");
+
+ for ( KIO::UDSEntryList::Iterator it = valuelist->begin();
+ it != valuelist->end();
+ ++it )
+ {
+ KIO::UDSEntry * udsentry = &(*it);
+ VALUE subav = rb_ary_new();
+
+ for ( KIO::UDSEntry::Iterator it = udsentry->begin();
+ it != udsentry->end();
+ ++it )
+ {
+ void * p = &(*it);
+ VALUE obj = getPointerObject(p);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = ix;
+ o->ptr = p;
+ o->allocated = false;
+ obj = set_obj_info("KIO::UDSAtom", o);
+ }
+
+ rb_ary_push(subav, obj);
+ }
+
+ rb_ary_push(av, subav);
+ }
+
+ *(m->var()) = av;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+
+// Some time saving magic from Alex Kellett here..
+template <class Item, class ItemList, const char *ItemSTR >
+void marshall_ItemList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ VALUE list = *(m->var());
+ if (TYPE(list) != T_ARRAY) {
+ m->item().s_voidp = 0;
+ break;
+ }
+ int count = RARRAY(list)->len;
+ ItemList *cpplist = new ItemList;
+ long i;
+ for(i = 0; i < count; i++) {
+ VALUE item = rb_ary_entry(list, i);
+ // TODO do type checking!
+ smokeruby_object *o = value_obj_info(item);
+ if(!o || !o->ptr)
+ continue;
+ void *ptr = o->ptr;
+ ptr = o->smoke->cast(
+ ptr, // pointer
+ o->classId, // from
+ o->smoke->idClass(ItemSTR) // to
+ );
+ cpplist->append((Item*)ptr);
+ }
+
+ m->item().s_voidp = cpplist;
+ m->next();
+
+ if(m->cleanup()) {
+ rb_ary_clear(list);
+ for( Item * it = cpplist->first();
+ it != 0;
+ it = cpplist->next()) {
+ VALUE obj = getPointerObject((void*)it);
+ rb_ary_push(list, obj);
+ }
+ delete cpplist;
+ }
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ ItemList *valuelist = (ItemList*)m->item().s_voidp;
+ if(!valuelist) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ int ix = m->smoke()->idClass(ItemSTR);
+ const char * className = m->smoke()->binding->className(ix);
+
+ for(Item * it = valuelist->first();
+ it != 0;
+ it = valuelist->next()) {
+ void *p = it;
+
+ if(m->item().s_voidp == 0) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE obj = getPointerObject(p);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = o->smoke->idClass(ItemSTR);
+ o->ptr = p;
+ o->allocated = false;
+ obj = set_obj_info(className, o);
+ }
+ rb_ary_push(av, obj);
+ }
+
+ if(m->cleanup())
+ delete valuelist;
+ else
+ *(m->var()) = av;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+#define DEF_LIST_MARSHALLER(ListIdent,ItemList,Item) namespace { char ListIdent##STR[] = #Item; }; \
+ Marshall::HandlerFn marshall_##ListIdent = marshall_ItemList<Item,ItemList,ListIdent##STR>;
+
+DEF_LIST_MARSHALLER( KFileItemList, QPtrList<KFileItem>, KFileItem )
+DEF_LIST_MARSHALLER( KMainWindowList, QPtrList<KMainWindow>, KMainWindow )
+DEF_LIST_MARSHALLER( KActionList, QPtrList<KAction>, KAction )
+DEF_LIST_MARSHALLER( DCOPObjectList, QPtrList<DCOPObject>, DCOPObject )
+DEF_LIST_MARSHALLER( KDockWidgetList, QPtrList<KDockWidget>, KDockWidget )
+DEF_LIST_MARSHALLER( KFileTreeBranch, QPtrList<KFileTreeBranch>, KFileTreeBranch )
+DEF_LIST_MARSHALLER( KFileTreeViewItem, QPtrList<KFileTreeViewItem>, KFileTreeViewItem )
+DEF_LIST_MARSHALLER( KPartList, QPtrList<KParts::Part>, KParts::Part )
+DEF_LIST_MARSHALLER( KPartPluginList, QPtrList<KParts::Plugin>, KParts::Plugin )
+DEF_LIST_MARSHALLER( KPartReadOnlyPartList, QPtrList<KParts::ReadOnlyPart>, KParts::ReadOnlyPart )
+DEF_LIST_MARSHALLER( KServiceTypeProfileList, QPtrList<KServiceTypeProfile>, KServiceTypeProfile )
+
+template <class Item, class ItemList, class ItemListIterator, const char *ItemSTR >
+void marshall_ValueItemList(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ VALUE list = *(m->var());
+ if (TYPE(list) != T_ARRAY) {
+ m->item().s_voidp = 0;
+ break;
+ }
+ int count = RARRAY(list)->len;
+ ItemList *cpplist = new ItemList;
+ long i;
+ for(i = 0; i < count; i++) {
+ VALUE item = rb_ary_entry(list, i);
+ // TODO do type checking!
+ smokeruby_object *o = value_obj_info(item);
+ if(!o || !o->ptr)
+ continue;
+ void *ptr = o->ptr;
+ ptr = o->smoke->cast(
+ ptr, // pointer
+ o->classId, // from
+ o->smoke->idClass(ItemSTR) // to
+ );
+ cpplist->append(*(Item*)ptr);
+ }
+
+ m->item().s_voidp = cpplist;
+ m->next();
+
+ if(m->cleanup()) {
+ rb_ary_clear(list);
+ for(ItemListIterator it = cpplist->begin();
+ it != cpplist->end();
+ ++it) {
+ VALUE obj = getPointerObject((void*)&(*it));
+ rb_ary_push(list, obj);
+ }
+ delete cpplist;
+ }
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ ItemList *valuelist = (ItemList*)m->item().s_voidp;
+ if(!valuelist) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE av = rb_ary_new();
+
+ int ix = m->smoke()->idClass(ItemSTR);
+ const char * className = m->smoke()->binding->className(ix);
+
+ for(ItemListIterator it = valuelist->begin();
+ it != valuelist->end();
+ ++it) {
+ void *p = &(*it);
+
+ if(m->item().s_voidp == 0) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE obj = getPointerObject(p);
+ if(obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->smoke = m->smoke();
+ o->classId = o->smoke->idClass(ItemSTR);
+ o->ptr = p;
+ o->allocated = false;
+ obj = set_obj_info(className, o);
+ }
+ rb_ary_push(av, obj);
+ }
+
+ if(m->cleanup())
+ delete valuelist;
+ else
+ *(m->var()) = av;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+#define DEF_VALUELIST_MARSHALLER(ListIdent,ItemList,Item,Itr) namespace { char ListIdent##STR[] = #Item; }; \
+ Marshall::HandlerFn marshall_##ListIdent = marshall_ValueItemList<Item,ItemList,Itr,ListIdent##STR>;
+
+#if KDE_VERSION >= 0x030200
+DEF_VALUELIST_MARSHALLER( ChoicesList, QValueList<KConfigSkeleton::ItemEnum::Choice>, KConfigSkeleton::ItemEnum::Choice, QValueList<KConfigSkeleton::ItemEnum::Choice>::Iterator )
+#endif
+DEF_VALUELIST_MARSHALLER( KAboutPersonList, QValueList<KAboutPerson>, KAboutPerson, QValueList<KAboutPerson>::Iterator )
+DEF_VALUELIST_MARSHALLER( KAboutTranslatorList, QValueList<KAboutTranslator>, KAboutTranslator, QValueList<KAboutTranslator>::Iterator )
+DEF_VALUELIST_MARSHALLER( KIOCopyInfoList, QValueList<KIO::CopyInfo>, KIO::CopyInfo, QValueList<KIO::CopyInfo>::Iterator )
+DEF_VALUELIST_MARSHALLER( KServiceOfferList, QValueList<KServiceOffer>, KServiceOffer, QValueList<KServiceOffer>::Iterator )
+DEF_VALUELIST_MARSHALLER( UDSEntry, QValueList<KIO::UDSAtom>, KIO::UDSAtom, QValueList<KIO::UDSAtom>::Iterator )
+
+template <class Key, class Value, class ItemMapIterator, const char *KeySTR, const char *ValueSTR >
+void marshall_Map(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ VALUE hash = *(m->var());
+ if (TYPE(hash) != T_HASH) {
+ m->item().s_voidp = 0;
+ break;
+ }
+
+ QMap<Key,Value> * map = new QMap<Key,Value>;
+
+ // Convert the ruby hash to an array of key/value arrays
+ VALUE temp = rb_funcall(hash, rb_intern("to_a"), 0);
+
+ for (long i = 0; i < RARRAY(temp)->len; i++) {
+ VALUE key = rb_ary_entry(rb_ary_entry(temp, i), 0);
+ VALUE value = rb_ary_entry(rb_ary_entry(temp, i), 1);
+
+ smokeruby_object *o = value_obj_info(key);
+ if( !o || !o->ptr)
+ continue;
+ void * key_ptr = o->ptr;
+ key_ptr = o->smoke->cast(key_ptr, o->classId, o->smoke->idClass(KeySTR));
+
+ o = value_obj_info(value);
+ if( !o || !o->ptr)
+ continue;
+ void * val_ptr = o->ptr;
+ val_ptr = o->smoke->cast(val_ptr, o->classId, o->smoke->idClass(ValueSTR));
+
+ (*map)[(Key)*(Key*)key_ptr] = (Value)*(Value*)val_ptr;
+ }
+
+ m->item().s_voidp = map;
+ m->next();
+
+ if(m->cleanup())
+ delete map;
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ QMap<Key,Value> *map = (QMap<Key,Value>*)m->item().s_voidp;
+ if(!map) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE hv = rb_hash_new();
+
+ int key_ix = m->smoke()->idClass(KeySTR);
+ const char * key_className = m->smoke()->binding->className(key_ix);
+
+ int val_ix = m->smoke()->idClass(ValueSTR);
+ const char * val_className = m->smoke()->binding->className(val_ix);
+
+ ItemMapIterator it;
+ for (it = map->begin(); it != map->end(); ++it) {
+ void *key_p = new Key(it.key());
+ VALUE key_obj = getPointerObject(key_p);
+ smokeruby_object * o;
+
+ if (key_obj == Qnil) {
+ o = ALLOC(smokeruby_object);
+ o->classId = m->smoke()->idClass(KeySTR);
+ o->smoke = m->smoke();
+ o->ptr = key_p;
+ o->allocated = true;
+ key_obj = set_obj_info(key_className, o);
+ }
+
+ void *val_p = new Value(it.data());
+ VALUE value_obj = getPointerObject(val_p);
+
+ if (value_obj == Qnil) {
+ o = ALLOC(smokeruby_object);
+ o->classId = m->smoke()->idClass(ValueSTR);
+ o->smoke = m->smoke();
+ o->ptr = val_p;
+ o->allocated = true;
+ value_obj = set_obj_info(val_className, o);
+ }
+
+ rb_hash_aset(hv, key_obj, value_obj);
+ }
+
+ *(m->var()) = hv;
+ m->next();
+
+ if(m->cleanup())
+ delete map;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+#define DEF_MAP_MARSHALLER(MapIdent,Key,Value) namespace { char KeyIdent##STR[] = #Key; char ValueIdent##STR[] = #Value; }; \
+ Marshall::HandlerFn marshall_##MapIdent = marshall_Map<Key, Value,QMap<Key,Value>::Iterator,KeyIdent##STR, ValueIdent##STR>;
+
+DEF_MAP_MARSHALLER( QMapKEntryKeyKEntry, KEntryKey, KEntry )
+
+void marshall_QMapQCStringDCOPRef(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromVALUE:
+ {
+ VALUE hash = *(m->var());
+ if (TYPE(hash) != T_HASH) {
+ m->item().s_voidp = 0;
+ break;
+ }
+
+ QMap<QCString,DCOPRef> * map = new QMap<QCString,DCOPRef>;
+
+ // Convert the ruby hash to an array of key/value arrays
+ VALUE temp = rb_funcall(hash, rb_intern("to_a"), 0);
+
+ for (long i = 0; i < RARRAY(temp)->len; i++) {
+ VALUE key = rb_ary_entry(rb_ary_entry(temp, i), 0);
+ VALUE value = rb_ary_entry(rb_ary_entry(temp, i), 1);
+
+ smokeruby_object *o = value_obj_info(value);
+ if( !o || !o->ptr)
+ continue;
+ void * ptr = o->ptr;
+ ptr = o->smoke->cast(ptr, o->classId, o->smoke->idClass("DCOPRef"));
+
+ (*map)[QCString(StringValuePtr(key))] = (DCOPRef)*(DCOPRef*)ptr;
+ }
+
+ m->item().s_voidp = map;
+ m->next();
+
+ if(m->cleanup())
+ delete map;
+ }
+ break;
+ case Marshall::ToVALUE:
+ {
+ QMap<QCString,DCOPRef> *map = (QMap<QCString,DCOPRef>*)m->item().s_voidp;
+ if(!map) {
+ *(m->var()) = Qnil;
+ break;
+ }
+
+ VALUE hv = rb_hash_new();
+
+ QMap<QCString,DCOPRef>::Iterator it;
+ for (it = map->begin(); it != map->end(); ++it) {
+ void *p = new DCOPRef(it.data());
+ VALUE obj = getPointerObject(p);
+
+ if (obj == Qnil) {
+ smokeruby_object * o = ALLOC(smokeruby_object);
+ o->classId = m->smoke()->idClass("DCOPRef");
+ o->smoke = m->smoke();
+ o->ptr = p;
+ o->allocated = true;
+ obj = set_obj_info("KDE::DCOPRef", o);
+ }
+
+ rb_hash_aset(hv, rb_str_new2((const char *) it.key()), obj);
+ }
+
+ *(m->var()) = hv;
+ m->next();
+
+ if(m->cleanup())
+ delete map;
+ }
+ break;
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+TypeHandler KDE_handlers[] = {
+ { "QCStringList", marshall_QCStringList },
+ { "KCmdLineOptions*", marshall_KCmdLineOptions },
+ { "KActionPtrList", marshall_KActionList },
+ { "QPtrList<KAction>", marshall_KActionList },
+ { "QPtrList<KAction>&", marshall_KActionList },
+ { "KMimeType::List", marshall_KMimeTypeList },
+ { "KMimeType::Ptr", marshall_KMimeTypePtr },
+ { "KService::Ptr", marshall_KServicePtr },
+ { "KService::List", marshall_KServiceList },
+ { "KServiceGroup::List", marshall_KServiceGroupList },
+ { "KServiceGroup::Ptr", marshall_KServiceGroupPtr },
+#if KDE_VERSION >= 0x030200
+ { "KMountPoint::List", marshall_KMountPointList },
+ { "KPluginInfo::List", marshall_KPluginInfoList },
+ { "QValueList<KConfigSkeleton::ItemEnum::Choice>", marshall_ChoicesList },
+ { "QValueList<KConfigSkeleton::ItemEnum::Choice>&", marshall_ChoicesList },
+#endif
+ { "KServiceType::List", marshall_KServiceTypeList },
+ { "KTrader::OfferList", marshall_KTraderOfferList },
+ { "KURL::List", marshall_KURLList },
+ { "KURL::List&", marshall_KURLList },
+ { "KFileItemList", marshall_KFileItemList },
+ { "KFileItemList*", marshall_KFileItemList },
+ { "QPtrList<KMainWindow>*", marshall_KMainWindowList },
+ { "QPtrList<DCOPObject>", marshall_DCOPObjectList },
+ { "QPtrList<KDockWidget>&", marshall_KDockWidgetList },
+ { "QPtrList<KDockWidget>*", marshall_KDockWidgetList },
+ { "KFileTreeBranchList&", marshall_KFileTreeBranch },
+ { "KFileTreeViewItemList&", marshall_KFileTreeViewItem },
+ { "QPtrList<KParts::Part>*", marshall_KPartList },
+ { "QPtrList<KParts::Plugin>", marshall_KPartPluginList },
+ { "QPtrList<KParts::ReadOnlyPart>", marshall_KPartReadOnlyPartList },
+ { "QPtrList<KServiceTypeProfile>&", marshall_KServiceTypeProfileList },
+ { "QValueList<KAction*>", marshall_KActionPtrList },
+ { "KActionPtrList", marshall_KActionPtrList },
+ { "QValueList<KAboutPerson>", marshall_KAboutPersonList },
+ { "QValueList<KAboutTranslator>", marshall_KAboutTranslatorList },
+ { "QValueList<KIO::CopyInfo>&", marshall_KIOCopyInfoList },
+ { "KIO::UDSEntry&", marshall_UDSEntry },
+ { "KIO::UDSEntryList&", marshall_UDSEntryList },
+ { "KServiceTypeProfile::OfferList", marshall_KServiceOfferList },
+ { "KEntryMap", marshall_QMapKEntryKeyKEntry },
+ { "KEntryMap&", marshall_QMapKEntryKeyKEntry },
+ { "KEntryMap*", marshall_QMapKEntryKeyKEntry },
+ { "QMap<QCString,DCOPRef>", marshall_QMapQCStringDCOPRef },
+ { "QValueList<WId>&", marshall_WIdList },
+ { "QValueList<WId>", marshall_WIdList },
+ { 0, 0 }
+};
diff --git a/korundum/rubylib/korundum/lib/KDE/Korundum.rb b/korundum/rubylib/korundum/lib/KDE/Korundum.rb
new file mode 100644
index 00000000..101d3e30
--- /dev/null
+++ b/korundum/rubylib/korundum/lib/KDE/Korundum.rb
@@ -0,0 +1 @@
+require 'korundum'
diff --git a/korundum/rubylib/korundum/lib/KDE/Makefile.am b/korundum/rubylib/korundum/lib/KDE/Makefile.am
new file mode 100644
index 00000000..3f7b0c53
--- /dev/null
+++ b/korundum/rubylib/korundum/lib/KDE/Makefile.am
@@ -0,0 +1,5 @@
+kderubylibdir = $(RUBY_SITEDIR)/KDE
+kderubylib_DATA = korundum.rb
+
+rubylibdir = $(RUBY_SITEDIR)
+rubylib_DATA = Korundum.rb
diff --git a/korundum/rubylib/korundum/lib/KDE/korundum.rb b/korundum/rubylib/korundum/lib/KDE/korundum.rb
new file mode 100644
index 00000000..40c87260
--- /dev/null
+++ b/korundum/rubylib/korundum/lib/KDE/korundum.rb
@@ -0,0 +1,1391 @@
+=begin
+/***************************************************************************
+ Korundum.rb - KDE specific ruby runtime, dcop etc.
+ -------------------
+ begin : Sun Sep 28 2003
+ copyright : (C) 2003-2006 by Richard Dale
+ email : Richard_Dale@tipitina.demon.co.uk
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+=end
+
+module KDE
+ DCOPMeta = {}
+
+ # An entry for each dcop signal or slot
+ # Example
+ # int foobar(QString,bool)
+ # :name is 'foobar'
+ # :full_name is 'foobar(QString,bool)'
+ # :arg_types is 'QString,bool'
+ # :reply_type is 'int'
+ DCOPMember = Struct.new :name, :full_name, :arg_types, :reply_type
+
+ # If the class with the 'k_dcop' slots declaration is not a subclass of DCOPObject,
+ # then 'dcop_object' holds a instance of DCOPObject for the class to use as a
+ # proxy. For subclasses of DCOPObject, 'dcop_object' will always be nil
+ class DCOPMetaInfo
+ attr_accessor :dcop_object, :changed
+ attr_reader :k_dcop_signals, :k_dcop
+
+ def initialize(aClass)
+ DCOPMeta[aClass.name] = self
+ @dcop_object = nil
+ @k_dcop_signals = {}
+ @k_dcop = {}
+ @changed = false
+ end
+
+ def add_signals(signal_list)
+ signal_list.each do |signal|
+ signal = DCOPClient.normalizeFunctionSignature(signal)
+ if signal =~ /^([\w,<>:]*)\s+([^\s]*)\((.*)\)/
+ args = DCOPClient.normalizeFunctionSignature($3)
+ @k_dcop_signals[$2] = DCOPMember.new($2, $2 + "(" + args + ")", args, $1)
+ else
+ qWarning( "Invalid DCOP signal format: '#{signal}'" )
+ end
+ end
+ end
+
+ def add_slots(slot_list)
+ slot_list.each do |slot|
+ if slot =~ /^([\w,<>:]*)\s+([^\s]*)\((.*)\)/
+ args = DCOPClient.normalizeFunctionSignature($3)
+ @k_dcop[$2] = DCOPMember.new($2, $1 + ' ' + $2 + "(" + args + ")", args, $1)
+ else
+ qWarning( "Invalid DCOP slot format: '#{slot}'" )
+ end
+ end
+ end
+ end # DCOPMetaInfo
+
+ def KDE.hasDCOPSignals(aClass)
+ classname = aClass.name if aClass.is_a? Module
+ meta = DCOPMeta[classname]
+ return !meta.nil? && meta.k_dcop_signals.length > 0
+ end
+
+ def KDE.hasDCOPSlots(aClass)
+ classname = aClass.name if aClass.is_a? Module
+ meta = DCOPMeta[classname]
+ return !meta.nil? && meta.k_dcop.length > 0
+ end
+
+ def KDE.getDCOPSignalNames(aClass)
+ classname = aClass.name if aClass.is_a? Module
+ signals = DCOPMeta[classname].k_dcop_signals
+ return signals.keys
+ end
+
+ module Internal
+ def Internal.fullSignalName(instance, signalName)
+ classname = instance.class.name if instance.class.is_a? Module
+ signals = DCOPMeta[classname].k_dcop_signals
+ return signals[signalName].full_name
+ end
+ end
+
+ class KDE::DCOPObject
+ def initialize(*k)
+ super
+ end
+
+ def process(fun, data, replyType, replyData)
+ if fun == 'functions()' or fun == 'interfaces()'
+ return super
+ end
+
+ slots = DCOPMeta[@client.class.name].k_dcop
+ dcop_slot = slots[fun.sub(/\(.*/, '')]
+ if dcop_slot.nil?
+ # Can't find an entry for the slot being called? This shouldn't happen..
+ return false
+ end
+
+ replyType << dcop_slot.reply_type
+ KDE::dcop_process( @client,
+ dcop_slot.name,
+ Qt::Internal::getMocArguments(fun),
+ data,
+ replyType,
+ (replyType == 'void' or replyType == 'ASYNC') ? nil : Qt::Internal::getMocArguments(replyType),
+ replyData )
+ end
+
+ def interfaces()
+ ifaces = super()
+ return ifaces << @client.class.name
+ end
+
+ def functions()
+ funcs = super()
+ return funcs + @functions
+ end
+
+ def functions=(funcs)
+ @functions = funcs
+ end
+
+ # If a ruby class has 'k_dcop' slots declarations, but isn't a
+ # subclass of DCOPObject, then keep an instance of it
+ def client=(obj)
+ @client = obj
+ end
+
+ def inspect
+ str = super
+ if @functions != nil
+ str.sub(/>$/, " objId=%s, functions=Array (%d element(s))>" % [objId.inspect, functions.length])
+ end
+ end
+
+ def pretty_print(pp)
+ str = to_s
+ if @functions != nil
+ pp.text str.sub(/>$/, "\n objId=%s,\n functions=Array (%d element(s))>" % [objId.inspect, functions.length])
+ end
+ end
+ end
+
+ # If a class contains a k_dcop slots list declaration, then create a DCOPObject
+ # associated with it
+ def KDE.createDCOPObject(instance)
+ meta = DCOPMeta[instance.class.name]
+ return nil if meta.nil?
+
+ if meta.dcop_object.nil? or meta.changed
+ funcs = []
+ meta.k_dcop.each_value do |value|
+ sig = value.reply_type + ' ' + value.name + '(' + value.arg_types + ')'
+ funcs << sig
+ end
+ meta.changed = false
+ if instance.kind_of? DCOPObject
+ instance.functions = funcs
+ instance.client = instance
+ return nil
+ else
+ if meta.dcop_object.nil?
+ # Only ever allocate a single instance of a DCOPObject if the
+ # class isn't a subclass of DCOPObject
+ meta.dcop_object = DCOPObject.new(instance.class.name)
+ meta.dcop_object.client = instance
+ end
+ meta.dcop_object.functions = funcs
+ end
+ end
+
+ return meta.dcop_object
+ end
+
+ class DCOPRef < Qt::Base
+ def method_missing(*k)
+ # Enables DCOPRef calls to be made like this:
+ #
+ # dcopRef = DCOPRef.new("dcopslot", "MyWidget")
+ # result = dcopRef.getPoint("Hello from dcopcall")
+ begin
+ # First look for a method in the Smoke runtime.
+ # If not found, then throw an exception and try dcop.
+ super(*k)
+ rescue
+ dcopArgs = k[1, k.length-1]
+ dcopArgs << NoEventLoop << -1
+ method = k[0].id2name
+ # Make 'parrot.age = 7' a synonym for 'parrot.setAge(7)'
+ method = 'set' + method[0,1].upcase + method[1,method.length].sub("=", "") if method =~ /.*[^-+%\/|]=$/
+
+ # If the method name contains underscores, convert to camel case
+ while method =~ /([^_]*)_(.)(.*)/
+ method = $1 + $2.upcase + $3
+ end
+
+ # Get the functions() for this dcop ref and
+ # cache method_name => full_type_signature in a hash
+ if @functions.nil?
+ @functions = {}
+ funcs = call("functions()")
+ if funcs.nil?
+ return nil
+ end
+ funcs.each do |func|
+ if func =~ /^([\w,<>:]*)\s+(.*)(\(.*\))/
+ return_type = $1
+ name = $2
+ args = $3
+ if args =~ / /
+ # Remove any arg names
+ args.gsub!(/ \w*/, "")
+ end
+
+ # Make thing? a synonym for isThing() or hasThing()
+ if name =~ /^(is|has)(.)(.*)/
+ predicate = $2.downcase + $3 + '?'
+ if @functions[predicate].nil?
+ @functions[predicate] = return_type + " " + name + args
+ end
+ end
+
+ if @functions[name].nil?
+ @functions[name] = return_type + " " + name + args
+ else
+ # If a function name is overloaded, just keep a single name entry in
+ # the hash, not all the full type signatures. Then leave dcopTypeNames()
+ # to try and resolve the ambiguous call from the ruby arg types passed.
+ @functions.delete(name)
+ @functions[name] = name
+ end
+ end
+ end
+ end
+
+ method = @functions[method]
+ if method.nil?
+ qWarning( "DCOPRef: call #{k[0].id2name}() not found" )
+ return
+ end
+
+ return callExt(method, *dcopArgs)
+ end
+ end
+
+ def dcopTypeNames(*k)
+ typeNames = "("
+ k.each do |arg|
+ if arg.kind_of? Integer
+ typeNames << "int,"
+ elsif arg.kind_of? Float
+ typeNames << "double,"
+ elsif arg.kind_of? Array
+ typeNames << "QStringList,"
+ elsif arg.kind_of? String
+ typeNames << "QString,"
+ elsif arg.kind_of? Qt::Base
+ typeNames << arg.class.name + ","
+ elsif arg.instance_of? FalseClass or arg.instance_of? TrueClass
+ typeNames << "bool,"
+ end
+ end
+ typeNames.sub!(/,$/, '')
+ typeNames.gsub!(/Qt::/, 'Q')
+ typeNames.gsub!(/KDE::/, 'K')
+ typeNames << ")"
+ return typeNames
+ end
+
+ def call(fun, *k)
+ k << NoEventLoop << -1
+ callExt(fun, *k)
+ end
+
+ def callExt(fun, *k)
+ if isNull
+ qWarning( "DCOPRef: call #{fun} on null reference error" )
+ return
+ end
+ sig = fun
+ if fun.index('(') == nil
+ sig << dcopTypeNames(*k[0, k.length - 2])
+ end
+ dc = dcopClient()
+ if !dc || !dc.isAttached
+ qWarning( "DCOPRef::call(): no DCOP client or client not attached error" )
+ return
+ end
+ if sig =~ /([^\s]*)(\(.*\))/
+ full_name = $1+$2
+ else
+ qWarning( "DCOPRef: call #{fun} invalid format, expecting '<function_name>(<args>)'" )
+ return
+ end
+ return KDE::dcop_call( self,
+ full_name,
+ Qt::Internal::getMocArguments(full_name),
+ *k )
+ end
+
+ def send(fun, *k)
+ if isNull
+ qWarning( "DCOPRef: send #{fun} on null reference error" )
+ end
+ sig = fun
+ if fun.index('(') == nil
+ sig << dcopTypeNames(*k)
+ end
+ dc = dcopClient()
+ if !dc || !dc.isAttached
+ qWarning( "DCOPRef::send(): no DCOP client or client not attached error" )
+ return
+ end
+ if !sig =~ /^([^\s]*)(\(.*\))/
+ qWarning( "DCOPRef: send #{sig} invalid format, expecting '<function_name>(<args>)'" )
+ return
+ end
+ return KDE::dcop_send( self,
+ fun,
+ Qt::Internal::getMocArguments(sig),
+ *k )
+ end
+
+ def methods
+ if @functions.nil?
+ functions()
+ end
+
+ result = super + @functions.keys.map {|k| k.sub(/^(set)([A-Z])(.*)/) { $2.downcase + $3 + '=' } }
+ return result.uniq
+ end
+
+ def inspect
+ str = super
+ str.sub(/>$/, " app=%s, obj=%s>" % [app.inspect, obj.inspect])
+ end
+
+ def pretty_print(pp)
+ str = to_s
+ pp.text str.sub(/>$/, "\n app=%s,\n obj=%s>" % [app.inspect, obj.inspect])
+ end
+
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ def CmdLineArgs::init(*k)
+ if k.length > 0
+ if k[0].kind_of? Array
+ # If init() is passed an array as the first argument, assume it's ARGV.
+ # Then convert to a pair of args 'ARGV.length+1, [$0]+ARGV'
+ array = k.shift
+ super(*([array.length+1] + [[$0] + array] + k))
+ elsif k[0].kind_of? KDE::AboutData
+ super(1, [$0], k[0])
+ end
+ else
+ super
+ end
+ end
+
+ # A sane alternative to the strange looking C++ template version,
+ # this takes a variable number of ruby args as classes to restore
+ def MainWindow::kRestoreMainWindows(*k)
+ n = 1
+ while MainWindow.canBeRestored(n)
+ className = MainWindow.classNameOfToplevel(n)
+ k.each do |klass|
+ if klass.name == className
+ klass.new.restore(n)
+ end
+ end
+ n += 1
+ end
+ end
+
+ class AboutData
+ def inspect
+ str = super
+ str.sub!(/>$/, " appName=%s, copyrightStatement=%s, programName=%s, version=%s, shortDescription=%s, homepage=%s, bugAddress=%s>" %
+ [appName.inspect, copyrightStatement.inspect, programName.inspect, version.inspect,
+ shortDescription.inspect, homepage.inspect, bugAddress.inspect] )
+ length = authors.length
+ if length > 0
+ str.sub!(/>$/, ", authors=Array (%d element(s))>" % length)
+ end
+ length = credits.length
+ if length > 0
+ str.sub!(/>$/, ", credits=Array (%d element(s))>" % length)
+ end
+ length = translators.length
+ if length > 0
+ str.sub!(/>$/, ", translators=Array (%d element(s))>" % length)
+ end
+ return str
+ end
+
+ def pretty_print(pp)
+ str = to_s
+ str.sub!(/>$/, "\n appName=%s,\n copyrightStatement=%s,\n programName=%s,\n version=%s,\n shortDescription=%s,\n homepage=%s,\n bugAddress=%s>" %
+ [appName.inspect, copyrightStatement.inspect, programName.inspect, version.inspect,
+ shortDescription.inspect, homepage.inspect, bugAddress.inspect] )
+ length = authors.length
+ if length > 0
+ str.sub!(/>$/, ",\n authors=Array (%d element(s))>" % length)
+ end
+ length = credits.length
+ if length > 0
+ str.sub!(/>$/, ",\n credits=Array (%d element(s))>" % length)
+ end
+ length = translators.length
+ if length > 0
+ str.sub!(/>$/, ",\n translators=Array (%d element(s))>" % length)
+ end
+ pp.text str
+ end
+ end
+
+ class AboutPerson
+ def inspect
+ str = super
+ str.sub(/>$/, " emailAddress=%s, name=%s, task=%s, webAddress=%s>" %
+ [emailAddress.inspect, name.inspect, task.inspect, webAddress.inspect] )
+ end
+
+ def pretty_print(pp)
+ str = to_s
+ pp.text str.sub(/>$/, "\n emailAddress=%s,\n name=%s,\n task=%s,\n webAddress=%s>" %
+ [emailAddress.inspect, name.inspect, task.inspect, webAddress.inspect] )
+ end
+
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class AboutTranslator
+ def inspect
+ str = super
+ str.sub(/>$/, " emailAddress=%s, name=%s>" %
+ [emailAddress.inspect, name.inspect] )
+ end
+
+ def pretty_print(pp)
+ str = to_s
+ pp.text str.sub(/>$/, "\n emailAddress=%s,\n name=%s>" %
+ [emailAddress.inspect, name.inspect] )
+ end
+
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class AccelShortcutList
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class ActionPtrShortcutList
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class ActionShortcutList
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class Application
+ def initialize(*k)
+ super
+ $kapp = self
+ end
+
+ # Delete the underlying C++ instance after exec returns
+ # Otherwise, rb_gc_call_finalizer_at_exit() can delete
+ # stuff that KDE::Application still needs for its cleanup.
+ def exec
+ method_missing(:exec)
+ self.dispose
+ Qt::Internal.application_terminated = true
+ end
+ end
+
+ class Archive
+ def open(*args)
+ method_missing(:open, *args)
+ end
+ end
+
+ class ArchiveEntry
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class BookmarkDrag
+ def format(*args)
+ method_missing(:format, *args)
+ end
+ end
+
+ class CModule
+ def load(*args)
+ method_missing(:load, *args)
+ end
+ end
+
+ class Catalogue
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class ColorDrag
+ def format(*args)
+ method_missing(:format, *args)
+ end
+ end
+
+ class CustomMenuEditor
+ def load(*args)
+ method_missing(:load, *args)
+ end
+ end
+
+ class FileItem
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class FileMetaInfoGroup
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class FileMetaInfoItem
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class FileTreeBranch
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class FilterDev
+ def open(*args)
+ method_missing(:open, *args)
+ end
+ end
+
+ class HTMLView
+ def print(*args)
+ method_missing(:print, *args)
+ end
+ end
+
+ class Icon
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class ImageEffect
+ def hash(*args)
+ method_missing(:hash, *args)
+ end
+ end
+
+ class ImageIO
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class ListView
+ include Enumerable
+
+ def each
+ it = Qt::ListViewItemIterator.new(self)
+ while it.current
+ yield it.current
+ it += 1
+ end
+ end
+
+ def sort(*args)
+ method_missing(:sort, *args)
+ end
+ end
+
+ class ListViewItem
+ include Enumerable
+
+ def each
+ it = Qt::ListViewItemIterator.new(self)
+ while it.current
+ yield it.current
+ it += 1
+ end
+ end
+
+ def sort(*args)
+ method_missing(:sort, *args)
+ end
+
+ def inspect
+ str = super
+ str.sub!(/>$/, "")
+ for i in 0..(listView.columns - 1)
+ str << " text%d=%s," % [i, self.text(i)]
+ end
+ str.sub!(/,?$/, ">")
+ end
+
+ def pretty_print(pp)
+ str = to_s
+ str.sub!(/>$/, "")
+ for i in 0..(listView.columns - 1)
+ str << " text%d=%s," % [i, self.text(i)]
+ end
+ str.sub!(/,?$/, ">")
+ pp.text str
+ end
+ end
+
+ class MainWindowInterface
+ def raise(*args)
+ method_missing(:raise, *args)
+ end
+ end
+
+ class MdiChildView
+ def raise(*args)
+ method_missing(:raise, *args)
+ end
+ end
+
+ class MimeType
+ def load(*args)
+ method_missing(:load, *args)
+ end
+ end
+
+ class MultiTabBarButton
+ def id(*args)
+ method_missing(:id, *args)
+ end
+ end
+
+ class MultipleDrag
+ def format(*args)
+ method_missing(:format, *args)
+ end
+ end
+
+ class NamedCommand
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class NewStuff
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class OCRDialog
+ def id(*args)
+ method_missing(:id, *args)
+ end
+ end
+
+ class Palette
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class PanelApplet
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class PanelExtension
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class Pixmap
+ def load(*args)
+ method_missing(:load, *args)
+ end
+ end
+
+ class PixmapEffect
+ def hash(*args)
+ method_missing(:hash, *args)
+ end
+ end
+
+ class PluginInfo
+ def load(*args)
+ method_missing(:load, *args)
+ end
+
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class PluginSelector
+ def load(*args)
+ method_missing(:load, *args)
+ end
+ end
+
+ class PopupFrame
+ def exec(*args)
+ method_missing(:exec, *args)
+ end
+ end
+
+ class PrintAction
+ def print(*args)
+ method_missing(:print, *args)
+ end
+ end
+
+ class Printer
+ def abort(*args)
+ method_missing(:abort, *args)
+ end
+ end
+
+ class Progress
+ def format(*args)
+ method_missing(:format, *args)
+ end
+ end
+
+ class ProtocolInfo
+ def exec(*args)
+ method_missing(:exec, *args)
+ end
+
+ def load(*args)
+ method_missing(:load, *args)
+ end
+
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class Pty
+ def open(*args)
+ method_missing(:open, *args)
+ end
+ end
+
+ class Run
+ def abort(*args)
+ method_missing(:abort, *args)
+ end
+ end
+
+ class SSLCertDlgRet
+ def send(*args)
+ method_missing(:send, *args)
+ end
+ end
+
+ class SSLPKCS12
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class SSLPKCS7
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class SSLSettings
+ def load(*args)
+ method_missing(:load, *args)
+ end
+ end
+
+ class SaveFile
+ def abort(*args)
+ method_missing(:abort, *args)
+ end
+
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class ScanDialog
+ def id(*args)
+ method_missing(:id, *args)
+ end
+ end
+
+ class Service
+ def inspect
+ str = super
+ str.sub(/>$/, " library=%s, type=%s, name=%s>" % [library.inspect, type.inspect, name.inspect])
+ end
+
+ def pretty_print(pp)
+ str = to_s
+ pp.text str.sub(/>$/, "\n library=%s,\n type=%s,\n name=%s>" % [library.inspect, type.inspect, name.inspect])
+ end
+
+ def exec(*args)
+ method_missing(:exec, *args)
+ end
+
+ def load(*args)
+ method_missing(:load, *args)
+ end
+
+ def name(*args)
+ method_missing(:name, *args)
+ end
+
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class ServiceGroup
+ def load(*args)
+ method_missing(:load, *args)
+ end
+
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class ServiceSeparator
+ def load(*args)
+ method_missing(:load, *args)
+ end
+
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class ServiceType
+ def load(*args)
+ method_missing(:load, *args)
+ end
+
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class Socks
+ def select(*args)
+ method_missing(:select, *args)
+ end
+
+ def send(*args)
+ method_missing(:send, *args)
+ end
+ end
+
+ class StdAccel
+ def name(*args)
+ method_missing(:name, *args)
+ end
+
+ def open(*args)
+ method_missing(:open, *args)
+ end
+
+ def print(*args)
+ method_missing(:print, *args)
+ end
+ end
+
+ class StdAccel::ShortcutList
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class StdAction
+ def name(*args)
+ method_missing(:name, *args)
+ end
+
+ def open(*args)
+ method_missing(:open, *args)
+ end
+
+ def print(*args)
+ method_missing(:print, *args)
+ end
+ end
+
+ class StdGuiItem
+ def open(*args)
+ method_missing(:open, *args)
+ end
+
+ def print(*args)
+ method_missing(:print, *args)
+ end
+
+ def test(*args)
+ method_missing(:test, *args)
+ end
+ end
+
+ class TempDir
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class TempFile
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class ToolBarButton
+ def id(*args)
+ method_missing(:id, *args)
+ end
+ end
+
+ class UniqueApplication
+ def initialize(*k)
+ super
+ $kapp = self
+ end
+
+ # Delete the underlying C++ instance after exec returns
+ # Otherwise, rb_gc_call_finalizer_at_exit() can delete
+ # stuff that KDE::Application still needs for its cleanup.
+ def exec
+ method_missing(:exec)
+ self.dispose
+ Qt::Internal.application_terminated = true
+ end
+ end
+
+ class URIFilterPlugin
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class URL
+ def inspect
+ str = super
+ str.sub(/>$/, " url=%s, protocol=%s, host=%s, port=%d>" % [url.inspect, protocol.inspect, host.inspect, port])
+ end
+
+ def pretty_print(pp)
+ str = to_s
+ pp.text str.sub(/>$/, "\n url=%s,\n protocol=%s,\n host=%s,\n port=%d>" % [url.inspect, protocol.inspect, host.inspect, port])
+ end
+
+ def split(*args)
+ method_missing(:split, *args)
+ end
+ end
+
+ class URLDrag
+ def format(*args)
+ method_missing(:format, *args)
+ end
+ end
+
+ class VMAllocator
+ def allocate(*args)
+ method_missing(:allocate, *args)
+ end
+ end
+
+ class WindowInfo
+ def display(*args)
+ method_missing(:display, *args)
+ end
+ end
+
+end
+
+module DOM
+ class Attr
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class DOMString
+ def split(*args)
+ method_missing(:split, *args)
+ end
+ end
+
+ class DocumentType
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class Event
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLAnchorElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLAnchorElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLAppletElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLButtonElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLButtonElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLElement
+ def id(*args)
+ method_missing(:id, *args)
+ end
+ end
+
+ class HTMLFormElement
+ def method(*args)
+ method_missing(:method, *args)
+ end
+ end
+
+ class HTMLFormElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLFrameElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLIFrameElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLImageElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLInputElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLInputElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLLIElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLLinkElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLMapElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLMetaElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLOListElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLObjectElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLObjectElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLParamElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLParamElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLScriptElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLSelectElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLSelectElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLStyleElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLTextAreaElement
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class HTMLTextAreaElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class HTMLUListElement
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class StyleSheet
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class CSSRule
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class Document
+ def abort(*args)
+ method_missing(:abort, *args)
+ end
+ end
+
+ class Document
+ def load(*args)
+ method_missing(:load, *args)
+ end
+ end
+
+ class HTMLDocument
+ def open(*args)
+ method_missing(:open, *args)
+ end
+ end
+
+ class HTMLInputElement
+ def select(*args)
+ method_missing(:select, *args)
+ end
+ end
+
+ class HTMLTextAreaElement
+ def select(*args)
+ method_missing(:select, *args)
+ end
+ end
+end # DOM
+
+module KIO
+ class Connection
+ def send(*args)
+ method_missing(:send, *args)
+ end
+ end
+
+ class NetRC::AutoLogin
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class Slave
+ def send(*args)
+ method_missing(:send, *args)
+ end
+ end
+
+ class SlaveBase
+ def exit(*args)
+ method_missing(:exit, *args)
+ end
+ end
+end # KIO
+
+module KNS
+ class Engine
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class Entry
+ def name(*args)
+ method_missing(:name, *args)
+ end
+
+ def type(*args)
+ method_missing(:type, *args)
+ end
+ end
+
+ class Provider
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+
+ class ProviderLoader
+ def load(*args)
+ method_missing(:load, *args)
+ end
+ end
+end # KNS
+
+module KParts
+ class Event
+ def test(*args)
+ method_missing(:test, *args)
+ end
+ end
+
+ class GUIActivateEvent
+ def test(*args)
+ method_missing(:test, *args)
+ end
+ end
+
+ class OpenURLEvent
+ def test(*args)
+ method_missing(:test, *args)
+ end
+ end
+
+ class PartActivateEvent
+ def test(*args)
+ method_missing(:test, *args)
+ end
+ end
+
+ class PartSelectEvent
+ def test(*args)
+ method_missing(:test, *args)
+ end
+ end
+end # KParts
+
+module Win
+ class Win::WindowInfo
+ def name(*args)
+ method_missing(:name, *args)
+ end
+ end
+end
+
+class Object
+ def RESTORE(klass)
+ n = 1
+ while MainWindow.canBeRestored(n)
+ klass.new.restore(n)
+ n += 1
+ end
+ end
+
+ def I18N_NOOP(x) x end
+ def I18N_NOOP2(comment, x) x end
+end
+
+class Qt::Base
+ def self.k_dcop_signals(*signal_list)
+ meta = KDE::DCOPMeta[self.name] || KDE::DCOPMetaInfo.new(self)
+ meta.add_signals(signal_list)
+ meta.changed = true
+ end
+
+ def self.k_dcop(*slot_list)
+ meta = KDE::DCOPMeta[self.name] || KDE::DCOPMetaInfo.new(self)
+ meta.add_slots(slot_list)
+ meta.changed = true
+ end
+end
diff --git a/korundum/rubylib/korundum/lib/Makefile.am b/korundum/rubylib/korundum/lib/Makefile.am
new file mode 100644
index 00000000..fba7d258
--- /dev/null
+++ b/korundum/rubylib/korundum/lib/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = KDE
diff --git a/korundum/rubylib/rbkconfig_compiler/Makefile.am b/korundum/rubylib/rbkconfig_compiler/Makefile.am
new file mode 100644
index 00000000..492c6882
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/Makefile.am
@@ -0,0 +1,28 @@
+SUBDIRS = . tests
+
+RBUIC=rbuic
+
+%.rb: %.ui
+ $(RBUIC) -tr ${UIC_TR} -kde $*.ui -o $@
+
+exampleprefs_base.rb: $(srcdir)/example.kcfg rbkconfig_compiler $(srcdir)/exampleprefs_base.kcfgc
+ ./rbkconfig_compiler $(srcdir)/example.kcfg $(srcdir)/exampleprefs_base.kcfgc
+
+AM_CPPFLAGS = -I$(top_srcdir)/kdecore -I$(top_srcdir) $(all_includes)
+
+bin_PROGRAMS = rbkconfig_compiler
+
+rbkconfig_compiler_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+rbkconfig_compiler_LDADD = $(LIB_KDECORE)
+rbkconfig_compiler_SOURCES = rbkconfig_compiler.cpp
+
+METASOURCES = AUTO
+
+TESTFILES = test1.kcfg test2.kcfg test3.kcfg test4.kcfg test5.kcfg
+
+check-local:
+ for i in $(TESTFILES); \
+ do xmllint --noout --schema $(srcdir)/kcfg.xsd $(srcdir)/tests/$$i; \
+ perl $(top_srcdir)/korundum/rubylib/rbkconfig_compiler/checkkcfg.pl \
+ $(top_srcdir)/korundum/rubylib/rbkconfig_compiler/tests/$$i; done
+
diff --git a/korundum/rubylib/rbkconfig_compiler/README.dox b/korundum/rubylib/rbkconfig_compiler/README.dox
new file mode 100644
index 00000000..97da4dc9
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/README.dox
@@ -0,0 +1,251 @@
+/**
+\page rbkconfig_compiler The KDE Configuration Compiler for Ruby
+
+rbkconfig_compiler generates Ruby source code from an XML file containing
+information about configuration options (.kcfg) and a file that provides
+the code generation options (.kcfgc) The generated class is based on
+KDE::ConfigSkeleton and provides an API for the application to access its
+configuration data.
+
+<h2>XML description of the configuration options</h2>
+
+The structure of the .kcfg file is described by its DTD kcfg.dtd.
+
+The \<kcfgfile\> tag contains the name of the configuration file described.
+Omitting the name will make the generated class use the default configuration
+file ("<appname>rc").
+
+The remaining entries in the XML file are grouped by the tag \<group\>
+which describes the corresponding group in the configuration file.
+
+The individual entries must have at least a name or a key. The name is used to
+create accessor and modifier functions. It's also used as the key in the config
+file. If \<key\> is given, but not \<name\>, the name is constructed by removing
+all spaces from \<key\>.
+
+An entry must also have a type. The list of allowable types is
+specified in the DTD and loosely follows the list of types supported
+by the Qt::Variant with exception of the clearly binary types
+(e.g. Pixmap, Image...) which are not supported. Besides those basic
+type the following special types are supported:
+
+- Path This is a string that is specially treated as a file-path.
+ In particular paths in the home directory are prefixed with $HOME in
+ when being stored in the configuration file.
+
+- Enum This indicates an enumeration. The possible enum values should
+ be provided via the \<choices\> tag. Enum values are accessed as integers
+ by the application but stored as string in the configuration file. This
+ makes it possible to add more values at a later date without breaking
+ compatibility.
+
+- IntList This indicates a list of integers. This information is provided
+ to the application as an Array of Integers. Useful for storing Qt::Splitter
+ geometries.
+
+An entry can optionally have a default value which is used as default when
+the value isn't specified in any config file. Default values are interpreted
+as literal constant values. If a default value needs to be computed
+or if it needs to be obtained from a function call, the \<default\> tag
+should contain the code="true" attribute. The contents of the \<default\>
+tag is then considered to be a ruby expression.
+
+Additional code for computing default values can be provided via
+the \<code\> tag. The contents of the \<code\> tag is inserted as-is. A
+typical use for this is to compute a common default value which can
+then be referenced by multiple entries that follow.
+
+<h2>Code generation options</h2>
+
+The options for generating the Ruby sources are read from the file with the
+extension .kcfgc. To generate a class add the corresponding kcfgc file to the
+SOURCES line in the Makefile.am.
+
+The following options are read from the kcfgc file:
+
+<table>
+<tr>
+ <td><b><i>Name</i></b></td>
+ <td><b><i>Type</i></b></td>
+ <td><b><i>Default</i></b></td>
+ <td><b><i>Description</i></b></td>
+</tr>
+<tr>
+ <td><b>File</b></td>
+ <td>string</td>
+ <td>programname.kcfg</td>
+ <td>Name of kcfg file containing the options the class is generated for</td>
+</tr>
+<tr>
+ <td><b>NameSpace</b></td>
+ <td>string</td>
+ <td>-</td>
+ <td>Optional namespace for generated class</td>
+</tr>
+<tr>
+ <td><b>ClassName</b></td>
+ <td>string</td>
+ <td>-</td>
+ <td>Name of generated class (required)</td>
+</tr>
+<tr>
+ <td><b>Inherits</b></td>
+ <td>string</td>
+ <td>KConfigSkeleton</td>
+ <td>Class the generated class inherits from. This class must inherit
+ KConfigSkeleton.</td>
+</tr>
+<tr>
+ <td><b>Visibility</b></td>
+ <td>string</td>
+ <td>-</td>
+ <td>Inserts visibility directive (for example KDE_EXPORT) between "class" keyword and class
+ name in header file</td>
+</tr>
+<tr>
+ <td><b>Singleton</b></td>
+ <td>bool</td>
+ <td>false</td>
+ <td>Generated class is a singleton.</td>
+</tr>
+<tr>
+ <td><b>CustomAdditions</b></td>
+ <td>bool</td>
+ <td>-</td>
+ <td></td>
+</tr>
+<tr>
+ <td><b>MemberVariables</b></td>
+ <td>string: public|protected|private</td>
+ <td>private</td>
+ <td>C++ access modifier used for memeber variables holding the configuration
+ valuse</td>
+</tr>
+<tr>
+ <td><b>IncludeFiles</b></td>
+ <td>comma separated list of strings</td>
+ <td>-</td>
+ <td>Names of files to be included in the header of the generated class</td>
+</tr>
+<tr>
+ <td><b>Mutators</b></td>
+ <td>true, false or a comma seperated list of options</td>
+ <td>-</td>
+ <td>If true, mutator functions for all configuration options are generated.
+ If false, no mutator functions are generated. If a list is provided,
+ mutator functions are generated for the options that are listed.</td>
+</tr>
+<tr>
+ <td><b>ItemAccessors</b></td>
+ <td>bool</td>
+ <td>false</td>
+ <td>Generate accessor functions for the KConfigSkeletonItem objects
+ corresponding to the configuration options. If <b>SetUserTexts</b> is set,
+ <b>ItemAccessors</b> also has to be set.</td>
+</tr>
+<tr>
+ <td><b>SetUserTexts</b></td>
+ <td>bool</td>
+ <td>false</td>
+ <td>Set the label and whatthis texts of the items from the kcfg file.If
+ <b>SetUserTexts</b> is set, <b>ItemAccessors</b> also has to be set.</td>
+</tr>
+<tr>
+ <td><b>GlobalEnums</b></td>
+ <td>bool</td>
+ <td>false</td>
+ <td>If set to true all choices of Enum items will be created in the global
+ scope of the generated class. If set to false, each Enum item will get an own
+ namespace for its choices.</td>
+</tr>
+</table>
+
+
+<h2>Advanced options</h2>
+
+There are several possibilities to parameterize entries.
+
+- Parameterized entries
+
+An entry can be parameterized using a fixed range parameter specified with
+the \<parameter\> tag. Such parameter can either be an Enum or an int. An Enum
+parameter should specify the possible enumeration values with the \<choices\>
+tag. An int parameter should specify its maximum value. Its minimum value
+is always 0.
+
+A parameterized entry is expanded to a number of entries, one for each
+value in the parameter range. The name and key should contain a reference
+to the parameter in the form of $(parameter-name). When expanding the entries
+the $(parameter-name) part is replaced with the value of the parameter.
+In the case of an Enum parameter it is replaced with the name of the
+enumuration value. In the case of an int parameter it is replaced with
+the numeric value of the parameter.
+
+Parameterized entries all share the same default value unless different
+default values have been specified for specific parameter values.
+This can be done with the param= attribute of the \<default\>. When a
+param attribute is specified the default value only applies to that
+particular parameter value.
+
+Example 1:
+\verbatim
+ <entry name="Color$(ColorIndex)" type="Color" key="color_$(ColorIndex)">
+ <parameter name="ColorIndex" type="Int" max="3"/>
+ <default param="0">#ff0000</default>
+ <default param="1">#00ff00</default>
+ <default param="2">#0000ff</default>
+ <default param="3">#ffff00</default>
+ </entry>
+\endverbatim
+
+The above describes 4 color configuration entries with the following defaults:
+
+color_0=#ff0000
+color_1=#00ff00
+color_2=#0000ff
+color_3=#ffff00
+
+The configuration options will be accessible to the application via
+a color(colorIndex) and a
+setColor(colorIndex, v) method.
+
+Example 2:
+\verbatim
+ <entry name="Sound$(SoundEvent)" type="String" key="sound_$(SoundEvent)">
+ <parameter name="SoundEvent" type="Enum">
+ <values>
+ <value>Explosion</value>
+ <value>Crash</value>
+ <value>Missile</value>
+ </values>
+ </parameter>
+ <default param="Explosion">boom.wav</default>
+ <default param="Crash">crash.wav</default>
+ <default param="Missile">missile.wav</default>
+ </entry>
+\endverbatim
+
+The above describes 3 string configuration entries with the following defaults:
+
+sound_Explosion=boom.wav
+sound_Crash=crash.wav
+sound_Missile=missile.wav
+
+The configuration options will be accessible to the application via
+a sound(soundEvent) and a
+setSound(soundEvent, v) method.
+
+- Parameterized groups
+
+...STILL TODO...
+
+
+
+
+
+If you have questions or comments please contact Cornelius Schumacher
+<schumacher@kde.org> or Waldo Bastian <bastian@kde.org>
+
+For Ruby specific questions please contact Richard Dale
+<Richard_Dale@tipitina.demon.co.uk>
+*/
diff --git a/korundum/rubylib/rbkconfig_compiler/TODO b/korundum/rubylib/rbkconfig_compiler/TODO
new file mode 100644
index 00000000..db4137ed
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/TODO
@@ -0,0 +1 @@
+- Support linebreaks in whasthis texts in the kcfg file.
diff --git a/korundum/rubylib/rbkconfig_compiler/autoexample.rb b/korundum/rubylib/rbkconfig_compiler/autoexample.rb
new file mode 100644
index 00000000..8526c93d
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/autoexample.rb
@@ -0,0 +1,49 @@
+=begin
+ This file is part of KDE.
+
+ Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+=end
+
+require 'Korundum'
+require 'exampleprefs_base.rb'
+require 'general_base.rb'
+require 'myoptions_base.rb'
+
+ aboutData = KDE::AboutData.new( "example", I18N_NOOP("autoconfig example"), "0.1" )
+ aboutData.addAuthor( "Cornelius Schumacher", nil, "schumacher@kde.org" )
+
+ KDE::CmdLineArgs.init( ARGV, aboutData )
+
+ app = KDE::Application.new
+
+ configSkeleton = ExamplePrefsBase.new( "dummy1", "dummy2" )
+ configSkeleton.readConfig()
+
+ dialog = KDE::ConfigDialog.new( nil, "settings", configSkeleton )
+
+ general = GeneralBase.new(nil)
+ dialog.addPage( general, app.i18n("General"), "General", "" )
+
+ myOptions = MyOptionsBase.new( nil )
+ dialog.addPage( myOptions, app.i18n("MyOptions"), "MyOptions", "" )
+
+ app.mainWidget = dialog
+
+ dialog.show()
+
+ app.exec
diff --git a/korundum/rubylib/rbkconfig_compiler/checkkcfg.pl b/korundum/rubylib/rbkconfig_compiler/checkkcfg.pl
new file mode 100755
index 00000000..2eddbeee
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/checkkcfg.pl
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+
+if ( @ARGV != 1 ) {
+ print STDERR "Missing arg: filename\n";
+ exit 1;
+}
+
+$file = $ARGV[0];
+
+$file =~ /^(.*)\.[^\.]*$/;
+$filebase = $1;
+
+$file_h = "$filebase.h";
+$file_cpp = "$filebase.cpp";
+
+$kcfgc = $file . "c";
+
+$cmd = "./kconfig_compiler $file $kcfgc";
+
+#print "CMD $cmd\n";
+
+if ( system( $cmd ) != 0 ) {
+ print STDERR "Unable to run kconfig_compiler\n";
+ exit 1;
+}
+
+checkfile( $file_h );
+checkfile( $file_cpp );
+
+exit 0;
+
+sub checkfile()
+{
+ my $file = shift;
+
+ $file =~ /\/([^\/]*)$/;
+ my $filename = $1;
+
+ print "Checking '$filename':\n";
+
+ my @ref;
+ if ( !open( REF, "$file.ref" ) ) {
+ print STDERR "Unable to open $file.ref\n";
+ exit 1;
+ }
+ while( <REF> ) {
+ push @ref, $_;
+ }
+ close REF;
+
+ if ( !open( READ, $filename ) ) {
+ print STDERR "Unable to open $filename\n";
+ exit 1;
+ }
+
+ $error = 0;
+ $i = 0;
+ $line = 1;
+ while( <READ> ) {
+ $out = $_;
+ $ref = @ref[$i++];
+
+ if ( $out ne $ref ) {
+ $error++;
+ print " Line $line: Expected : $ref";
+ print " Line $line: Compiler output : $out";
+ }
+
+ $line++;
+ }
+
+ close READ;
+
+ if ( $error > 0 ) {
+ print "\n FAILED: $error errors found.\n";
+ if ( $error > 5 ) {
+ system( "diff -u $file.ref $filename" );
+ }
+ exit 1;
+ } else {
+ print " OK\n";
+ }
+}
diff --git a/korundum/rubylib/rbkconfig_compiler/example.kcfg b/korundum/rubylib/rbkconfig_compiler/example.kcfg
new file mode 100644
index 00000000..89d1e646
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/example.kcfg
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <include>qdir.h</include>
+ <kcfgfile name="examplerc">
+ <parameter name="transport" />
+ <parameter name="folder" />
+ </kcfgfile>
+ <group name="General-$(folder)">
+ <entry name="OneOption" type="Bool">
+ <label>One option</label>
+ <default>true</default>
+ </entry>
+ <entry name="AnotherOption" type="Int" key="Another Option">
+ <label>Another option</label>
+ <default>5</default>
+ </entry>
+ <entry name="ListOption" type="Enum">
+ <label>This is some funky option</label>
+ <whatsthis>And this is a longer description of this option. Just wondering, how will the translations of those be handled?</whatsthis>
+ <choices>
+ <choice name="One"/>
+ <choice name="Two"/>
+ <choice name="Three"/>
+ </choices>
+ <default>One</default>
+ </entry>
+ </group>
+ <group name="MyOptions">
+ <entry name="MyString" type="String">
+ <label>This is a string</label>
+ <default>Default String</default>
+ </entry>
+ <entry name="MyPath" type="Path">
+ <label>This is a path</label>
+ <default code="true">Qt::Dir.homeDirPath()+".hidden_file"</default>
+ </entry>
+ <entry name="AnotherOption2" type="Int" key="Another Option">
+ <label>Another option</label>
+ <default>10</default>
+ </entry>
+ <entry name="MyStringList" type="StringList">
+ <default>up,down</default>
+ </entry>
+ <entry name="MyStringListHidden" hidden="true" type="StringList">
+ <default>up,down</default>
+ </entry>
+ <entry name="MyNumber" type="Int64" key="List-$(transport)-$(folder)">
+ <label>List Number</label>
+ <default>1</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/korundum/rubylib/rbkconfig_compiler/example.rb b/korundum/rubylib/rbkconfig_compiler/example.rb
new file mode 100644
index 00000000..d7ef38b1
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/example.rb
@@ -0,0 +1,40 @@
+=begin
+ This file is part of KDE.
+
+ Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+=end
+
+require 'Korundum'
+require 'exampleprefs_base.rb'
+
+ aboutData = KDE::AboutData.new( "example", I18N_NOOP("cfgc example"), "0.1" )
+ aboutData.addAuthor( "Cornelius Schumacher", nil, "schumacher@kde.org" )
+
+ KDE::CmdLineArgs.init( ARGV, aboutData )
+
+ app = KDE::Application.new
+
+ prefs = ExamplePrefsBase.new("Trans1", "Folder2")
+
+ prefs.readConfig()
+
+ prefs.setAnotherOption(17)
+
+
+ qWarning("Another Option = %d" % prefs.anotherOption())
+ qWarning("Another Option2 = %d" % prefs.anotherOption2())
diff --git a/korundum/rubylib/rbkconfig_compiler/exampleprefs_base.kcfgc b/korundum/rubylib/rbkconfig_compiler/exampleprefs_base.kcfgc
new file mode 100644
index 00000000..957ed912
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/exampleprefs_base.kcfgc
@@ -0,0 +1,18 @@
+# Code generation options for kconfig_compiler
+ClassName=ExamplePrefsBase
+#
+# Singleton=false
+#
+# Inherits=KConfigSkeleton
+#
+# IncludeFiles=libkdepim/kpimprefs.h
+#
+# MemberVariables=public
+#
+### The following line includes the file exampleprefs_base_addon.h
+### It can be used to add extra functions and variables to the
+### class.
+# CustomAdditions=true
+#
+### Provide setFooBar(int) style functions
+Mutators=true
diff --git a/korundum/rubylib/rbkconfig_compiler/general_base.ui b/korundum/rubylib/rbkconfig_compiler/general_base.ui
new file mode 100644
index 00000000..9b41370c
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/general_base.ui
@@ -0,0 +1,46 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>GeneralBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>GeneralBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>486</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>AutoExampleDialog</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>kcfg_OneOption</cstring>
+ </property>
+ <property name="text">
+ <string>OneOption</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>kcfg_AnotherOption2</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>AnotherOption:</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/korundum/rubylib/rbkconfig_compiler/kcfg.xsd b/korundum/rubylib/rbkconfig_compiler/kcfg.xsd
new file mode 100644
index 00000000..61450d25
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/kcfg.xsd
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- kcfg XSD v1.0 -->
+<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:kcfg="http://www.kde.org/standards/kcfg/1.0"
+ targetNamespace="http://www.kde.org/standards/kcfg/1.0"
+ version="1.0"
+ elementFormDefault="qualified" >
+
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Copyright (c) 2003 Cornelius Schumacher &lt;schumacher@kde.org&gt;
+ Copyright (c) 2003 Waldo Bastian &lt;bastian@kde.org&gt;
+ Copyright (c) 2003 Zack Rusin &lt;zack@kde.org&gt;
+ Copyright (c) 2004 Frans Englich &lt;frans.englich@telia.com&gt;
+
+ Permission to use, copy, modify and distribute this DTD
+ and its accompanying documentation for any purpose and without fee
+ is hereby granted in perpetuity, provided that the above copyright
+ notice and this paragraph appear in all copies. The copyright
+ holders make no representation about the suitability of the DTD for
+ any purpose. It is provided "as is" without expressed or implied
+ warranty.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:annotation>
+ <xsd:documentation>
+
+ A Schema for KDE's KConfigXT XML format. It is similar to the DTD
+ found at:
+
+ http://www.kde.org/standards/kcfg/1.0/kcfg.dtd
+
+ Documents valid against the Schema version are backwards compatible
+ to the DTD. Validating against the Schema instead of the DTD is
+ recommended, since the former provides better validation.
+
+ A document instance of this Schema should have a declaration
+ looking like this:
+
+ <![CDATA[
+
+ <?xml version="1.0" encoding="UTF-8" ?>
+ <kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <!-- the content -->
+ </kcfg>
+
+ ]]>
+
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:element name="kcfg">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="include" minOccurs="0" maxOccurs="unbounded" type="xsd:string"/>
+ <xsd:element name="kcfgfile" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="parameter" type="kcfg:parameter" minOccurs="0" maxOccurs="unbounded" />
+ <!-- FIXME: Are really unbounded occurances of parameter allowed? -->
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="arg" type="xsd:boolean" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="group" maxOccurs="unbounded" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="entry" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="parameter" minOccurs="0" type="kcfg:parameter"/>
+ <xsd:element name="label" minOccurs="0" type="xsd:string"/>
+ <xsd:element name="whatsthis" minOccurs="0" type="xsd:string"/>
+ <xsd:element name="choices" minOccurs="0">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="choice" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element minOccurs="0" name="label" type="xsd:string"/>
+ <xsd:element minOccurs="0" name="whatsthis" type="xsd:string"/>
+ </xsd:all>
+ <xsd:attribute name="name" use="required" type="xsd:string"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="code" minOccurs="0" type="kcfg:code"/>
+
+ <xsd:element name="default" maxOccurs="unbounded" minOccurs="0" >
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute use="optional" name="code" type="xsd:boolean"/>
+ <xsd:attribute use="optional" name="param" type="xsd:string"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="min" minOccurs="0" >
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="code" type="xsd:boolean"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="max" minOccurs="0">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="code" type="xsd:boolean"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ </xsd:choice>
+ <xsd:attribute name="name" use="optional" type="xsd:string"/>
+ <xsd:attribute name="key" use="optional" type="xsd:string"/>
+ <xsd:attribute name="hidden" use="optional" type="xsd:boolean"/>
+ <xsd:attribute name="type" type="kcfg:datatype"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:simpleType name="datatype">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="String"/>
+ <xsd:enumeration value="StringList"/>
+ <xsd:enumeration value="Font"/>
+ <xsd:enumeration value="Rect"/>
+ <xsd:enumeration value="Size"/>
+ <xsd:enumeration value="Color"/>
+ <xsd:enumeration value="Point"/>
+ <xsd:enumeration value="Int"/>
+ <xsd:enumeration value="UInt"/>
+ <xsd:enumeration value="Bool"/>
+ <xsd:enumeration value="Double"/>
+ <xsd:enumeration value="DateTime"/>
+ <xsd:enumeration value="Int64"/>
+ <xsd:enumeration value="UInt64"/>
+ <xsd:enumeration value="IntList"/>
+ <xsd:enumeration value="Enum"/>
+ <xsd:enumeration value="Path"/>
+ <xsd:enumeration value="Password"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="parameter">
+ <xsd:sequence>
+ <xsd:element minOccurs="0" name="values">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" maxOccurs="unbounded" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string"/>
+ <xsd:attribute name="type" use="optional" type="kcfg:datatype" />
+ <xsd:attribute name="max" use="optional" type="xsd:positiveInteger"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="code">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string"/>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+</xsd:schema>
+
diff --git a/korundum/rubylib/rbkconfig_compiler/myoptions_base.ui b/korundum/rubylib/rbkconfig_compiler/myoptions_base.ui
new file mode 100644
index 00000000..3c0c2e6c
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/myoptions_base.ui
@@ -0,0 +1,35 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>MyOptionsBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>MyOptionsBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>486</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>MyString:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>kcfg_MyString</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/korundum/rubylib/rbkconfig_compiler/rbkconfig_compiler.cpp b/korundum/rubylib/rbkconfig_compiler/rbkconfig_compiler.cpp
new file mode 100644
index 00000000..6274e4bf
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/rbkconfig_compiler.cpp
@@ -0,0 +1,1330 @@
+// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
+/*
+ This file is part of KDE.
+
+ Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
+ Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
+ Copyright (c) 2003 Zack Rusin <zack@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qdom.h>
+#include <qregexp.h>
+
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kcmdlineargs.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <ksimpleconfig.h>
+#include <kstandarddirs.h>
+
+#include <iostream>
+
+static const KCmdLineOptions options[] =
+{
+ { "d", 0, 0 },
+ { "directory <dir>", I18N_NOOP("Directory to generate files in"), "." },
+ { "+file.kcfg", I18N_NOOP("Input kcfg XML file"), 0 },
+ { "+file.kcfgc", I18N_NOOP("Code generation options file"), 0 },
+ KCmdLineLastOption
+};
+
+
+bool globalEnums;
+bool itemAccessors;
+QStringList allNames;
+QRegExp *validNameRegexp;
+
+class CfgEntry
+{
+ public:
+ struct Choice
+ {
+ QString name;
+ QString label;
+ QString whatsThis;
+ };
+
+ CfgEntry( const QString &group, const QString &type, const QString &key,
+ const QString &name, const QString &label,
+ const QString &whatsThis, const QString &code,
+ const QString &defaultValue, const QValueList<Choice> &choices,
+ bool hidden )
+ : mGroup( group ), mType( type ), mKey( key ), mName( name ),
+ mLabel( label ), mWhatsThis( whatsThis ), mCode( code ),
+ mDefaultValue( defaultValue ),
+ mChoices( choices ), mHidden( hidden )
+ {
+ }
+
+ void setGroup( const QString &group ) { mGroup = group; }
+ QString group() const { return mGroup; }
+
+ void setType( const QString &type ) { mType = type; }
+ QString type() const { return mType; }
+
+ void setKey( const QString &key ) { mKey = key; }
+ QString key() const { return mKey; }
+
+ void setName( const QString &name ) { mName = name; }
+ QString name() const { return mName; }
+
+ void setLabel( const QString &label ) { mLabel = label; }
+ QString label() const { return mLabel; }
+
+ void setWhatsThis( const QString &whatsThis ) { mWhatsThis = whatsThis; }
+ QString whatsThis() const { return mWhatsThis; }
+
+ void setDefaultValue( const QString &d ) { mDefaultValue = d; }
+ QString defaultValue() const { return mDefaultValue; }
+
+ void setCode( const QString &d ) { mCode = d; }
+ QString code() const { return mCode; }
+
+ void setMinValue( const QString &d ) { mMin = d; }
+ QString minValue() const { return mMin; }
+
+ void setMaxValue( const QString &d ) { mMax = d; }
+ QString maxValue() const { return mMax; }
+
+ void setParam( const QString &d ) { mParam = d; }
+ QString param() const { return mParam; }
+
+ void setParamName( const QString &d ) { mParamName = d; }
+ QString paramName() const { return mParamName; }
+
+ void setParamType( const QString &d ) { mParamType = d; }
+ QString paramType() const { return mParamType; }
+
+ void setChoices( const QValueList<Choice> &d ) { mChoices = d; }
+ QValueList<Choice> choices() const { return mChoices; }
+
+ void setParamValues( const QStringList &d ) { mParamValues = d; }
+ QStringList paramValues() const { return mParamValues; }
+
+ void setParamDefaultValues( const QStringList &d ) { mParamDefaultValues = d; }
+ QString paramDefaultValue(int i) const { return mParamDefaultValues[i]; }
+
+ void setParamMax( int d ) { mParamMax = d; }
+ int paramMax() const { return mParamMax; }
+
+ bool hidden() const { return mHidden; }
+
+ void dump() const
+ {
+ kdDebug() << "<entry>" << endl;
+ kdDebug() << " group: " << mGroup << endl;
+ kdDebug() << " type: " << mType << endl;
+ kdDebug() << " key: " << mKey << endl;
+ kdDebug() << " name: " << mName << endl;
+ kdDebug() << " label: " << mLabel << endl;
+// whatsthis
+ kdDebug() << " code: " << mCode << endl;
+// kdDebug() << " values: " << mValues.join(":") << endl;
+
+ if (!param().isEmpty())
+ {
+ kdDebug() << " param name: "<< mParamName << endl;
+ kdDebug() << " param type: "<< mParamType << endl;
+ kdDebug() << " paramvalues: " << mParamValues.join(":") << endl;
+ }
+ kdDebug() << " default: " << mDefaultValue << endl;
+ kdDebug() << " hidden: " << mHidden << endl;
+ kdDebug() << " min: " << mMin << endl;
+ kdDebug() << " max: " << mMax << endl;
+ kdDebug() << "</entry>" << endl;
+ }
+
+ private:
+ QString mGroup;
+ QString mType;
+ QString mKey;
+ QString mName;
+ QString mLabel;
+ QString mWhatsThis;
+ QString mCode;
+ QString mDefaultValue;
+ QString mParam;
+ QString mParamName;
+ QString mParamType;
+ QValueList<Choice> mChoices;
+ QStringList mParamValues;
+ QStringList mParamDefaultValues;
+ int mParamMax;
+ bool mHidden;
+ QString mMin;
+ QString mMax;
+};
+
+
+static QString varName(const QString &n)
+{
+ QString result = "@"+n;
+ result[1] = result[1].lower();
+ return result;
+}
+
+static QString enumName(const QString &n)
+{
+ QString result = "Enum"+n;
+ result[4] = result[4].upper();
+ return result;
+}
+
+static QString enumValue(const QString &n)
+{
+ QString result = n;
+ result[0] = result[0].upper();
+ return result;
+}
+
+static QString setFunction(const QString &n)
+{
+ QString result = "set"+n;
+ result[3] = result[3].upper();
+ return result;
+}
+
+
+static QString getFunction(const QString &n)
+{
+ QString result = n;
+ result[0] = result[0].lower();
+ return result;
+}
+
+
+static void addQuotes( QString &s )
+{
+ if ( s.left( 1 ) != "\"" ) s.prepend( "\"" );
+ if ( s.right( 1 ) != "\"" ) s.append( "\"" );
+}
+
+static QString quoteString( const QString &s )
+{
+ QString r = s;
+ r.replace( "\\", "\\\\" );
+ r.replace( "\"", "\\\"" );
+ r.replace( "\r", "" );
+ r.replace( "\n", "\\n\"\n\"" );
+ return "\"" + r + "\"";
+}
+
+static QString literalString( const QString &s )
+{
+ bool isAscii = true;
+ for(int i = s.length(); i--;)
+ if (s[i].unicode() > 127) isAscii = false;
+
+ return quoteString(s);
+
+// if (isAscii)
+// return "QString::fromLatin1( " + quoteString(s) + " )";
+// else
+// return "QString::fromUtf8( " + quoteString(s) + " )";
+}
+
+static QString dumpNode(const QDomNode &node)
+{
+ QString msg;
+ QTextStream s(&msg, IO_WriteOnly );
+ node.save(s, 0);
+
+ msg = msg.simplifyWhiteSpace();
+ if (msg.length() > 40)
+ return msg.left(37)+"...";
+ return msg;
+}
+
+static QString filenameOnly(QString path)
+{
+ int i = path.findRev('/');
+ if (i >= 0)
+ return path.mid(i+1);
+ return path;
+}
+
+static void preProcessDefault( QString &defaultValue, const QString &name,
+ const QString &type,
+ const QValueList<CfgEntry::Choice> &choices,
+ QString &code )
+{
+ if ( type == "String" && !defaultValue.isEmpty() ) {
+ defaultValue = literalString(defaultValue);
+
+ } else if ( type == "Path" && !defaultValue.isEmpty() ) {
+ defaultValue = literalString( defaultValue );
+
+ } else if ( type == "StringList" && !defaultValue.isEmpty() ) {
+ QTextStream rb( &code, IO_WriteOnly | IO_Append );
+ if (!code.isEmpty())
+ rb << endl;
+
+// rb << " QStringList default" << name << ";" << endl;
+ rb << " default" << name << " = []" << endl;
+ QStringList defaults = QStringList::split( ",", defaultValue );
+ QStringList::ConstIterator it;
+ for( it = defaults.begin(); it != defaults.end(); ++it ) {
+ rb << " default" << name << " << \"" << *it << "\""
+ << endl;
+ }
+ defaultValue = "default" + name;
+
+ } else if ( type == "Color" && !defaultValue.isEmpty() ) {
+ QRegExp colorRe("\\d+,\\s*\\d+,\\s*\\d+");
+ if (colorRe.exactMatch(defaultValue))
+ {
+ defaultValue = "Qt::Color.new( " + defaultValue + " )";
+ }
+ else
+ {
+ defaultValue = "Qt::Color.new( \"" + defaultValue + "\" )";
+ }
+
+ } else if ( type == "Enum" ) {
+ if ( !globalEnums ) {
+ QValueList<CfgEntry::Choice>::ConstIterator it;
+ for( it = choices.begin(); it != choices.end(); ++it ) {
+ if ( (*it).name == defaultValue ) {
+ defaultValue.prepend( enumName(name) + "_");
+ break;
+ }
+ }
+ }
+
+ } else if ( type == "IntList" ) {
+ QTextStream rb( &code, IO_WriteOnly | IO_Append );
+ if (!code.isEmpty())
+ rb << endl;
+
+ rb << " default" << name << " = []" << endl;
+ QStringList defaults = QStringList::split( ",", defaultValue );
+ QStringList::ConstIterator it;
+ for( it = defaults.begin(); it != defaults.end(); ++it ) {
+ rb << " default" << name << " << " << *it << ""
+ << endl;
+ }
+ defaultValue = "default" + name;
+ }
+}
+
+
+CfgEntry *parseEntry( const QString &group, const QDomElement &element )
+{
+ bool defaultCode = false;
+ QString type = element.attribute( "type" );
+ QString name = element.attribute( "name" );
+ QString key = element.attribute( "key" );
+ QString hidden = element.attribute( "hidden" );
+ QString label;
+ QString whatsThis;
+ QString defaultValue;
+ QString code;
+ QString param;
+ QString paramName;
+ QString paramType;
+ QValueList<CfgEntry::Choice> choices;
+ QStringList paramValues;
+ QStringList paramDefaultValues;
+ QString minValue;
+ QString maxValue;
+ int paramMax = 0;
+
+ QDomNode n;
+ for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
+ QDomElement e = n.toElement();
+ QString tag = e.tagName();
+ if ( tag == "label" ) label = e.text();
+ else if ( tag == "whatsthis" ) whatsThis = e.text();
+ else if ( tag == "min" ) minValue = e.text();
+ else if ( tag == "max" ) maxValue = e.text();
+ else if ( tag == "code" ) code = e.text();
+ else if ( tag == "parameter" )
+ {
+ param = e.attribute( "name" );
+ paramType = e.attribute( "type" );
+ if ( param.isEmpty() ) {
+ kdError() << "Parameter must have a name: " << dumpNode(e) << endl;
+ return 0;
+ }
+ if ( paramType.isEmpty() ) {
+ kdError() << "Parameter must have a type: " << dumpNode(e) << endl;
+ return 0;
+ }
+ if ((paramType == "Int") || (paramType == "UInt"))
+ {
+ bool ok;
+ paramMax = e.attribute("max").toInt(&ok);
+ if (!ok)
+ {
+ kdError() << "Integer parameter must have a maximum (e.g. max=\"0\"): " << dumpNode(e) << endl;
+ return 0;
+ }
+ }
+ else if (paramType == "Enum")
+ {
+ QDomNode n2;
+ for ( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
+ QDomElement e2 = n2.toElement();
+ if (e2.tagName() == "values")
+ {
+ QDomNode n3;
+ for ( n3 = e2.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) {
+ QDomElement e3 = n3.toElement();
+ if (e3.tagName() == "value")
+ {
+ paramValues.append( e3.text() );
+ }
+ }
+ break;
+ }
+ }
+ if (paramValues.isEmpty())
+ {
+ kdError() << "No values specified for parameter '" << param << "'." << endl;
+ return 0;
+ }
+ paramMax = paramValues.count()-1;
+ }
+ else
+ {
+ kdError() << "Parameter '" << param << "' has type " << paramType << " but must be of type int, uint or Enum." << endl;
+ return 0;
+ }
+ }
+ else if ( tag == "default" )
+ {
+ if (e.attribute("param").isEmpty())
+ {
+ defaultValue = e.text();
+ if (e.attribute( "code" ) == "true")
+ defaultCode = true;
+ }
+ }
+ else if ( tag == "choices" ) {
+ QDomNode n2;
+ for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
+ QDomElement e2 = n2.toElement();
+ if ( e2.tagName() == "choice" ) {
+ QDomNode n3;
+ CfgEntry::Choice choice;
+ choice.name = e2.attribute( "name" );
+ if ( choice.name.isEmpty() ) {
+ kdError() << "Tag <choice> requires attribute 'name'." << endl;
+ }
+ for( n3 = e2.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) {
+ QDomElement e3 = n3.toElement();
+ if ( e3.tagName() == "label" ) choice.label = e3.text();
+ if ( e3.tagName() == "whatsthis" ) choice.whatsThis = e3.text();
+ }
+ choices.append( choice );
+ }
+ }
+ }
+ }
+
+ bool nameIsEmpty = name.isEmpty();
+ if ( nameIsEmpty && key.isEmpty() ) {
+ kdError() << "Entry must have a name or a key: " << dumpNode(element) << endl;
+ return 0;
+ }
+
+ if ( key.isEmpty() ) {
+ key = name;
+ }
+
+ if ( nameIsEmpty ) {
+ name = key;
+ name.replace( " ", QString::null );
+ } else if ( name.contains( ' ' ) ) {
+ kdWarning()<<"Entry '"<<name<<"' contains spaces! <name> elements can't contain speces!"<<endl;
+ name.remove( ' ' );
+ }
+
+ if (name.contains("$("))
+ {
+ if (param.isEmpty())
+ {
+ kdError() << "Name may not be parameterized: " << name << endl;
+ return 0;
+ }
+ }
+ else
+ {
+ if (!param.isEmpty())
+ {
+ kdError() << "Name must contain '$(" << param << ")': " << name << endl;
+ return 0;
+ }
+ }
+
+ if ( label.isEmpty() ) {
+ label = key;
+ }
+
+ if ( type.isEmpty() ) type = "String"; // XXX : implicit type might be bad
+
+ if (!param.isEmpty())
+ {
+ // Adjust name
+ paramName = name;
+ name.replace("$("+param+")", QString::null);
+ // Lookup defaults for indexed entries
+ for(int i = 0; i <= paramMax; i++)
+ {
+ paramDefaultValues.append(QString::null);
+ }
+
+ QDomNode n;
+ for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
+ QDomElement e = n.toElement();
+ QString tag = e.tagName();
+ if ( tag == "default" )
+ {
+ QString index = e.attribute("param");
+ if (index.isEmpty())
+ continue;
+
+ bool ok;
+ int i = index.toInt(&ok);
+ if (!ok)
+ {
+ i = paramValues.findIndex(index);
+ if (i == -1)
+ {
+ kdError() << "Index '" << index << "' for default value is unknown." << endl;
+ return 0;
+ }
+ }
+
+ if ((i < 0) || (i > paramMax))
+ {
+ kdError() << "Index '" << i << "' for default value is out of range [0, "<< paramMax<<"]." << endl;
+ return 0;
+ }
+
+ QString tmpDefaultValue = e.text();
+
+ if (e.attribute( "code" ) != "true")
+ preProcessDefault(tmpDefaultValue, name, type, choices, code);
+
+ paramDefaultValues[i] = tmpDefaultValue;
+ }
+ }
+ }
+
+ if (!validNameRegexp->exactMatch(name))
+ {
+ if (nameIsEmpty)
+ kdError() << "The key '" << key << "' can not be used as name for the entry because "
+ "it is not a valid name. You need to specify a valid name for this entry." << endl;
+ else
+ kdError() << "The name '" << name << "' is not a valid name for an entry." << endl;
+ return 0;
+ }
+
+ if (allNames.contains(name))
+ {
+ if (nameIsEmpty)
+ kdError() << "The key '" << key << "' can not be used as name for the entry because "
+ "it does not result in a unique name. You need to specify a unique name for this entry." << endl;
+ else
+ kdError() << "The name '" << name << "' is not unique." << endl;
+ return 0;
+ }
+ allNames.append(name);
+
+ if (!defaultCode)
+ {
+ preProcessDefault(defaultValue, name, type, choices, code);
+ }
+
+ CfgEntry *result = new CfgEntry( group, type, key, name, label, whatsThis,
+ code, defaultValue, choices,
+ hidden == "true" );
+ if (!param.isEmpty())
+ {
+ result->setParam(param);
+ result->setParamName(paramName);
+ result->setParamType(paramType);
+ result->setParamValues(paramValues);
+ result->setParamDefaultValues(paramDefaultValues);
+ result->setParamMax(paramMax);
+ }
+ result->setMinValue(minValue);
+ result->setMaxValue(maxValue);
+
+ return result;
+}
+
+/**
+ Return parameter declaration for given type.
+*/
+QString param( const QString &type )
+{
+ if ( type == "String" ) return "const QString &";
+ else if ( type == "StringList" ) return "const QStringList &";
+ else if ( type == "Font" ) return "const QFont &";
+ else if ( type == "Rect" ) return "const QRect &";
+ else if ( type == "Size" ) return "const QSize &";
+ else if ( type == "Color" ) return "const QColor &";
+ else if ( type == "Point" ) return "const QPoint &";
+ else if ( type == "Int" ) return "int";
+ else if ( type == "UInt" ) return "uint";
+ else if ( type == "Bool" ) return "bool";
+ else if ( type == "Double" ) return "double";
+ else if ( type == "DateTime" ) return "const QDateTime &";
+ else if ( type == "Int64" ) return "Q_INT64";
+ else if ( type == "UInt64" ) return "Q_UINT64";
+ else if ( type == "IntList" ) return "const QValueList<int> &";
+ else if ( type == "Enum" ) return "int";
+ else if ( type == "Path" ) return "const QString &";
+ else if ( type == "Password" ) return "const QString &";
+ else {
+ kdError() <<"rbkconfig_compiler does not support type \""<< type <<"\""<<endl;
+ return "QString"; //For now, but an assert would be better
+ }
+}
+
+/**
+ Actual Ruby initializer value to give a type.
+*/
+QString rbType( const QString &type )
+{
+ if ( type == "String" ) return "\"\"";
+ else if ( type == "StringList" ) return "[]";
+ else if ( type == "Font" ) return "Qt::Font.new";
+ else if ( type == "Rect" ) return "Qt::Rect.new";
+ else if ( type == "Size" ) return "Qt::Size.new";
+ else if ( type == "Color" ) return "Qt::Color.new";
+ else if ( type == "Point" ) return "Qt::Point.new";
+ else if ( type == "Int" ) return "0";
+ else if ( type == "UInt" ) return "0";
+ else if ( type == "Bool" ) return "false, 42";
+ else if ( type == "Double" ) return "0.0";
+ else if ( type == "DateTime" ) return "Qt::DateTime.new";
+ else if ( type == "Int64" ) return "0";
+ else if ( type == "UInt64" ) return "0";
+ else if ( type == "IntList" ) return "[]";
+ else if ( type == "Enum" ) return "0";
+ else if ( type == "Path" ) return "\"\"";
+ else if ( type == "Password" ) return "\"\"";
+ else {
+ kdError()<<"rbkconfig_compiler does not support type \""<< type <<"\""<<endl;
+ return "nil"; //For now, but an assert would be better
+ }
+}
+
+QString defaultValue( const QString &type )
+{
+ if ( type == "String" ) return "\"\""; // Use empty string, not null string!
+ else if ( type == "StringList" ) return "[]";
+ else if ( type == "Font" ) return "KDE::GlobalSettings.generalFont()";
+ else if ( type == "Rect" ) return "Qt::Rect.new()";
+ else if ( type == "Size" ) return "Qt::Size.new()";
+ else if ( type == "Color" ) return "Qt::Color.new(128, 128, 128)";
+ else if ( type == "Point" ) return "Qt::Point.new()";
+ else if ( type == "Int" ) return "0";
+ else if ( type == "UInt" ) return "0";
+ else if ( type == "Bool" ) return "false";
+ else if ( type == "Double" ) return "0.0";
+ else if ( type == "DateTime" ) return "Qt::DateTime.new()";
+ else if ( type == "Int64" ) return "0";
+ else if ( type == "UInt64" ) return "0";
+ else if ( type == "IntList" ) return "[]";
+ else if ( type == "Enum" ) return "0";
+ else if ( type == "Path" ) return "\"\""; // Use empty string, not null string!
+ else if ( type == "Password" ) return "\"\""; // Use empty string, not null string!
+ else {
+ kdWarning()<<"Error, rbkconfig_compiler doesn't support the \""<< type <<"\" type!"<<endl;
+ return "String"; //For now, but an assert would be better
+ }
+}
+
+QString itemType( const QString &type )
+{
+ QString t;
+
+ t = type;
+ t.replace( 0, 1, t.left( 1 ).upper() );
+ return t;
+}
+
+static QString itemVar(const CfgEntry *e)
+{
+ if (itemAccessors)
+ return varName( e->name() ) + "Item";
+
+ return "item" + e->name();
+
+}
+
+QString newItem( const QString &type, const QString &name, const QString &key,
+ const QString &defaultValue, const QString &param = QString::null)
+{
+ QString t = "Item" + itemType( type ) +
+ ".new( currentGroup(), " + key + ", " + varName( name ) + param;
+ if ( type == "Enum" ) {
+ t += ".toInt";
+ t += ", values" + name;
+ } else if ( type == "Path" ) {
+ t += ".toString";
+ } else if ( type == "Int64" ) {
+ t += ".toLongLong";
+ } else {
+ t += ".to" + itemType( type );
+ }
+ if ( !defaultValue.isEmpty() ) {
+ t += ", ";
+ if ( type == "String" ) t += defaultValue;
+ else t+= defaultValue;
+ }
+ t += " )";
+
+ return t;
+}
+
+QString addItem( const QString &type, const QString &name, const QString &key,
+ const QString &defaultValue, const QString &param = QString::null,
+ const QString &paramName = QString::null )
+{
+ QString t = "addItem" + itemType( type ) +
+ "( " + key + ", " + varName( name ) + param;
+ if ( type == "Enum" ) t += ", values" + name;
+ if ( !defaultValue.isEmpty() ) {
+ t += ", ";
+ if ( type == "String" ) t += defaultValue;
+ else if ( type == "Enum" ) t += enumValue(defaultValue);
+ else t+= defaultValue;
+ }
+
+ if (!paramName.isNull()) {
+ t += ", \"" + paramName + "\"";
+ }
+
+ t += " )";
+
+ return t;
+}
+
+QString paramString(const QString &s, const CfgEntry *e, int i)
+{
+ QString result = s;
+ QString needle = "$("+e->param()+")";
+ if (result.contains(needle))
+ {
+ QString tmp;
+ if (e->paramType() == "Enum")
+ {
+ tmp = e->paramValues()[i];
+ }
+ else
+ {
+ tmp = QString::number(i);
+ }
+
+ result.replace(needle, tmp);
+ }
+ return result;
+}
+
+QString paramString(const QString &group, const QStringList &parameters)
+{
+ QString paramString = group;
+ QString arguments;
+ int i = 0;
+ for( QStringList::ConstIterator it = parameters.begin();
+ it != parameters.end(); ++it)
+ {
+ if (paramString.contains("$("+*it+")"))
+ {
+ i++;
+ paramString.replace("$("+*it+")", "%s");
+ if (i > 1) {
+ arguments += ", ";
+ }
+ arguments += " @param"+*it;
+ }
+ }
+ if (arguments.isEmpty())
+ return "\""+group+"\"";
+
+ if (i == 1) {
+ return "\""+paramString+"\" % "+arguments;
+ } else {
+ return "\""+paramString+"\" % ["+arguments+"]";
+ }
+}
+
+/* int i is the value of the parameter */
+QString userTextsFunctions( CfgEntry *e, QString itemVarStr=QString::null, QString i=QString::null )
+{
+ QString txt;
+ if (itemVarStr.isNull()) itemVarStr=itemVar(e);
+ if ( !e->label().isEmpty() ) {
+ txt += " " + itemVarStr + ".setLabel( i18n(";
+ if ( !e->param().isEmpty() )
+ txt += quoteString(e->label().replace("$("+e->param()+")", i));
+ else
+ txt+= quoteString(e->label());
+ txt+= ") )\n";
+ }
+ if ( !e->whatsThis().isEmpty() ) {
+ txt += " " + itemVarStr + ".setWhatsThis( i18n(";
+ if ( !e->param().isEmpty() )
+ txt += quoteString(e->whatsThis().replace("$("+e->param()+")", i));
+ else
+ txt+= quoteString(e->whatsThis());
+ txt+=") )\n";
+ }
+ return txt;
+}
+
+int main( int argc, char **argv )
+{
+ KAboutData aboutData( "rbkconfig_compiler", I18N_NOOP("KDE .kcfg compiler"), "0.3",
+ I18N_NOOP("Ruby KConfig Compiler") , KAboutData::License_LGPL );
+ aboutData.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );
+ aboutData.addAuthor( "Waldo Bastian", 0, "bastian@kde.org" );
+ aboutData.addAuthor( "Zack Rusin", 0, "zack@kde.org" );
+ aboutData.addCredit( "Reinhold Kainhofer", "Fix for parametrized entries",
+ "reinhold@kainhofer.com", "http://reinhold.kainhofer.com" );
+ aboutData.addCredit( "Richard Dale", "Ruby port",
+ "Richard_Dale@tipitina.demon.co.uk", "" );
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KInstance app( &aboutData );
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ if ( args->count() < 2 ) {
+ kdError() << "Too few arguments." << endl;
+ return 1;
+ }
+ if ( args->count() > 2 ) {
+ kdError() << "Too many arguments." << endl;
+ return 1;
+ }
+
+ validNameRegexp = new QRegExp("[a-zA-Z_][a-zA-Z0-9_]*");
+
+ QString baseDir = QFile::decodeName(args->getOption("directory"));
+ if (!baseDir.endsWith("/"))
+ baseDir.append("/");
+
+ QString inputFilename = args->url( 0 ).path();
+ QString codegenFilename = args->url( 1 ).path();
+
+ if (!codegenFilename.endsWith(".kcfgc"))
+ {
+ kdError() << "Codegen options file must have extension .kcfgc" << endl;
+ return 1;
+ }
+ QString baseName = args->url( 1 ).fileName();
+ baseName = baseName.left(baseName.length() - 6);
+
+ KSimpleConfig codegenConfig( codegenFilename, true );
+
+ QString nameSpace = codegenConfig.readEntry("NameSpace");
+ QString className = codegenConfig.readEntry("ClassName");
+ QString inherits = codegenConfig.readEntry("Inherits");
+ QString visibility = codegenConfig.readEntry("Visibility");
+ if (!visibility.isEmpty()) visibility+=" ";
+ bool singleton = codegenConfig.readBoolEntry("Singleton", false);
+ bool customAddons = codegenConfig.readBoolEntry("CustomAdditions");
+ QString memberVariables = codegenConfig.readEntry("MemberVariables");
+ QStringList headerIncludes = codegenConfig.readListEntry("IncludeFiles");
+ QStringList mutators = codegenConfig.readListEntry("Mutators");
+ bool allMutators = false;
+ if ((mutators.count() == 1) && (mutators[0].lower() == "true"))
+ allMutators = true;
+ itemAccessors = codegenConfig.readBoolEntry( "ItemAccessors", false );
+ bool setUserTexts = codegenConfig.readBoolEntry( "SetUserTexts", false );
+
+ globalEnums = codegenConfig.readBoolEntry( "GlobalEnums", false );
+
+ QFile input( inputFilename );
+
+ QDomDocument doc;
+ QString errorMsg;
+ int errorRow;
+ int errorCol;
+ if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
+ kdError() << "Unable to load document." << endl;
+ kdError() << "Parse error in " << args->url( 0 ).fileName() << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << endl;
+ return 1;
+ }
+
+ QDomElement cfgElement = doc.documentElement();
+
+ if ( cfgElement.isNull() ) {
+ kdError() << "No document in kcfg file" << endl;
+ return 1;
+ }
+
+ QString cfgFileName;
+ bool cfgFileNameArg = false;
+ QStringList parameters;
+ QStringList includes;
+
+ QPtrList<CfgEntry> entries;
+ entries.setAutoDelete( true );
+
+ QDomNode n;
+ for ( n = cfgElement.firstChild(); !n.isNull(); n = n.nextSibling() ) {
+ QDomElement e = n.toElement();
+
+ QString tag = e.tagName();
+
+ if ( tag == "include" ) {
+ QString includeFile = e.text();
+ if (!includeFile.isEmpty())
+ includes.append(includeFile);
+
+ } else if ( tag == "kcfgfile" ) {
+ cfgFileName = e.attribute( "name" );
+ cfgFileNameArg = e.attribute( "arg" ).lower() == "true";
+ QDomNode n2;
+ for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
+ QDomElement e2 = n2.toElement();
+ if ( e2.tagName() == "parameter" ) {
+ parameters.append( e2.attribute( "name" ) );
+ }
+ }
+
+ } else if ( tag == "group" ) {
+ QString group = e.attribute( "name" );
+ if ( group.isEmpty() ) {
+ kdError() << "Group without name" << endl;
+ return 1;
+ }
+ QDomNode n2;
+ for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) {
+ QDomElement e2 = n2.toElement();
+ if ( e2.tagName() != "entry" ) continue;
+ CfgEntry *entry = parseEntry( group, e2 );
+ if ( entry ) entries.append( entry );
+ else {
+ kdError() << "Can't parse entry." << endl;
+ return 1;
+ }
+ }
+ }
+ }
+
+ if ( inherits.isEmpty() ) inherits = "KDE::ConfigSkeleton";
+
+ if ( className.isEmpty() ) {
+ kdError() << "Class name missing" << endl;
+ return 1;
+ }
+
+ if ( singleton && !parameters.isEmpty() ) {
+ kdError() << "Singleton class can not have parameters" << endl;
+ return 1;
+ }
+
+ if ( singleton && cfgFileNameArg)
+ {
+ kdError() << "Singleton class can not use filename as argument." << endl;
+ return 1;
+ }
+
+ if ( !cfgFileName.isEmpty() && cfgFileNameArg)
+ {
+ kdError() << "Having both a fixed filename and a filename as argument is not possible." << endl;
+ return 1;
+ }
+
+ if ( entries.isEmpty() ) {
+ kdWarning() << "No entries." << endl;
+ }
+
+#if 0
+ CfgEntry *cfg;
+ for( cfg = entries.first(); cfg; cfg = entries.next() ) {
+ cfg->dump();
+ }
+#endif
+
+ QString implementationFileName = baseName + ".rb";
+
+ QFile implementation( baseDir + implementationFileName );
+ if ( !implementation.open( IO_WriteOnly ) ) {
+ kdError() << "Can't open '" << implementationFileName << "for writing." << endl;
+ return 1;
+ }
+
+ QTextStream rb( &implementation );
+
+ rb << "# This file is generated by rbkconfig_compiler from " << args->url(0).fileName() << "." << endl;
+ rb << "# All changes you do to this file will be lost." << endl;
+ rb << endl << "require 'Korundum'" << endl;
+
+ if (singleton) {
+ rb << "require 'singleton'" << endl;
+ }
+
+ rb << endl;
+
+// rb << "#ifndef " << ( !nameSpace.isEmpty() ? nameSpace.upper() + "_" : "" )
+// << className.upper() << "_H" << endl;
+// rb << "#define " << ( !nameSpace.isEmpty() ? nameSpace.upper() + "_" : "" )
+// << className.upper() << "_H" << endl << endl;
+
+ // Includes
+// QStringList::ConstIterator it;
+// for( it = headerIncludes.begin(); it != headerIncludes.end(); ++it ) {
+// rb << "#include <" << *it << ">" << endl;
+// }
+
+ if ( headerIncludes.count() > 0 ) rb << endl;
+
+// rb << "#include <kconfigskeleton.h>" << endl << endl;
+
+ if ( !nameSpace.isEmpty() )
+ rb << "module " << nameSpace << endl << endl;
+
+ // Class declaration header
+ rb << "class " << className << " < " << inherits << endl;
+
+ if (singleton) {
+ rb << " include Singleton" << endl << endl;
+ }
+
+ // enums
+ CfgEntry *e;
+ for( e = entries.first(); e; e = entries.next() ) {
+ QValueList<CfgEntry::Choice> choices = e->choices();
+ if ( !choices.isEmpty() ) {
+ QStringList values;
+ QValueList<CfgEntry::Choice>::ConstIterator itChoice;
+ for( itChoice = choices.begin(); itChoice != choices.end(); ++itChoice ) {
+ if (globalEnums) {
+ values.append( enumValue((*itChoice).name) );
+ } else {
+ values.append( enumName(e->name()) + "_" + (*itChoice).name );
+ }
+ }
+ if (!globalEnums) {
+ values.append( enumName(e->name()) + "_COUNT" );
+ }
+ int count = 0;
+ for ( QStringList::Iterator it = values.begin(); it != values.end(); ++it, count++ ) {
+ rb << " " << *it << " = " << count << endl;
+ }
+ rb << endl;
+ }
+
+ QStringList values = e->paramValues();
+ if ( !values.isEmpty() ) {
+ int count = 0;
+ for ( QStringList::Iterator it = values.begin(); it != values.end(); ++it, count++ ) {
+ if (globalEnums) {
+ rb << " " << enumValue(*it) << " = " << count << endl;
+ } else {
+ rb << " " << enumName(e->param()) << "_" << *it << " = " << count << endl;
+ }
+ }
+ if (!globalEnums) {
+ rb << " " << enumName(e->param()) << "_COUNT = " << count << endl;
+ }
+ rb << endl;
+
+ rb << " def " << enumName(e->param()) << "ToString(i)" << endl;
+ rb << " [";
+ count = 0;
+ for ( QStringList::Iterator it = values.begin(); it != values.end(); ++it, count++ ) {
+ if (count > 0) {
+ rb << ", ";
+ }
+
+ rb << "\"" << *it << "\"";
+ }
+
+ rb << "].at(i)" << endl;
+ rb << " end" << endl;
+ }
+ }
+
+ rb << endl;
+
+ for( e = entries.first(); e; e = entries.next() ) {
+ QString n = e->name();
+ QString t = e->type();
+
+ // Manipulator
+ if (allMutators || mutators.contains(n))
+ {
+ rb << " #" << endl;
+ rb << " # Set " << e->label() << endl;
+ rb << " #" << endl;
+ rb << " def " << setFunction(n) << "( ";
+ if (!e->param().isEmpty())
+ rb << " i, ";
+ rb << " v )" << endl;
+ rb << " item = findItem( \"";
+ if (!e->param().isEmpty()) {
+ rb << e->paramName().replace("$("+e->param()+")", "%s") << "\" % ";
+ if ( e->paramType() == "Enum" ) {
+ rb << " ";
+ if (globalEnums)
+ rb << enumName(e->param()) << "ToString(i)";
+ else
+ rb << enumName(e->param()) << "ToString(i)";
+ } else {
+ rb << "i";
+ }
+ } else {
+ rb << n << "\"";
+ }
+ rb << " )" << endl;
+ rb << " if !item.immutable? " << endl;
+ rb << " item.property = " << varName(n);
+ if (!e->param().isEmpty())
+ rb << "[i]";
+ rb << " = Qt::Variant.new( v )" << endl;
+ rb << " end" << endl;
+ rb << " end" << endl << endl;
+ }
+
+ // Accessor
+ rb << " #" << endl;
+ rb << " # Get " << e->label() << endl;
+ rb << " #" << endl;
+ rb << " def " << getFunction(n) << "(";
+ if (!e->param().isEmpty())
+ rb << " " <<" i ";
+ rb << ")" << endl;
+ rb << " " << varName(n);
+ if (!e->param().isEmpty()) rb << "[i]";
+ rb << " = findItem( \"";
+ if (!e->param().isEmpty()) {
+ rb << e->paramName().replace("$("+e->param()+")", "%s") << "\" % ";
+ if ( e->paramType() == "Enum" ) {
+ rb << " ";
+ if (globalEnums)
+ rb << enumName(e->param()) << "ToString(i)";
+ else
+ rb << enumName(e->param()) << "ToString(i)";
+ } else {
+ rb << "i";
+ }
+ } else {
+ rb << n << "\"";
+ }
+ rb << " ).property" << endl;
+ rb << " return " << varName(n);
+ if (!e->param().isEmpty()) rb << "[i]";
+ if ( e->type() == "Enum" ) {
+ rb << ".toInt" << endl;
+ } else if ( e->type() == "Int64" ) {
+ rb << ".toLongLong" << endl;
+ } else if ( e->type() == "Path" ) {
+ rb << ".toString" << endl;
+ } else {
+ rb << ".to" << itemType( e->type() ) << endl;
+ }
+ rb << " end" << endl;
+
+ // Item accessor
+ if ( itemAccessors ) {
+ rb << endl;
+ rb << " #" << endl;
+ rb << " # Get Item object corresponding to " << n << "()"
+ << endl;
+ rb << " #" << endl;
+ rb << " def "
+ << getFunction( n ) << "Item(";
+ if (!e->param().isEmpty()) {
+ rb << " " << " i ";
+ }
+ rb << ")" << endl;
+ rb << " return " << itemVar(e);
+ if (!e->param().isEmpty()) rb << "[i]";
+ rb << endl << " end" << endl;
+ }
+
+ rb << endl;
+ }
+
+
+ if (customAddons)
+ {
+ rb << " # Include custom additions" << endl;
+ }
+
+
+ // Constructor
+ rb << " def initialize( ";
+ if (cfgFileNameArg)
+ rb << " config" << (parameters.isEmpty() ? " " : ", ");
+ for (QStringList::ConstIterator it = parameters.begin();
+ it != parameters.end(); ++it)
+ {
+ if (it != parameters.begin())
+ rb << ",";
+ rb << " " << *it;
+ }
+ rb << " )" << endl;
+
+ rb << " super(";
+ if ( !cfgFileName.isEmpty() ) rb << " \"" << cfgFileName << "\" ";
+ if ( cfgFileNameArg ) rb << " config ";
+// if ( !cfgFileName.isEmpty() ) rb << ") ";
+ rb << ")" << endl;
+
+ // Store parameters
+ for (QStringList::ConstIterator it = parameters.begin();
+ it != parameters.end(); ++it)
+ {
+ rb << " @param" << *it << " = Qt::Variant.new( " << *it << " )" << endl;
+ }
+
+ QString group;
+ for( e = entries.first(); e; e = entries.next() ) {
+ if ( e->group() != group ) {
+ group = e->group();
+ rb << endl;
+ rb << " # " << group << endl;
+ }
+ if (e->param().isEmpty()) {
+ rb << " " << varName(e->name()) << " = Qt::Variant.new( " << rbType(e->type()) << " )";
+ } else {
+ rb << " " << varName(e->name()) << " = [ ";
+ for (int i = 0; i < e->paramMax()+1; i++) {
+ if (i > 0) {
+ rb << ", ";
+ }
+ rb << "Qt::Variant.new( " << rbType(e->type()) << " )";
+ }
+ rb << " ]";
+ }
+ rb << endl;
+ }
+
+ rb << endl;
+
+
+ group = QString::null;
+ for( e = entries.first(); e; e = entries.next() ) {
+ if ( e->group() != group ) {
+ if ( !group.isEmpty() ) rb << endl;
+ group = e->group();
+ rb << " setCurrentGroup( " << paramString(group, parameters) << " )" << endl << endl;
+ }
+
+ QString key = paramString(e->key(), parameters);
+ if ( !e->code().isEmpty())
+ {
+ rb << e->code() << endl;
+ }
+ if ( e->type() == "Enum" ) {
+ rb << " values"
+ << e->name() << " = []" << endl;
+ QValueList<CfgEntry::Choice> choices = e->choices();
+ QValueList<CfgEntry::Choice>::ConstIterator it;
+ for( it = choices.begin(); it != choices.end(); ++it ) {
+ rb << " choice = ItemEnum::Choice.new" << endl;
+ rb << " choice.name = \"" << enumValue((*it).name) << "\" " << endl;
+ if ( setUserTexts ) {
+ if ( !(*it).label.isEmpty() )
+ rb << " choice.label = i18n(" << quoteString((*it).label) << ")" << endl;
+ if ( !(*it).whatsThis.isEmpty() )
+ rb << " choice.whatsThis = i18n(" << quoteString((*it).whatsThis) << ")" << endl;
+ }
+ rb << " values" << e->name() << " << choice" << endl;
+ }
+ }
+
+ if (e->param().isEmpty())
+ {
+ // Normal case
+ rb << " " << itemVar(e) << " = "
+ << newItem( e->type(), e->name(), key, e->defaultValue() ) << endl;
+
+ rb << " " << itemVar(e) << ".property = " << varName(e->name()) << endl;
+
+ if ( !e->minValue().isEmpty() )
+ rb << " " << itemVar(e) << ".setMinValue(" << e->minValue() << ")" << endl;
+ if ( !e->maxValue().isEmpty() )
+ rb << " " << itemVar(e) << ".setMaxValue(" << e->maxValue() << ")" << endl;
+
+ if ( setUserTexts )
+ rb << userTextsFunctions( e );
+
+ rb << " addItem( " << itemVar(e);
+ QString quotedName = e->name();
+ addQuotes( quotedName );
+ if ( quotedName != key ) rb << ", \"" << e->name() << "\"";
+ rb << " )" << endl;
+ }
+ else
+ {
+ // Indexed
+ rb << " " << itemVar(e) << " = Array.new(" << e->paramMax()+1 << ")" << endl;
+ for(int i = 0; i <= e->paramMax(); i++)
+ {
+ QString defaultStr;
+ QString itemVarStr(itemVar(e)+QString("[%1]").arg(i));
+
+ if ( !e->paramDefaultValue(i).isEmpty() )
+ defaultStr = e->paramDefaultValue(i);
+ else if ( !e->defaultValue().isEmpty() )
+ defaultStr = paramString(e->defaultValue(), e, i);
+ else
+ defaultStr = defaultValue( e->type() );
+
+ rb << " " << itemVarStr << " = "
+ << newItem( e->type(), e->name(), paramString(key, e, i), defaultStr, QString("[%1]").arg(i) )
+ << endl;
+
+ rb << " " << itemVarStr << ".property = " << varName(e->name())+QString("[%1]").arg(i) << endl;
+
+ if ( setUserTexts )
+ rb << userTextsFunctions( e, itemVarStr, e->paramName() );
+
+ // Make mutators for enum parameters work by adding them with $(..) replaced by the
+ // param name. The check for isImmutable in the set* functions doesn't have the param
+ // name available, just the corresponding enum value (int), so we need to store the
+ // param names in a separate static list!.
+ rb << " addItem( " << itemVarStr << ", \"";
+ if ( e->paramType()=="Enum" )
+ rb << e->paramName().replace( "$("+e->param()+")", "%1").arg(e->paramValues()[i] );
+ else
+ rb << e->paramName().replace( "$("+e->param()+")", "%1").arg(i);
+ rb << "\" )" << endl;
+
+ }
+ }
+ }
+
+ rb << " end" << endl << endl;
+
+ rb << "end" << endl << endl;
+
+ if ( !nameSpace.isEmpty() ) rb << "end" << endl << endl;
+
+ implementation.close();
+}
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/Makefile.am b/korundum/rubylib/rbkconfig_compiler/tests/Makefile.am
new file mode 100644
index 00000000..ce61f658
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/Makefile.am
@@ -0,0 +1,40 @@
+check_PROGRAMS = test1 test2 test3 test4 test5
+
+CLEANFILES = test1.rb \
+ test2.rb \
+ test3.rb \
+ test4.rb \
+ test5.rb \
+ md5sums
+
+all: $(SOURCES)
+
+# Splitting this with backslashses produces broken Makefiles
+SOURCES = test1main.rb test1.rb test2main.rb test2.rb test3main.rb test3.rb test4main.rb test4.rb test5main.rb test5.rb
+
+# avoid running the below command in parallel
+test1.rb: $(srcdir)/test1.kcfg ../rbkconfig_compiler $(srcdir)/test1.kcfgc
+ ../rbkconfig_compiler $(srcdir)/test1.kcfg $(srcdir)/test1.kcfgc
+
+# avoid running the below command in parallel
+test2.rb: $(srcdir)/test2.kcfg ../rbkconfig_compiler $(srcdir)/test2.kcfgc
+ ../rbkconfig_compiler $(srcdir)/test2.kcfg $(srcdir)/test2.kcfgc
+
+# avoid running the below command in parallel
+test3.rb: $(srcdir)/test3.kcfg ../rbkconfig_compiler $(srcdir)/test3.kcfgc
+ ../rbkconfig_compiler $(srcdir)/test3.kcfg $(srcdir)/test3.kcfgc
+
+# avoid running the below command in parallel
+test4.rb: $(srcdir)/test4.kcfg ../rbkconfig_compiler $(srcdir)/test4.kcfgc
+ ../rbkconfig_compiler $(srcdir)/test4.kcfg $(srcdir)/test4.kcfgc
+
+# avoid running the below command in parallel
+test5.rb: $(srcdir)/test5.kcfg ../rbkconfig_compiler $(srcdir)/test5.kcfgc
+ ../rbkconfig_compiler $(srcdir)/test5.kcfg $(srcdir)/test5.kcfgc
+
+md5sums:
+ $(MD5SUM) $(srcdir)/test*.ref | sed -e "s,$(srcdir)/,,; s,\.ref$$,," > md5sums
+
+md5check: test1.rb test2.rb test3.rb test4.rb test5.rb md5sums
+ $(MD5SUM) --check md5sums
+
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/myprefs.rb b/korundum/rubylib/rbkconfig_compiler/tests/myprefs.rb
new file mode 100644
index 00000000..a4f1f082
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/myprefs.rb
@@ -0,0 +1,5 @@
+class MyPrefs < KDE::ConfigSkeleton
+ def initialize( a )
+ super( a )
+ end
+end
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfg b/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfg
new file mode 100644
index 00000000..0c0c8216
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfg
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <include>qdir.h</include>
+ <kcfgfile name="examplerc">
+ <parameter name="transport" />
+ <parameter name="folder" />
+ </kcfgfile>
+ <group name="General-$(folder)">
+ <entry name="OneOption" type="Bool">
+ <label>One option</label>
+ <default>true</default>
+ </entry>
+ <entry name="AnotherOption" type="Int" key="Another Option">
+ <label>Another option</label>
+ <default>5</default>
+ </entry>
+ <entry name="ListOption" type="Enum">
+ <label>This is some funky option</label>
+ <whatsthis>And this is a longer description of this option. Just wondering, how will the translations of those be handled?</whatsthis>
+ <choices>
+ <choice name="One"/>
+ <choice name="Two"/>
+ <choice name="Three"/>
+ </choices>
+ <default>One</default>
+ </entry>
+ </group>
+ <group name="MyOptions">
+ <entry name="MyString" type="String">
+ <label>This is a string</label>
+ <default>Default String</default>
+ </entry>
+ <entry name="MyPath" type="Path">
+ <label>This is a path</label>
+ <default code="true">Qt::Dir.homeDirPath()+".hidden_file"</default>
+ </entry>
+ <entry name="AnotherOption2" type="Int" key="Another Option">
+ <label>Another option</label>
+ <default>10</default>
+ </entry>
+ <entry name="MyStringList" type="StringList">
+ <default>up,down</default>
+ </entry>
+ <entry name="MyStringListHidden" hidden="true" type="StringList">
+ <default>up,down</default>
+ </entry>
+ <entry name="MyNumber" type="Int" key="List-$(transport)-$(folder)">
+ <label>List Number</label>
+ <default>1</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfgc b/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfgc
new file mode 100644
index 00000000..6e0edd36
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfgc
@@ -0,0 +1,18 @@
+# Code generation options for kconfig_compiler
+ClassName=Test1
+#
+# Singleton=false
+#
+# Inherits=KConfigSkeleton
+#
+# IncludeFiles=libkdepim/kpimprefs.h
+#
+# MemberVariables=public
+#
+### The following line includes the file exampleprefs_base_addon.h
+### It can be used to add extra functions and variables to the
+### class.
+# CustomAdditions=true
+#
+### Provide setFooBar(int) style functions
+Mutators=true
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test1main.rb b/korundum/rubylib/rbkconfig_compiler/tests/test1main.rb
new file mode 100644
index 00000000..88a151a6
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test1main.rb
@@ -0,0 +1,4 @@
+require 'Korundum'
+require 'test1.rb'
+
+t = Test1.new(nil, nil)
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfg b/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfg
new file mode 100644
index 00000000..3b19e270
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfg
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="korganizerrc"/>
+
+ <group name="General">
+ <entry type="Bool" key="Auto Save">
+ <label>Enable automatic saving of calendar</label>
+ <whatsthis>WhatsThis text for AutoSave option</whatsthis>
+ <default>false</default>
+ </entry>
+ <entry type="Int" key="Auto Save Interval">
+ <default>10</default>
+ </entry>
+ <entry type="Bool" key="Confirm Deletes" name="Confirm">
+ <label>Confirm deletes</label>
+ <default>true</default>
+ </entry>
+ <entry type="String" key="Archive File">
+ </entry>
+ <entry type="Enum" key="Destination" name="Destination">
+ <label>New Events/Todos Should</label>
+ <choices>
+ <choice name="standardDestination">
+ </choice>
+ <choice name="askDestination">
+ </choice>
+ <choice name="argl1">
+ <label>Argl1 Label</label>
+ </choice>
+ <choice name="argl2">
+ <whatsthis>Argl2 Whatsthis</whatsthis>
+ </choice>
+ <choice name="argl3">
+ <label>Argl3 Label</label>
+ <whatsthis>Argl3 Whatsthis</whatsthis>
+ </choice>
+ </choices>
+ <default>standardDestination</default>
+ </entry>
+ </group>
+
+ <group name="Views">
+ <entry type="Int" key="Hour Size">
+ <default>10</default>
+ </entry>
+ <entry type="Bool" name="SelectionStartsEditor">
+ <label>Time range selection in agenda view starts event editor</label>
+ <default>false</default>
+ </entry>
+ </group>
+
+ <group name="KOrganizer Plugins">
+ <entry type="StringList" name="SelectedPlugins">
+ <default>holidays,webexport</default>
+ </entry>
+ </group>
+
+ <group name="Colors">
+ <entry type="Color" key="Highlight Color">
+ <label>Highlight color</label>
+ <default>100, 100, 255</default>
+ </entry>
+ <entry type="Color" key="Agenda Background Color" name="AgendaBgColor">
+ <label>Agenda view background color</label>
+ <default>255, 255, 255</default>
+ </entry>
+ </group>
+
+ <group name="Fonts">
+ <entry type="Font" key="TimeBar Font">
+ <label>Time bar</label>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfgc b/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfgc
new file mode 100644
index 00000000..56620d2f
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=test2.kcfg
+ClassName=Test2
+Singleton=false
+Mutators=true
+Inherits=MyPrefs
+IncludeFiles=myprefs.h
+MemberVariables=public
+GlobalEnums=true
+ItemAccessors=true
+SetUserTexts=true
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test2main.rb b/korundum/rubylib/rbkconfig_compiler/tests/test2main.rb
new file mode 100644
index 00000000..85d18f07
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test2main.rb
@@ -0,0 +1,5 @@
+require 'Korundum'
+require 'myprefs.rb'
+require 'test2.rb'
+
+t = Test2.new()
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfg b/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfg
new file mode 100644
index 00000000..77916da4
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="test3rc"/>
+
+ <group name="General">
+ <entry type="Bool" key="Auto Save">
+ <label>Enable automatic saving of calendar</label>
+ <whatsthis>WhatsThis text for AutoSave option</whatsthis>
+ <default>false</default>
+ </entry>
+ </group>
+
+ <group name="Blah">
+ <entry type="Int" name="Blubb">
+ <default>10</default>
+ </entry>
+ <entry type="String" name="BlahBlah">
+ <default>a string</default>
+ </entry>
+ <entry type="Password" name="MyPassword"/>
+ </group>
+
+</kcfg>
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfgc b/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfgc
new file mode 100644
index 00000000..ca2c2205
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfgc
@@ -0,0 +1,12 @@
+# Code generation options for kconfig_compiler
+File=test3.kcfg
+NameSpace=TestNameSpace
+ClassName=Test3
+#Singleton=false
+Mutators=true
+#Inherits=MyPrefs
+#IncludeFiles=myprefs.h
+#MemberVariables=public
+GlobalEnums=true
+ItemAccessors=true
+#SetUserTexts=true
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test3main.rb b/korundum/rubylib/rbkconfig_compiler/tests/test3main.rb
new file mode 100644
index 00000000..8c19b442
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test3main.rb
@@ -0,0 +1,4 @@
+require 'Korundum'
+require 'test3.rb'
+
+t = TestNameSpace::Test3.new()
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfg b/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfg
new file mode 100644
index 00000000..1428bc0d
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfg
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="test4rc"/>
+
+ <group name="Foo">
+ <entry name="Color$(Number)" type="Color" key="color #$(Number)">
+ <parameter name="Number" type="Int" max="3"/>
+ <label>Block colors.</label>
+ <code>defaultColor = [ Qt::red, Qt::blue, Qt::green, Qt::black ]</code>
+ <default code="true">defaultColor[$(Number)]</default>
+ </entry>
+ <entry name="MouseAction$(Button)" type="Enum" key="$(Button)_mouse_action">
+ <parameter name="Button" type="Enum">
+ <values>
+ <value>right</value>
+ <value>mid</value>
+ <value>left</value>
+ </values>
+ </parameter>
+ <label>Mouse actions.</label>
+ <choices>
+ <choice name="Encrypt"/>
+ <choice name="Decrypt"/>
+ <choice name="CrashNBurn"/>
+ <choice name="PumpNDump"/>
+ </choices>
+ <default param="right">Decrypt</default>
+ <default param="mid">Encrypt</default>
+ <default param="left">PumpNDump</default>
+ </entry>
+ <entry name="FooBar" key="foo bar" type="String"/>
+ <entry name="Age" type="Int">
+ <default>35</default>
+ <min>8</min>
+ <max>88</max>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfgc b/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfgc
new file mode 100644
index 00000000..754706df
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=test4.kcfg
+ClassName=Test4
+Singleton=true
+Mutators=true
+#Inherits=MyPrefs
+#IncludeFiles=myprefs.h
+#MemberVariables=public
+GlobalEnums=false
+ItemAccessors=false
+#SetUserTexts=true
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test4main.rb b/korundum/rubylib/rbkconfig_compiler/tests/test4main.rb
new file mode 100644
index 00000000..c75f0995
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test4main.rb
@@ -0,0 +1,4 @@
+require 'Korundum'
+require 'test4.rb'
+
+t = Test4.instance()
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfg b/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfg
new file mode 100644
index 00000000..1428bc0d
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfg
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="test4rc"/>
+
+ <group name="Foo">
+ <entry name="Color$(Number)" type="Color" key="color #$(Number)">
+ <parameter name="Number" type="Int" max="3"/>
+ <label>Block colors.</label>
+ <code>defaultColor = [ Qt::red, Qt::blue, Qt::green, Qt::black ]</code>
+ <default code="true">defaultColor[$(Number)]</default>
+ </entry>
+ <entry name="MouseAction$(Button)" type="Enum" key="$(Button)_mouse_action">
+ <parameter name="Button" type="Enum">
+ <values>
+ <value>right</value>
+ <value>mid</value>
+ <value>left</value>
+ </values>
+ </parameter>
+ <label>Mouse actions.</label>
+ <choices>
+ <choice name="Encrypt"/>
+ <choice name="Decrypt"/>
+ <choice name="CrashNBurn"/>
+ <choice name="PumpNDump"/>
+ </choices>
+ <default param="right">Decrypt</default>
+ <default param="mid">Encrypt</default>
+ <default param="left">PumpNDump</default>
+ </entry>
+ <entry name="FooBar" key="foo bar" type="String"/>
+ <entry name="Age" type="Int">
+ <default>35</default>
+ <min>8</min>
+ <max>88</max>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfgc b/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfgc
new file mode 100644
index 00000000..663005e5
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=test5.kcfg
+ClassName=Test5
+Singleton=true
+Mutators=true
+#Inherits=MyPrefs
+#IncludeFiles=myprefs.h
+#MemberVariables=public
+GlobalEnums=true
+ItemAccessors=false
+#SetUserTexts=true
diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test5main.rb b/korundum/rubylib/rbkconfig_compiler/tests/test5main.rb
new file mode 100644
index 00000000..cd0fbeb7
--- /dev/null
+++ b/korundum/rubylib/rbkconfig_compiler/tests/test5main.rb
@@ -0,0 +1,4 @@
+require 'Korundum'
+require 'test5.rb'
+
+t = Test5.instance()
diff --git a/korundum/rubylib/templates/annotated/basicapp.rb b/korundum/rubylib/templates/annotated/basicapp.rb
new file mode 100644
index 00000000..41f61bce
--- /dev/null
+++ b/korundum/rubylib/templates/annotated/basicapp.rb
@@ -0,0 +1,106 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+require 'Korundum'
+
+=begin
+Most Korundum applications will need a main window - the is the top
+level widget (the parent for all other widgets). KDE::MainWindow has
+more functionality than shown here (see more complex templates).
+It has the ability to create the other major parts of the user
+interface - the main view, menus, toolbars, etc.
+
+Usually you provide a subclass of KDE::MainWindow, construct menus
+and toolbars in the subclass' initialize method, and provide
+slots for menu/toolbar actions in separate methods.
+=end
+
+class MainWin < KDE::MainWindow
+ def initialize(*args)
+ super
+ end
+
+end
+#-------------------- main ------------------------------------------------
+
+# set up some basic information about the program in
+# a KDE::AboutData object - this affects the application's
+# title bar caption and makes it easy to set up a
+# Help | About dialog box for your app
+description = "A basic application template"
+version = "1.0"
+aboutData = KDE::AboutData.new("", "",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+# you can add the names of the app's authors here
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+# Pass the command line arguments and aboutData to
+# KDE::CmdLineArgs - this is where KDE will look for
+# this information. The KDE::Application constructor
+# used below *requires* the args are processed
+# *before* KDE::Application is instantiated. There
+# is an alternate constructor that takes ARGV
+# as an argument (see minimal.rb)
+
+# Note that instead of argc/argv, this constructor
+# only takes a single argument - ARGV - which
+# is a Ruby list
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+# Set up the command line options (switches) you
+# want your app to be able to process (you could
+# use Ruby's getopt module instead, but it works
+# a little differently)
+
+# Note that the argument for this method is a list
+# of three element lists
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+# instantiate KDE::Application - no other QObject
+# or QWidget based classes can be instantiated
+# until there is a KApplication instance
+app = KDE::Application.new()
+
+# instantiate the subclass of KMainWindow
+mainWindow = MainWin.new(nil, "main window")
+
+# create the display
+mainWindow.show
+
+# run KDE::Application's event loop until the
+# program exits
+app.exec
+
diff --git a/korundum/rubylib/templates/annotated/menuapp1.rb b/korundum/rubylib/templates/annotated/menuapp1.rb
new file mode 100644
index 00000000..0553aa14
--- /dev/null
+++ b/korundum/rubylib/templates/annotated/menuapp1.rb
@@ -0,0 +1,278 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+
+=begin
+This template constructs an application with menus, toolbar and statusbar,
+HOWEVER it is not recommended this template actually be used. It presents
+the "KDE 1.0" method for constructing menus and toolbars - later versions
+of KDE have introduced better(easier and more powerful) methods for
+doing this job - see other menuapp*.rb templates for these methods
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+
+require 'Korundum'
+
+class MainWin < KDE::MainWindow
+ TOOLBAR_NEW = 1
+ TOOLBAR_OPEN = 2
+ TOOLBAR_SAVE = 3
+ TOOLBAR_CUT = 4
+ TOOLBAR_COPY = 5
+ TOOLBAR_PASTE = 6
+
+ STATUSBAR_LEFT = 1
+ STATUSBAR_MIDDLE = 2
+ STATUSBAR_RIGHT = 3
+
+ slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()',
+ 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()',
+ 'slotSpecial()'
+
+ def initialize(*args)
+ super
+
+ initMenus()
+ initToolBar()
+ initStatusBar()
+ end
+
+ def initMenus()
+ # Create a QPopupMenu - all menus are "popup" menus
+
+ fileMenu = Qt::PopupMenu.new(self)
+
+ # This is the "simple" KDE-1.0 way. It is not suggested that this
+ # template actually be used in an application, but it's
+ # provided to show the underlying mechanics of menu construction
+ # that KDE makes much easier with other methods (see other
+ # menuapp*.rb templates for usable examples)
+
+ # All menu item strings are wrapped with i18n - this allows
+ # internationalization
+
+ # Predefined accelerators are in KDE::StdAccel - these are
+ # the standard accelerators. For custom accelerators, use
+ # KDE::Accel. All KDE::StdAccel methods are static, so there is no
+ # need to instantiate KDE::StdAccel
+
+ # "File" menu items
+ fileMenu.insertItem(i18n("New"), self, SLOT('slotNew()'), Qt::KeySequence.new(KDE::StdAccel.openNew().keyCodeQt()))
+ fileMenu.insertItem(i18n("Open"), self, SLOT('slotOpen()'), Qt::KeySequence.new(KDE::StdAccel.open().keyCodeQt()))
+ fileMenu.insertSeparator()
+ fileMenu.insertItem(i18n("Save"), self, SLOT('slotSave()'), Qt::KeySequence.new(KDE::StdAccel.save().keyCodeQt()))
+
+ # KStdAccel doesn't have a standard accelerator for 'Save As',
+ # so we omit it - insertItem uses the default value
+ fileMenu.insertItem(i18n("SaveAs"), self, SLOT('slotSaveAs()'))
+
+ # This inserts a line between groups of items in a menu
+
+ fileMenu.insertSeparator()
+ fileMenu.insertItem(i18n("Print"), self, SLOT('slotPrint()'), Qt::KeySequence.new(KDE::StdAccel.print().keyCodeQt()))
+ fileMenu.insertSeparator()
+ fileMenu.insertItem(i18n("&Quit"), self, SLOT('slotQuit()'), Qt::KeySequence.new(KDE::StdAccel.quit().keyCodeQt()))
+
+ # Put fileMenu (as the File menu) into the menu bar
+ # 'menuBar' is a predefined object owned by KDE::MainWindow
+ menuBar().insertItem(i18n("&File"), fileMenu)
+
+ editMenu = Qt::PopupMenu.new(self)
+
+ # "Edit" menu items
+ editMenu.insertItem(i18n("Undo"), self, SLOT('slotUndo()'), Qt::KeySequence.new(KDE::StdAccel.undo().keyCodeQt()))
+ editMenu.insertItem(i18n("Redo"), self, SLOT('slotRedo()'), Qt::KeySequence.new(KDE::StdAccel.redo().keyCodeQt()))
+ editMenu.insertSeparator()
+ editMenu.insertItem(i18n("Cut"), self, SLOT('slotCut()'), Qt::KeySequence.new(KDE::StdAccel.cut().keyCodeQt()))
+ editMenu.insertItem(i18n("Copy"), self, SLOT('slotCopy()'), Qt::KeySequence.new(KDE::StdAccel.copy().keyCodeQt()))
+ editMenu.insertItem(i18n("Paste"), self, SLOT('slotPaste()'), Qt::KeySequence.new(KDE::StdAccel.paste().keyCodeQt()))
+ editMenu.insertSeparator()
+ editMenu.insertItem(i18n("Find"), self, SLOT('slotFind()'), Qt::KeySequence.new(KDE::StdAccel.find().keyCodeQt()))
+ editMenu.insertItem(i18n("Find Next"), self, SLOT('slotFindNext()'), Qt::KeySequence.new(KDE::StdAccel.findNext().keyCodeQt()))
+ editMenu.insertItem(i18n("Replace"), self, SLOT('slotReplace()'), Qt::KeySequence.new(KDE::StdAccel.replace().keyCodeQt()))
+
+ # Put editMenu (as the Edit menu) into the menu bar
+
+ menuBar().insertItem(i18n("&Edit"), editMenu)
+
+ # Let KDE generate a nifty help menu
+
+ # The KDE::AboutData/KDE::CmdLineArgs data from the main part of the program
+ # will be used to generate the About dialog
+ helpMenu = helpMenu("")
+ menuBar().insertItem(i18n("&Help"), helpMenu)
+ end
+
+ def initToolBar()
+ # KDE::IconLoader will make it easy to locate the standard KDE icons for
+ # toolbar buttons. For custom icons, a complete path to the icon
+ # (without the loadIcon call) is needed
+ icons = KDE::IconLoader.new()
+
+ # KDE::MainWindow owns at least one KDE::ToolBar instance, which is returned
+ # by 'toolBar()'. To obtain additional toolbars, add an argument
+ # to the call -- toolBar(1) will return another toolbar you can
+ # add buttons to.
+
+ # Add buttons to the toolbar. The icon name, id value (eg TOOLBAR_NEW),
+ # signal to connect (eg clicked) and the slot to connect to all need
+ # to be specified,as does the tooltip (the last string argument). There
+ # are easier ways to do this - see other menuapp templates for easier
+ # methods using KDE::Action/KDE::StdAction
+
+ toolBar().insertButton(icons.loadIcon("filenew", KDE::Icon::Toolbar), TOOLBAR_NEW, SIGNAL("clicked(int)"),
+ self, SLOT('slotNew()'), true, "New")
+ toolBar().insertButton(icons.loadIcon("fileopen", KDE::Icon::Toolbar), TOOLBAR_OPEN, SIGNAL("clicked(int)"),
+ self, SLOT('slotOpen()'), true, "Open")
+ toolBar().insertButton(icons.loadIcon("filesave", KDE::Icon::Toolbar), TOOLBAR_SAVE, SIGNAL("clicked(int)"),
+ self, SLOT('slotSave()'), true, "Save")
+ toolBar().insertButton(icons.loadIcon("editcut", KDE::Icon::Toolbar), TOOLBAR_CUT, SIGNAL("clicked(int)"),
+ self, SLOT('slotCut()'), true, "Cut")
+ toolBar().insertButton(icons.loadIcon("editcopy", KDE::Icon::Toolbar), TOOLBAR_COPY, SIGNAL("clicked(int)"),
+ self, SLOT('slotCopy()'), true, "Copy")
+ toolBar().insertButton(icons.loadIcon("editpaste", KDE::Icon::Toolbar), TOOLBAR_PASTE, SIGNAL("clicked(int)"),
+ self, SLOT('slotPaste()'), true, "Paste")
+ end
+
+ def initStatusBar()
+ # KDE::MainWindow also owns a KDE::StatusBar instance. The first
+ # call creates a KDE::StatusBar instance. See 'notImpl' below
+ # for an example of writing to the status bar. You can
+ # also add widgets (labels, progress bars, etc) to the
+ # status bar
+
+ statusBar().insertItem("", STATUSBAR_LEFT, 1000, true)
+ statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true)
+ statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true)
+ end
+
+
+#-------------------- slots -----------------------------------------------
+
+ # Slots which can be called from both the menu toolbar
+ # have a second parameter with a default value (id = -1)
+ # This is because menu signals expect to connect to a
+ # slot that takes no arguments, while toolbar signals
+ # expect to send a signal with an int argument for the
+ # id of the toolbar button. The default value allows
+ # both cases to work.
+
+ def slotNew(id = -1)
+ notImpl("New")
+ end
+
+ def slotOpen(id = -1)
+ notImpl("Open")
+ end
+
+ def slotSave(id = -1)
+ notImpl("Save")
+ end
+
+ def slotSaveAs()
+ notImpl("Save As")
+ end
+
+ def slotPrint()
+ notImpl("Print")
+ end
+
+ def slotQuit()
+ notImpl("Qt::uit")
+ end
+
+ def slotUndo()
+ notImpl("Undo")
+ end
+
+ def slotRedo()
+ notImpl("Redo")
+ end
+
+ def slotCut(id = -1)
+ notImpl("Cut")
+ end
+
+ def slotCopy(id = -1)
+ notImpl("Copy")
+ end
+
+ def slotPaste(id = -1)
+ notImpl("Paste")
+ end
+
+ def slotFind()
+ notImpl("Find")
+ end
+
+ def slotFindNext()
+ notImpl("Find Next")
+ end
+
+ def slotReplace()
+ notImpl("Replace")
+ end
+
+ def notImpl(item = "Feature")
+ statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT)
+ KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented")
+ statusBar().changeItem("", STATUSBAR_LEFT)
+ end
+end
+
+#-------------------- main ------------------------------------------------
+
+# See athe minimal.rb and basicapp.rb templates for
+# explantion of the basic app and main window setup
+
+# The following data is passed to KDE::CmdLineArgs, which in
+# turn makes it available to the "about" box in the Help
+# menu (when the Help menu is created as above)
+
+description = "A basic application template"
+version = "1.0"
+aboutData = KDE::AboutData.new("", "",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show
+app.exec
diff --git a/korundum/rubylib/templates/annotated/menuapp2.rb b/korundum/rubylib/templates/annotated/menuapp2.rb
new file mode 100644
index 00000000..d3eab60d
--- /dev/null
+++ b/korundum/rubylib/templates/annotated/menuapp2.rb
@@ -0,0 +1,260 @@
+
+=begin
+This template constructs an application with menus, toolbar and statusbar.
+It uses KDE classes and methods that simplify the task of building and
+operating a GUI. It is recommended that this approach be used, rather
+than the primitive approach in menuapp1.rb
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+
+require 'Korundum'
+
+
+
+class MainWin < KDE::MainWindow
+ STATUSBAR_LEFT = 1
+ STATUSBAR_MIDDLE = 2
+ STATUSBAR_RIGHT = 3
+
+ slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()',
+ 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()',
+ 'slotSpecial()'
+
+ def initialize(*args)
+ super
+
+ # Create the actions that will populate
+ # the menus and toolbars
+ initActions()
+
+ # Plug actions into menus
+ initMenus()
+
+ # Plug actions into toolbars
+ initToolBar()
+
+ # Create the status bar
+ initStatusBar()
+
+ # Usings actions, only a single line is required
+ # to enable/disable both the menu item and corresponding
+ # toolbar button from anywhere in the program
+ @saveAction.setEnabled(false)
+ @saveAsAction.setEnabled(false)
+ end
+
+ def initActions()
+ # Most of the functions selectable by menu are "standard"
+ # actions (open a file, cut, paste, etc) - you customize
+ # how they behave in your code, but menu, toolbar, and
+ # accelerator settings are the same across all programs.
+ # Standard actions also have tooltips already assigned
+
+ # To create most of the actions below, KDE::StdAction is
+ # is used, since it takes care of everything with
+ # a single line of code.
+
+ # The standard actions only need to specify the slot
+ # where the code for the action is located
+
+ # "File" menu items
+ @newAction = KDE::StdAction.openNew(self, SLOT("slotNew()"), actionCollection())
+ @openAction = KDE::StdAction.open(self, SLOT("slotOpen()"), actionCollection())
+ @saveAction = KDE::StdAction.save(self, SLOT("slotSave()"), actionCollection())
+ @saveAsAction = KDE::StdAction.saveAs(self, SLOT("slotSaveAs()"), actionCollection())
+ @printAction = KDE::StdAction.print(self, SLOT("slotPrint()"), actionCollection())
+ @quitAction = KDE::StdAction.quit(self, SLOT("slotQuit()"), actionCollection())
+
+ # "Edit" menu items
+ @undoAction = KDE::StdAction.undo(self, SLOT("slotUndo()"), actionCollection())
+ @redoAction = KDE::StdAction.redo(self, SLOT("slotRedo()"), actionCollection())
+ @cutAction = KDE::StdAction.cut(self, SLOT("slotCut()"), actionCollection())
+ @copyAction = KDE::StdAction.copy(self, SLOT("slotCopy()"), actionCollection())
+ @pasteAction = KDE::StdAction.paste(self, SLOT("slotPaste()"), actionCollection())
+ @findAction = KDE::StdAction.find(self, SLOT("slotFind()"), actionCollection())
+ @findNextAction = KDE::StdAction.findNext(self, SLOT("slotFindNext()"), actionCollection())
+ @replaceAction = KDE::StdAction.replace(self, SLOT("slotReplace()"), actionCollection())
+
+ # For actions that are not "standard", you can create your
+ # own actions using KDE::Action. This example doesn't include
+ # an icon, but there is a KDE::Action constructor that will
+ # allow you to specify an icon (for toolbar use, for instance),
+ # or you can use KDE::Action.setIcon to set/change the icon. You
+ # can also add a tooltip with KDE::Action.setToolTip
+
+ # This KAction constructor requires a string, an accelerator (0
+ # in this case), a slot, and a QObject (None in this case)
+
+ @specialAction = KDE::Action.new(i18n("Special"), KDE::Shortcut.new(0), self, SLOT('slotSpecial()'), actionCollection(), "specialActionName")
+ end
+
+ def initMenus()
+ # plug the actions into the menus
+
+ fileMenu = Qt::PopupMenu.new(self)
+ @newAction.plug(fileMenu)
+ @openAction.plug(fileMenu)
+ fileMenu.insertSeparator()
+ @saveAction.plug(fileMenu)
+ @saveAsAction.plug(fileMenu)
+ fileMenu.insertSeparator()
+ @printAction.plug(fileMenu)
+ fileMenu.insertSeparator()
+ @quitAction.plug(fileMenu)
+ menuBar().insertItem(i18n("&File"), fileMenu)
+
+ editMenu = Qt::PopupMenu.new(self)
+ @undoAction.plug(editMenu)
+ @redoAction.plug(editMenu)
+ editMenu.insertSeparator()
+ @cutAction.plug(editMenu)
+ @copyAction.plug(editMenu)
+ @pasteAction.plug(editMenu)
+ editMenu.insertSeparator()
+ @findAction.plug(editMenu)
+ @findNextAction.plug(editMenu)
+ @replaceAction.plug(editMenu)
+ editMenu.insertSeparator()
+ @specialAction.plug(editMenu)
+ menuBar().insertItem(i18n("&Edit"), editMenu)
+
+ # Uses the info from KAboutData (specified below)
+ # to construct the "About" box in the Help menu
+
+ helpMenu = helpMenu("")
+ menuBar().insertItem(i18n("&Help"), helpMenu)
+ end
+
+ def initToolBar()
+ # Add some (but not all) actions to the toolbar
+
+ @newAction.plug(toolBar())
+ @openAction.plug(toolBar())
+ @saveAction.plug(toolBar())
+ @cutAction.plug(toolBar())
+ @copyAction.plug(toolBar())
+ @pasteAction.plug(toolBar())
+ end
+
+ def initStatusBar()
+ # Initialize the status bar
+
+ statusBar().insertItem("", STATUSBAR_LEFT, 1000, true)
+ statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true)
+ statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true)
+ end
+
+#-------------------- slots -----------------------------------------------
+
+ def slotNew(id = -1)
+ notImpl("New")
+ end
+
+ def slotOpen(id = -1)
+ notImpl("Open")
+ end
+
+ def slotSave(id = -1)
+ notImpl("Save")
+ end
+
+ def slotSaveAs()
+ notImpl("Save As")
+ end
+
+ def slotPrint()
+ notImpl("Print")
+ end
+
+ def slotQuit()
+ notImpl("Quit")
+ end
+
+ def slotUndo()
+ notImpl("Undo")
+ end
+
+ def slotRedo()
+ notImpl("Redo")
+ end
+
+ def slotCut(id = -1)
+ notImpl("Cut")
+ end
+
+ def slotCopy(id = -1)
+ notImpl("Copy")
+ end
+
+ def slotPaste(id = -1)
+ notImpl("Paste")
+ end
+
+ def slotFind()
+ notImpl("Find")
+ end
+
+ def slotFindNext()
+ notImpl("Find Next")
+ end
+
+ def slotReplace()
+ notImpl("Replace")
+ end
+
+ def notImpl(item = "Feature")
+ statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT)
+ KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented")
+ statusBar().changeItem("", STATUSBAR_LEFT)
+ end
+end
+
+
+#-------------------- main ------------------------------------------------
+
+description = "A basic application template"
+version = "1.0"
+aboutData = KDE::AboutData.new("", "",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show
+app.exec
diff --git a/korundum/rubylib/templates/annotated/menuapp3.rb b/korundum/rubylib/templates/annotated/menuapp3.rb
new file mode 100644
index 00000000..bd701d43
--- /dev/null
+++ b/korundum/rubylib/templates/annotated/menuapp3.rb
@@ -0,0 +1,221 @@
+=begin
+This template constructs an application with menus, toolbar and statusbar.
+It uses an XML file(menuapp3ui.rc) to specify the menu layout; all menu
+items have a corresponding action defined, but no menus are created
+explicitly in code. This app has the same menu layout as menuapp2.py
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+
+require 'Korundum'
+
+class MainWin < KDE::MainWindow
+ STATUSBAR_LEFT = 1
+ STATUSBAR_MIDDLE = 2
+ STATUSBAR_RIGHT = 3
+
+ slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()',
+ 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()',
+ 'slotSpecial()'
+
+ def initialize(*args)
+ super
+
+ # Create actions that correspond to those in the XML file
+ initActions()
+
+ # Parse the default XML file (<appName>ui.rc> and create
+ # the menus and toolbar. This single line (and the XML
+ # file it reads) replace initMenus and initToolBar from
+ # menuapp2.rb. Otherwise, the menuapp2 and menuapp3
+ # are identical 'createGUI' expects to find 'menuapp3ui.rc'
+ # either in the directory menuapp3.rb is run from, or
+ # in $KDEDIR/apps/menuapp3/
+ createGUI()
+
+ # Create the status bar
+ initStatusBar()
+
+ # Disable a couple of menu items using their actions
+ @saveAction.setEnabled(false)
+ @saveAsAction.setEnabled(false)
+ end
+
+ def initActions()
+ # Most of the functions selectable by menu are "standard"
+ # actions (open a file, cut, paste, etc) - you customize
+ # how they behave in your code, but menu, toolbar, and
+ # accelerator settings are the same across all programs.
+ # Standard actions also have tooltips already assigned
+
+ # To create most of the actions below, KDE::StdAction is
+ # is used, since it takes care of everything with
+ # a single line of code.
+
+ # The standard actions only need to specify the slot
+ # where the code for the action is located
+
+ # Because the XMLGUI mechanism parses $KDEDIR/config/ui/ui_standards.rc
+ # before parsing and merging menuapp3ui.rc, it actually isn't
+ # necessary to list KDE::StdAction actions in menuapp3.rc. THE XMLGUI
+ # code will create menu/toolbar items and place them *automatically*
+ # if you defined the KDE::StdActions as below. In fact, you can't override
+ # this behavior using KDE::StdActions - if you want menus to be "non-standard"
+ # KDE menus (eg 'Cut' in the 'File' menu), you'll need to create your
+ # actions from KDE::Action instead of KDE::StdAction. Obviously it makes more
+ # sense to use the mechanism provided to produce consistent menus and
+ # toolbars. You can "unplug" items if, for example, you don't want them
+ # in the toolBar.
+
+ # "File" menu items
+ @newAction = KDE::StdAction.openNew(self, SLOT("slotNew()"), actionCollection())
+ @openAction = KDE::StdAction.open(self, SLOT("slotOpen()"), actionCollection())
+ @saveAction = KDE::StdAction.save(self, SLOT("slotSave()"), actionCollection())
+ @saveAsAction = KDE::StdAction.saveAs(self, SLOT("slotSaveAs()"), actionCollection())
+ @printAction = KDE::StdAction.print(self, SLOT("slotPrint()"), actionCollection())
+ @quitAction = KDE::StdAction.quit(self, SLOT("slotQuit()"), actionCollection())
+
+
+ # "Edit" menu items
+ @undoAction = KDE::StdAction.undo(self, SLOT("slotUndo()"), actionCollection())
+ @redoAction = KDE::StdAction.redo(self, SLOT("slotRedo()"), actionCollection())
+ @cutAction = KDE::StdAction.cut(self, SLOT("slotCut()"), actionCollection())
+ @copyAction = KDE::StdAction.copy(self, SLOT("slotCopy()"), actionCollection())
+ @pasteAction = KDE::StdAction.paste(self, SLOT("slotPaste()"), actionCollection())
+ @findAction = KDE::StdAction.find(self, SLOT("slotFind()"), actionCollection())
+ @findNextAction = KDE::StdAction.findNext(self, SLOT("slotFindNext()"), actionCollection())
+ @replaceAction = KDE::StdAction.replace(self, SLOT("slotReplace()"), actionCollection())
+
+ # For ANYTHING constructed from KDE::Action or its descendants (KDE::ActionMenu, KDE::ActionSeparator,
+ # KDE::FontAction, etc) you MUST provide the actionCollection () parent and an object
+ # name ("specialActionName") or the XMLGUI mechanism will not be able to locate the
+ # action. XMLGUI finds the action via its member name value, NOT via its variable name.
+ @specialAction = KDE::Action.new(i18n("Special"), KDE::Shortcut.new(0), self, SLOT('slotSpecial()'), actionCollection(), "specialActionName")
+ end
+
+ def initStatusBar()
+ statusBar().insertItem("", STATUSBAR_LEFT, 1000, true)
+ statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true)
+ statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true)
+ end
+
+#-------------------- slots -----------------------------------------------
+
+
+ def slotNew(id = -1)
+ notImpl("New")
+ end
+
+ def slotOpen(id = -1)
+ notImpl("Open")
+ end
+
+ def slotSave(id = -1)
+ notImpl("Save")
+ end
+
+ def slotSaveAs()
+ notImpl("Save As")
+ end
+
+ def slotPrint()
+ notImpl("Print")
+ end
+
+ def slotQuit()
+ notImpl("Quit")
+ end
+
+ def slotUndo()
+ notImpl("Undo")
+ end
+
+ def slotRedo()
+ notImpl("Redo")
+ end
+
+ def slotCut(id = -1)
+ notImpl("Cut")
+ end
+
+ def slotCopy(id = -1)
+ notImpl("Copy")
+ end
+
+ def slotPaste(id = -1)
+ notImpl("Paste")
+ end
+
+ def slotFind()
+ notImpl("Find")
+ end
+
+ def slotFindNext()
+ notImpl("Find Next")
+ end
+
+ def slotReplace()
+ notImpl("Replace")
+ end
+
+ def notImpl(item = "Feature")
+ statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT)
+ KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented")
+ statusBar().changeItem("", STATUSBAR_LEFT)
+ end
+end
+
+
+#-------------------- main ------------------------------------------------
+
+description = "A basic application template"
+version = "1.0"
+
+# To use the XMLGUI mechanism, you MUST provide an appName
+# (the first argument to KDE::AboutData below) - the XML spec
+# for the interface will be in <appName>ui.rc (don't forget
+# the "ui" suffix to the application name)
+aboutData = KDE::AboutData.new("menuapp3", "",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show
+app.exec
+
diff --git a/korundum/rubylib/templates/annotated/menuapp3ui.rc b/korundum/rubylib/templates/annotated/menuapp3ui.rc
new file mode 100644
index 00000000..60120e21
--- /dev/null
+++ b/korundum/rubylib/templates/annotated/menuapp3ui.rc
@@ -0,0 +1,24 @@
+<!DOCTYPE kpartgui>
+<kpartgui name = "menuapp3">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name ="newAction"/>
+ <Action name ="openAction"/>
+ <Action name ="saveAction"/>
+ <Action name ="saveAsAction"/>
+ <Action name ="printAction"/>
+ <Action name ="quitAction"/>
+ </Menu>
+ <Menu name = "edit"><text>&amp;Edit</text>
+ <Action name ="undoAction"/>
+ <Action name ="redoAction"/>
+ <Action name ="cutAction"/>
+ <Action name ="copyAction"/>
+ <Action name ="pasteAction"/>
+ <Action name ="findAction"/>
+ <Action name ="findNextAction"/>
+ <Action name ="replaceAction"/>
+ <Action name ="specialActionName"/>
+ </Menu>
+</MenuBar>
+</kpartgui> \ No newline at end of file
diff --git a/korundum/rubylib/templates/annotated/minimal.rb b/korundum/rubylib/templates/annotated/minimal.rb
new file mode 100644
index 00000000..3ac9e23e
--- /dev/null
+++ b/korundum/rubylib/templates/annotated/minimal.rb
@@ -0,0 +1,80 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+This is a minimal PyKDE app template - it constructs an application
+and a main window, but does nothing else.
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+require 'Korundum'
+
+
+=begin
+Most Korundum applications will need a main window - the is the top
+level widget (the parent for all other widgets). KDE::MainWindow has
+more functionality than shown here (see more complex templates).
+It has the ability to create the other major parts of the user
+interface - the main view, menus, toolbars, etc.
+
+Usually you provide a subclass of KDE::MainWindow, construct menus
+and toolbars in the subclass' initialize method, and provide
+slots for menu/toolbar actions in separate methods.
+=end
+class MainWin < KDE::MainWindow
+ def initialize(*args)
+ super
+ end
+end
+
+
+#-------------------- main ------------------------------------------------
+
+# instantiate KDE::Application - no other Qt::Object
+# or Qt::Widget based classes can be instantiated
+# until there is a KDE::Application instance
+appName = "template"
+about = KDE::AboutData.new(appName, "A minimal application", "0.1")
+KDE::CmdLineArgs.init(ARGV, about)
+app = KDE::Application.new()
+
+# instantiate the subclass of KMainWindow
+mainWindow = MainWin.new(nil, "main window")
+
+# create the display
+mainWindow.show
+
+# run KDE::Application's event loop until the
+# program exits
+app.exec
+
+
diff --git a/korundum/rubylib/templates/annotated/systray1.rb b/korundum/rubylib/templates/annotated/systray1.rb
new file mode 100644
index 00000000..daf4f8ff
--- /dev/null
+++ b/korundum/rubylib/templates/annotated/systray1.rb
@@ -0,0 +1,94 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+A basic system tray application - you can combine this with code from
+menuapp2.rb or menuapp3.rb to quickly build a full-blown application
+framework.
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+require 'Korundum'
+
+# This template uses KDE::MainWindow as the main window widget
+# It solves the problem described in systray.rb by using
+# a flag to control the return value from queryClose - if
+# :quit" is signalled from anywhere EXCEPT the system tray
+# icon's menu, @exitFlag == false, and as the return
+# value for queryClose, it stops the application from shutting
+# down; if @exitFlag is true, the application shuts down
+
+class MainWin < KDE::MainWindow
+ slots 'slotQuitSelected()'
+
+ def initialize(*args)
+ super
+
+ @exitFlag = false
+
+ icons = KDE::IconLoader.new()
+
+ # KDE::SystemTray hides or shows its parent when the system tray icon is clicked
+ systray = KDE::SystemTray.new(self)
+ systray.setPixmap(icons.loadIcon("stop", 0))
+ connect(systray, SIGNAL("quitSelected()"), self, SLOT('slotQuitSelected()'))
+ systray.show()
+ end
+
+ # Controls whether or not the application really exits
+ def queryClose()
+ hide()
+ return @exitFlag
+ end
+
+ # Receives the signal emitted when the user selects Quit from the
+ # system tray icon's menu
+ def slotQuitSelected()
+ @exitFlag = true
+ $kapp.quit()
+ end
+end
+
+#-------------------- main ------------------------------------------------
+
+# The usual stuff..
+appName = "template"
+about = KDE::AboutData.new(appName, "A system tray", "0.1")
+KDE::CmdLineArgs.init(ARGV, about)
+app = KDE::Application.new()
+
+mainWindow = MainWin.new(nil, "main window")
+
+mainWindow.show
+app.exec
+
+
diff --git a/korundum/rubylib/templates/basic/basicapp.rb b/korundum/rubylib/templates/basic/basicapp.rb
new file mode 100644
index 00000000..5297c571
--- /dev/null
+++ b/korundum/rubylib/templates/basic/basicapp.rb
@@ -0,0 +1,61 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+require 'Korundum'
+
+class MainWin < KDE::MainWindow
+ def initialize(*args)
+ super
+ end
+
+end
+#-------------------- main ------------------------------------------------
+
+description = "A basic application template"
+version = "1.0"
+aboutData = KDE::AboutData.new("", "",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show
+app.exec
+
diff --git a/korundum/rubylib/templates/basic/menuapp1.rb b/korundum/rubylib/templates/basic/menuapp1.rb
new file mode 100644
index 00000000..3c8c9f51
--- /dev/null
+++ b/korundum/rubylib/templates/basic/menuapp1.rb
@@ -0,0 +1,213 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+
+=begin
+This template constructs an application with menus, toolbar and statusbar,
+HOWEVER it is not recommended this template actually be used. It presents
+the "KDE 1.0" method for constructing menus and toolbars - later versions
+of KDE have introduced better(easier and more powerful) methods for
+doing this job - see other menuapp*.rb templates for these methods
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+
+require 'Korundum'
+
+class MainWin < KDE::MainWindow
+ TOOLBAR_NEW = 1
+ TOOLBAR_OPEN = 2
+ TOOLBAR_SAVE = 3
+ TOOLBAR_CUT = 4
+ TOOLBAR_COPY = 5
+ TOOLBAR_PASTE = 6
+
+ STATUSBAR_LEFT = 1
+ STATUSBAR_MIDDLE = 2
+ STATUSBAR_RIGHT = 3
+
+ slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()',
+ 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()',
+ 'slotSpecial()'
+
+ def initialize(*args)
+ super
+
+ initMenus()
+ initToolBar()
+ initStatusBar()
+ end
+
+ def initMenus()
+ fileMenu = Qt::PopupMenu.new(self)
+
+ # "File" menu items
+ fileMenu.insertItem(i18n("New"), self, SLOT('slotNew()'), Qt::KeySequence.new(KDE::StdAccel.openNew().keyCodeQt()))
+ fileMenu.insertItem(i18n("Open"), self, SLOT('slotOpen()'), Qt::KeySequence.new(KDE::StdAccel.open().keyCodeQt()))
+ fileMenu.insertSeparator()
+ fileMenu.insertItem(i18n("Save"), self, SLOT('slotSave()'), Qt::KeySequence.new(KDE::StdAccel.save().keyCodeQt()))
+ fileMenu.insertItem(i18n("SaveAs"), self, SLOT('slotSaveAs()'))
+ fileMenu.insertSeparator()
+ fileMenu.insertItem(i18n("Print"), self, SLOT('slotPrint()'), Qt::KeySequence.new(KDE::StdAccel.print().keyCodeQt()))
+ fileMenu.insertSeparator()
+ fileMenu.insertItem(i18n("&Quit"), self, SLOT('slotQuit()'), Qt::KeySequence.new(KDE::StdAccel.quit().keyCodeQt()))
+
+ menuBar().insertItem(i18n("&File"), fileMenu)
+
+ editMenu = Qt::PopupMenu.new(self)
+
+ # "Edit" menu items
+ editMenu.insertItem(i18n("Undo"), self, SLOT('slotUndo()'), Qt::KeySequence.new(KDE::StdAccel.undo().keyCodeQt()))
+ editMenu.insertItem(i18n("Redo"), self, SLOT('slotRedo()'), Qt::KeySequence.new(KDE::StdAccel.redo().keyCodeQt()))
+ editMenu.insertSeparator()
+ editMenu.insertItem(i18n("Cut"), self, SLOT('slotCut()'), Qt::KeySequence.new(KDE::StdAccel.cut().keyCodeQt()))
+ editMenu.insertItem(i18n("Copy"), self, SLOT('slotCopy()'), Qt::KeySequence.new(KDE::StdAccel.copy().keyCodeQt()))
+ editMenu.insertItem(i18n("Paste"), self, SLOT('slotPaste()'), Qt::KeySequence.new(KDE::StdAccel.paste().keyCodeQt()))
+ editMenu.insertSeparator()
+ editMenu.insertItem(i18n("Find"), self, SLOT('slotFind()'), Qt::KeySequence.new(KDE::StdAccel.find().keyCodeQt()))
+ editMenu.insertItem(i18n("Find Next"), self, SLOT('slotFindNext()'), Qt::KeySequence.new(KDE::StdAccel.findNext().keyCodeQt()))
+ editMenu.insertItem(i18n("Replace"), self, SLOT('slotReplace()'), Qt::KeySequence.new(KDE::StdAccel.replace().keyCodeQt()))
+
+ menuBar().insertItem(i18n("&Edit"), editMenu)
+
+ helpMenu = helpMenu("")
+ menuBar().insertItem(i18n("&Help"), helpMenu)
+ end
+
+ def initToolBar()
+ icons = KDE::IconLoader.new()
+
+ toolBar().insertButton(icons.loadIcon("filenew", KDE::Icon::Toolbar), TOOLBAR_NEW, SIGNAL("clicked(int)"),
+ self, SLOT('slotNew()'), true, "New")
+ toolBar().insertButton(icons.loadIcon("fileopen", KDE::Icon::Toolbar), TOOLBAR_OPEN, SIGNAL("clicked(int)"),
+ self, SLOT('slotOpen()'), true, "Open")
+ toolBar().insertButton(icons.loadIcon("filesave", KDE::Icon::Toolbar), TOOLBAR_SAVE, SIGNAL("clicked(int)"),
+ self, SLOT('slotSave()'), true, "Save")
+ toolBar().insertButton(icons.loadIcon("editcut", KDE::Icon::Toolbar), TOOLBAR_CUT, SIGNAL("clicked(int)"),
+ self, SLOT('slotCut()'), true, "Cut")
+ toolBar().insertButton(icons.loadIcon("editcopy", KDE::Icon::Toolbar), TOOLBAR_COPY, SIGNAL("clicked(int)"),
+ self, SLOT('slotCopy()'), true, "Copy")
+ toolBar().insertButton(icons.loadIcon("editpaste", KDE::Icon::Toolbar), TOOLBAR_PASTE, SIGNAL("clicked(int)"),
+ self, SLOT('slotPaste()'), true, "Paste")
+ end
+
+ def initStatusBar()
+ statusBar().insertItem("", STATUSBAR_LEFT, 1000, true)
+ statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true)
+ statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true)
+ end
+
+
+#-------------------- slots -----------------------------------------------
+
+ def slotNew(id = -1)
+ notImpl("New")
+ end
+
+ def slotOpen(id = -1)
+ notImpl("Open")
+ end
+
+ def slotSave(id = -1)
+ notImpl("Save")
+ end
+
+ def slotSaveAs()
+ notImpl("Save As")
+ end
+
+ def slotPrint()
+ notImpl("Print")
+ end
+
+ def slotQuit()
+ notImpl("Qt::uit")
+ end
+
+ def slotUndo()
+ notImpl("Undo")
+ end
+
+ def slotRedo()
+ notImpl("Redo")
+ end
+
+ def slotCut(id = -1)
+ notImpl("Cut")
+ end
+
+ def slotCopy(id = -1)
+ notImpl("Copy")
+ end
+
+ def slotPaste(id = -1)
+ notImpl("Paste")
+ end
+
+ def slotFind()
+ notImpl("Find")
+ end
+
+ def slotFindNext()
+ notImpl("Find Next")
+ end
+
+ def slotReplace()
+ notImpl("Replace")
+ end
+
+ def notImpl(item = "Feature")
+ statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT)
+ KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented")
+ statusBar().changeItem("", STATUSBAR_LEFT)
+ end
+end
+
+#-------------------- main ------------------------------------------------
+
+description = "A basic application template"
+version = "1.0"
+aboutData = KDE::AboutData.new("", "",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show
+app.exec
diff --git a/korundum/rubylib/templates/basic/menuapp2.rb b/korundum/rubylib/templates/basic/menuapp2.rb
new file mode 100644
index 00000000..63430fd0
--- /dev/null
+++ b/korundum/rubylib/templates/basic/menuapp2.rb
@@ -0,0 +1,216 @@
+
+=begin
+This template constructs an application with menus, toolbar and statusbar.
+It uses KDE classes and methods that simplify the task of building and
+operating a GUI. It is recommended that this approach be used, rather
+than the primitive approach in menuapp1.py
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+
+require 'Korundum'
+
+
+
+class MainWin < KDE::MainWindow
+ STATUSBAR_LEFT = 1
+ STATUSBAR_MIDDLE = 2
+ STATUSBAR_RIGHT = 3
+
+ slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()',
+ 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()',
+ 'slotSpecial()'
+
+ def initialize(*args)
+ super
+
+ initActions()
+ initMenus()
+ initToolBar()
+ initStatusBar()
+
+ @saveAction.setEnabled(false)
+ @saveAsAction.setEnabled(false)
+ end
+
+ def initActions()
+ # "File" menu items
+ @newAction = KDE::StdAction.openNew(self, SLOT("slotNew()"), actionCollection())
+ @openAction = KDE::StdAction.open(self, SLOT("slotOpen()"), actionCollection())
+ @saveAction = KDE::StdAction.save(self, SLOT("slotSave()"), actionCollection())
+ @saveAsAction = KDE::StdAction.saveAs(self, SLOT("slotSaveAs()"), actionCollection())
+ @printAction = KDE::StdAction.print(self, SLOT("slotPrint()"), actionCollection())
+ @quitAction = KDE::StdAction.quit(self, SLOT("slotQuit()"), actionCollection())
+
+ # "Edit" menu items
+ @undoAction = KDE::StdAction.undo(self, SLOT("slotUndo()"), actionCollection())
+ @redoAction = KDE::StdAction.redo(self, SLOT("slotRedo()"), actionCollection())
+ @cutAction = KDE::StdAction.cut(self, SLOT("slotCut()"), actionCollection())
+ @copyAction = KDE::StdAction.copy(self, SLOT("slotCopy()"), actionCollection())
+ @pasteAction = KDE::StdAction.paste(self, SLOT("slotPaste()"), actionCollection())
+ @findAction = KDE::StdAction.find(self, SLOT("slotFind()"), actionCollection())
+ @findNextAction = KDE::StdAction.findNext(self, SLOT("slotFindNext()"), actionCollection())
+ @replaceAction = KDE::StdAction.replace(self, SLOT("slotReplace()"), actionCollection())
+ @specialAction = KDE::Action.new(i18n("Special"), KDE::Shortcut.new(0), self, SLOT('slotSpecial()'), actionCollection(), "specialActionName")
+ end
+
+ def initMenus()
+ fileMenu = Qt::PopupMenu.new(self)
+ @newAction.plug(fileMenu)
+ @openAction.plug(fileMenu)
+ fileMenu.insertSeparator()
+ @saveAction.plug(fileMenu)
+ @saveAsAction.plug(fileMenu)
+ fileMenu.insertSeparator()
+ @printAction.plug(fileMenu)
+ fileMenu.insertSeparator()
+ @quitAction.plug(fileMenu)
+ menuBar().insertItem(i18n("&File"), fileMenu)
+
+ editMenu = Qt::PopupMenu.new(self)
+ @undoAction.plug(editMenu)
+ @redoAction.plug(editMenu)
+ editMenu.insertSeparator()
+ @cutAction.plug(editMenu)
+ @copyAction.plug(editMenu)
+ @pasteAction.plug(editMenu)
+ editMenu.insertSeparator()
+ @findAction.plug(editMenu)
+ @findNextAction.plug(editMenu)
+ @replaceAction.plug(editMenu)
+ editMenu.insertSeparator()
+ @specialAction.plug(editMenu)
+ menuBar().insertItem(i18n("&Edit"), editMenu)
+
+ helpMenu = helpMenu("")
+ menuBar().insertItem(i18n("&Help"), helpMenu)
+ end
+
+ def initToolBar()
+ @newAction.plug(toolBar())
+ @openAction.plug(toolBar())
+ @saveAction.plug(toolBar())
+ @cutAction.plug(toolBar())
+ @copyAction.plug(toolBar())
+ @pasteAction.plug(toolBar())
+ end
+
+ def initStatusBar()
+ statusBar().insertItem("", STATUSBAR_LEFT, 1000, true)
+ statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true)
+ statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true)
+ end
+
+#-------------------- slots -----------------------------------------------
+
+ def slotNew(id = -1)
+ notImpl("New")
+ end
+
+ def slotOpen(id = -1)
+ notImpl("Open")
+ end
+
+ def slotSave(id = -1)
+ notImpl("Save")
+ end
+
+ def slotSaveAs()
+ notImpl("Save As")
+ end
+
+ def slotPrint()
+ notImpl("Print")
+ end
+
+ def slotQuit()
+ notImpl("Quit")
+ end
+
+ def slotUndo()
+ notImpl("Undo")
+ end
+
+ def slotRedo()
+ notImpl("Redo")
+ end
+
+ def slotCut(id = -1)
+ notImpl("Cut")
+ end
+
+ def slotCopy(id = -1)
+ notImpl("Copy")
+ end
+
+ def slotPaste(id = -1)
+ notImpl("Paste")
+ end
+
+ def slotFind()
+ notImpl("Find")
+ end
+
+ def slotFindNext()
+ notImpl("Find Next")
+ end
+
+ def slotReplace()
+ notImpl("Replace")
+ end
+
+ def notImpl(item = "Feature")
+ statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT)
+ KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented")
+ statusBar().changeItem("", STATUSBAR_LEFT)
+ end
+end
+
+
+#-------------------- main ------------------------------------------------
+
+description = "A basic application template"
+version = "1.0"
+aboutData = KDE::AboutData.new("", "",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show
+app.exec
diff --git a/korundum/rubylib/templates/basic/menuapp3.rb b/korundum/rubylib/templates/basic/menuapp3.rb
new file mode 100644
index 00000000..7751e847
--- /dev/null
+++ b/korundum/rubylib/templates/basic/menuapp3.rb
@@ -0,0 +1,174 @@
+=begin
+This template constructs an application with menus, toolbar and statusbar.
+It uses an XML file(menuapp3ui.rc) to specify the menu layout; all menu
+items have a corresponding action defined, but no menus are created
+explicitly in code. This app has the same menu layout as menuapp2.py
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+
+require 'Korundum'
+
+class MainWin < KDE::MainWindow
+ STATUSBAR_LEFT = 1
+ STATUSBAR_MIDDLE = 2
+ STATUSBAR_RIGHT = 3
+
+ slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()',
+ 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()',
+ 'slotSpecial()'
+
+ def initialize(*args)
+ super
+
+ initActions()
+ createGUI()
+ initStatusBar()
+
+ @saveAction.setEnabled(false)
+ @saveAsAction.setEnabled(false)
+ end
+
+ def initActions()
+ # "File" menu items
+ @newAction = KDE::StdAction.openNew(self, SLOT("slotNew()"), actionCollection())
+ @openAction = KDE::StdAction.open(self, SLOT("slotOpen()"), actionCollection())
+ @saveAction = KDE::StdAction.save(self, SLOT("slotSave()"), actionCollection())
+ @saveAsAction = KDE::StdAction.saveAs(self, SLOT("slotSaveAs()"), actionCollection())
+ @printAction = KDE::StdAction.print(self, SLOT("slotPrint()"), actionCollection())
+ @quitAction = KDE::StdAction.quit(self, SLOT("slotQuit()"), actionCollection())
+
+
+ # "Edit" menu items
+ @undoAction = KDE::StdAction.undo(self, SLOT("slotUndo()"), actionCollection())
+ @redoAction = KDE::StdAction.redo(self, SLOT("slotRedo()"), actionCollection())
+ @cutAction = KDE::StdAction.cut(self, SLOT("slotCut()"), actionCollection())
+ @copyAction = KDE::StdAction.copy(self, SLOT("slotCopy()"), actionCollection())
+ @pasteAction = KDE::StdAction.paste(self, SLOT("slotPaste()"), actionCollection())
+ @findAction = KDE::StdAction.find(self, SLOT("slotFind()"), actionCollection())
+ @findNextAction = KDE::StdAction.findNext(self, SLOT("slotFindNext()"), actionCollection())
+ @replaceAction = KDE::StdAction.replace(self, SLOT("slotReplace()"), actionCollection())
+ @specialAction = KDE::Action.new(i18n("Special"), KDE::Shortcut.new(0), self, SLOT('slotSpecial()'), actionCollection(), "specialActionName")
+ end
+
+ def initStatusBar()
+ statusBar().insertItem("", STATUSBAR_LEFT, 1000, true)
+ statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true)
+ statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true)
+ end
+
+#-------------------- slots -----------------------------------------------
+
+
+ def slotNew(id = -1)
+ notImpl("New")
+ end
+
+ def slotOpen(id = -1)
+ notImpl("Open")
+ end
+
+ def slotSave(id = -1)
+ notImpl("Save")
+ end
+
+ def slotSaveAs()
+ notImpl("Save As")
+ end
+
+ def slotPrint()
+ notImpl("Print")
+ end
+
+ def slotQuit()
+ notImpl("Quit")
+ end
+
+ def slotUndo()
+ notImpl("Undo")
+ end
+
+ def slotRedo()
+ notImpl("Redo")
+ end
+
+ def slotCut(id = -1)
+ notImpl("Cut")
+ end
+
+ def slotCopy(id = -1)
+ notImpl("Copy")
+ end
+
+ def slotPaste(id = -1)
+ notImpl("Paste")
+ end
+
+ def slotFind()
+ notImpl("Find")
+ end
+
+ def slotFindNext()
+ notImpl("Find Next")
+ end
+
+ def slotReplace()
+ notImpl("Replace")
+ end
+
+ def notImpl(item = "Feature")
+ statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT)
+ KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented")
+ statusBar().changeItem("", STATUSBAR_LEFT)
+ end
+end
+
+
+#-------------------- main ------------------------------------------------
+
+description = "A basic application template"
+version = "1.0"
+aboutData = KDE::AboutData.new("menuapp3", "",
+ version, description, KDE::AboutData::License_GPL,
+ "(C) 2003 whoever the author is")
+
+aboutData.addAuthor("author1", "whatever they did", "email@somedomain")
+aboutData.addAuthor("author2", "they did something else", "another@email.address")
+
+KDE::CmdLineArgs.init(ARGV, aboutData)
+
+KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]])
+
+app = KDE::Application.new()
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show
+app.exec
+
diff --git a/korundum/rubylib/templates/basic/menuapp3ui.rc b/korundum/rubylib/templates/basic/menuapp3ui.rc
new file mode 100644
index 00000000..60120e21
--- /dev/null
+++ b/korundum/rubylib/templates/basic/menuapp3ui.rc
@@ -0,0 +1,24 @@
+<!DOCTYPE kpartgui>
+<kpartgui name = "menuapp3">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name ="newAction"/>
+ <Action name ="openAction"/>
+ <Action name ="saveAction"/>
+ <Action name ="saveAsAction"/>
+ <Action name ="printAction"/>
+ <Action name ="quitAction"/>
+ </Menu>
+ <Menu name = "edit"><text>&amp;Edit</text>
+ <Action name ="undoAction"/>
+ <Action name ="redoAction"/>
+ <Action name ="cutAction"/>
+ <Action name ="copyAction"/>
+ <Action name ="pasteAction"/>
+ <Action name ="findAction"/>
+ <Action name ="findNextAction"/>
+ <Action name ="replaceAction"/>
+ <Action name ="specialActionName"/>
+ </Menu>
+</MenuBar>
+</kpartgui> \ No newline at end of file
diff --git a/korundum/rubylib/templates/basic/minimal.rb b/korundum/rubylib/templates/basic/minimal.rb
new file mode 100644
index 00000000..555875a2
--- /dev/null
+++ b/korundum/rubylib/templates/basic/minimal.rb
@@ -0,0 +1,56 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+require 'Korundum'
+
+
+
+class MainWin < KDE::MainWindow
+ def initialize(*args)
+ super
+ end
+end
+
+
+#-------------------- main ------------------------------------------------
+
+appName = "template"
+about = KDE::AboutData.new(appName, "A minimal application", "0.1")
+KDE::CmdLineArgs.init(ARGV, about)
+app = KDE::Application.new()
+
+mainWindow = MainWin.new(nil, "main window")
+mainWindow.show
+app.exec
+
+
diff --git a/korundum/rubylib/templates/basic/systray1.rb b/korundum/rubylib/templates/basic/systray1.rb
new file mode 100644
index 00000000..34f26f04
--- /dev/null
+++ b/korundum/rubylib/templates/basic/systray1.rb
@@ -0,0 +1,75 @@
+=begin
+This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale
+=end
+
+=begin
+Copyright 2003 Jim Bublitz
+
+Terms and Conditions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+copyright holder.
+=end
+
+require 'Korundum'
+
+class MainWin < KDE::MainWindow
+ slots 'slotQuitSelected()'
+
+ def initialize(*args)
+ super
+
+ @exitFlag = false
+
+ icons = KDE::IconLoader.new()
+
+ systray = KDE::SystemTray.new(self)
+ systray.setPixmap(icons.loadIcon("stop", 0))
+ connect(systray, SIGNAL("quitSelected()"), self, SLOT('slotQuitSelected()'))
+ systray.show()
+ end
+
+ def queryClose()
+ hide()
+ return @exitFlag
+ end
+
+ def slotQuitSelected()
+ @exitFlag = true
+ $kapp.quit()
+ end
+end
+
+#-------------------- main ------------------------------------------------
+
+appName = "template"
+about = KDE::AboutData.new(appName, "A system tray", "0.1")
+KDE::CmdLineArgs.init(ARGV, about)
+app = KDE::Application.new()
+
+mainWindow = MainWin.new(nil, "main window")
+
+mainWindow.show
+app.exec
+
+
diff --git a/korundum/rubylib/tutorials/p1/p1.rb b/korundum/rubylib/tutorials/p1/p1.rb
new file mode 100644
index 00000000..87e5e1b9
--- /dev/null
+++ b/korundum/rubylib/tutorials/p1/p1.rb
@@ -0,0 +1,13 @@
+require 'Qt'
+
+ a = Qt::Application.new( ARGV )
+
+ hello = Qt::PushButton.new( "Hello world!", nil )
+ hello.resize( 100, 30 )
+
+ Qt::Object::connect( hello, SIGNAL('clicked()'), a, SLOT('quit()') )
+
+ a.setMainWidget( hello )
+ hello.show()
+
+ a.exec() \ No newline at end of file
diff --git a/korundum/rubylib/tutorials/p2/p2.rb b/korundum/rubylib/tutorials/p2/p2.rb
new file mode 100644
index 00000000..b2c6d03c
--- /dev/null
+++ b/korundum/rubylib/tutorials/p2/p2.rb
@@ -0,0 +1,12 @@
+require 'Korundum'
+
+ about = KDE::AboutData.new("p2", "Hello World", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::Application.new()
+ hello = Qt::PushButton.new( a.i18n("Hello World !"), nil )
+ hello.autoResize = true
+
+ a.mainWidget = hello
+ hello.show
+
+ a.exec \ No newline at end of file
diff --git a/korundum/rubylib/tutorials/p3/p3.rb b/korundum/rubylib/tutorials/p3/p3.rb
new file mode 100644
index 00000000..fc575878
--- /dev/null
+++ b/korundum/rubylib/tutorials/p3/p3.rb
@@ -0,0 +1,61 @@
+require 'Korundum'
+
+class MainWindow < KDE::MainWindow
+ slots 'fileOpen()', 'fileSave()'
+
+ def initialize( name )
+ super(nil, name)
+ setCaption("KDE Tutorial - p3")
+
+ filemenu = Qt::PopupMenu.new
+ filemenu.insertItem( i18n( "&Open" ), self, SLOT('fileOpen()') )
+ filemenu.insertItem( i18n( "&Save" ), self, SLOT('fileSave()') )
+ filemenu.insertItem( i18n( "&Quit" ), $kapp, SLOT('quit()') )
+
+ about =
+ i18n("p3 1.0\n\n" +
+ "(C) 1999-2002 Antonio Larrosa Jimenez\n" +
+ "larrosa@kde.org\t\tantlarr@supercable.es\n" +
+ "Malaga (Spain)\n\n" +
+ "Simple KDE Tutorial\n" +
+ "This tutorial comes with ABSOLUTELY NO WARRANTY\n" +
+ "This is free software, and you are welcome to redistribute it\n" +
+ "under certain conditions\n")
+ helpmenu = helpMenu( about )
+
+ menu = menuBar()
+ menu.insertItem( i18n( "&File" ), filemenu )
+ menu.insertSeparator()
+ menu.insertItem( i18n( "&Help" ), helpmenu )
+
+ hello = Qt::TextEdit.new(
+ i18n("<H2>Hello World !</H2><BR>This is a simple" +
+ " window with <I><font size=5><B>R<font color=red" +
+ " size=5>ich </font><font color=blue size=5>Text" +
+ "</font></B></I> capabilities<BR>Try to resize" +
+ " this window, all this is automatic !"), "", self )
+ setCentralWidget(hello)
+ end
+
+ def fileOpen()
+ filename = KDE::FileDialog.getOpenURL( nil, "*", self )
+ msg = i18n("Now this app should open the url #{filename.url()}")
+ KDE::MessageBox.information( nil, msg, i18n( "Information" ),
+ "fileOpenInformationDialog" )
+ end
+
+ def fileSave()
+ filename = KDE::FileDialog.getSaveURL( nil, "*", self )
+ end
+end
+
+ about = KDE::AboutData.new("p3", "Tutorial - p3", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::Application.new()
+ window = MainWindow.new( "Tutorial - p3" )
+ window.resize( 400, 300 )
+
+ a.mainWidget = window
+ window.show
+
+ a.exec
diff --git a/korundum/rubylib/tutorials/p4/p4.rb b/korundum/rubylib/tutorials/p4/p4.rb
new file mode 100644
index 00000000..63777872
--- /dev/null
+++ b/korundum/rubylib/tutorials/p4/p4.rb
@@ -0,0 +1,67 @@
+require 'Korundum'
+
+class MainWindow < KDE::MainWindow
+ slots 'changeLocation()',
+ 'openURLRequest(const KURL &, const KParts::URLArgs & )'
+
+ def initialize( name )
+ super(nil, name)
+ setCaption("KDE Tutorial - p4")
+
+ filemenu = Qt::PopupMenu.new
+ filemenu.insertItem( i18n( "&Quit" ), $kapp, SLOT( 'quit()' ) )
+ about =
+ i18n("p4 1.0\n\n" +
+ "(C) 1999-2002 Antonio Larrosa Jimenez\n" +
+ "larrosa@kde.org\t\tantlarr@supercable.es\n" +
+ "Malaga (Spain)\n\n" +
+ "Simple KDE Tutorial\n" +
+ "This tutorial comes with ABSOLUTELY NO WARRANTY \n" +
+ "This is free software, and you are welcome to redistribute it\n" +
+ "under certain conditions\n");
+
+ helpmenu = helpMenu(about)
+ menu = menuBar()
+ menu.insertItem( i18n( "&File" ), filemenu)
+ menu.insertSeparator()
+ menu.insertItem(i18n("&Help"), helpmenu)
+
+ vbox = Qt::VBox.new( self )
+
+ @location = Qt::LineEdit.new( vbox )
+ @location.setText( "http://localhost" )
+
+ @browser = KDE::HTMLPart.new( vbox )
+ @browser.openURL( KDE::URL.new(@location.text()) )
+
+ connect( @location , SIGNAL( 'returnPressed()' ),
+ self, SLOT( 'changeLocation()' ) )
+
+ connect( @browser.browserExtension(),
+ SIGNAL( 'openURLRequest( const KURL &, const KParts::URLArgs & )' ),
+ self, SLOT( 'openURLRequest(const KURL &, const KParts::URLArgs & )' ) )
+
+ setCentralWidget(vbox)
+ end
+
+ def changeLocation()
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def openURLRequest(url, part)
+ @location.text = url.url()
+ changeLocation()
+ end
+end
+
+ about = KDE::AboutData.new("p4", "Tutorial - p4", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::Application.new()
+
+ window = MainWindow.new( "Tutorial - p4" )
+ window.resize( 300, 200 )
+
+ a.mainWidget = window
+ window.show
+
+ a.exec \ No newline at end of file
diff --git a/korundum/rubylib/tutorials/p5/p5.rb b/korundum/rubylib/tutorials/p5/p5.rb
new file mode 100644
index 00000000..8e16c2c8
--- /dev/null
+++ b/korundum/rubylib/tutorials/p5/p5.rb
@@ -0,0 +1,82 @@
+require 'Korundum'
+
+class MainWindow < KDE::MainWindow
+ slots 'changeLocation()',
+ 'openURLRequest(const KURL &, const KParts::URLArgs & )',
+ 'bookLocation()'
+
+ def initialize( name )
+ super(nil, name)
+ setCaption("KDE Tutorial - p5")
+
+ filemenu = Qt::PopupMenu.new
+ filemenu.insertItem( i18n( "&Quit" ), $kapp, SLOT( 'quit()' ) )
+ about =
+ i18n("p5 1.0\n\n" +
+ "(C) 1999-2002 Antonio Larrosa Jimenez\n" +
+ "larrosa@kde.org\t\tantlarr@supercable.es\n" +
+ "Malaga (Spain)\n\n" +
+ "Simple KDE Tutorial\n" +
+ "This tutorial comes with ABSOLUTELY NO WARRANTY \n" +
+ "This is free software, and you are welcome to redistribute it\n" +
+ "under certain conditions\n");
+
+ helpmenu = helpMenu(about)
+ menu = menuBar()
+ menu.insertItem( i18n( "&File" ), filemenu)
+ menu.insertSeparator()
+ menu.insertItem(i18n("&Help"), helpmenu)
+
+ vbox = Qt::VBox.new( self )
+
+ @location = Qt::LineEdit.new( vbox )
+ @location.setText( "http://localhost" )
+
+ connect( @location , SIGNAL( 'returnPressed()' ),
+ self, SLOT( 'changeLocation()' ) )
+
+ split = Qt::Splitter.new( vbox )
+ split.setOpaqueResize()
+
+ bookmark = Qt::PushButton.new( i18n("Add to Bookmarks"), split );
+
+ connect( bookmark, SIGNAL( 'clicked()' ), self, SLOT( 'bookLocation()' ) )
+
+ @browser = KDE::HTMLPart.new( split )
+ @browser.openURL( KDE::URL.new(@location.text()) )
+
+ connect( @browser.browserExtension(),
+ SIGNAL( 'openURLRequest( const KURL &, const KParts::URLArgs & )' ),
+ self, SLOT( 'openURLRequest(const KURL &, const KParts::URLArgs & )' ) )
+ setCentralWidget(vbox)
+ end
+
+
+ def changeLocation()
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def openURLRequest(url, part)
+ @location.text = url.url()
+ changeLocation()
+ end
+
+ def bookLocation()
+ dcopRef = KDE::DCOPRef.new("p6", "BookMarkList")
+ if ! dcopRef.add(@location.text())
+ qWarning("Error with DCOP\n")
+ end
+ end
+end
+
+ about = KDE::AboutData.new("p5", "Tutorial - p5", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::Application.new()
+
+ window = MainWindow.new( "Tutorial - p5" )
+ window.resize( 300, 200 )
+
+ a.mainWidget = window
+ window.show
+
+ a.exec
diff --git a/korundum/rubylib/tutorials/p6/addurl.sh b/korundum/rubylib/tutorials/p6/addurl.sh
new file mode 100644
index 00000000..6163dad4
--- /dev/null
+++ b/korundum/rubylib/tutorials/p6/addurl.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/bash
+
+dcop p6 BookMarkList add "http://www.kde.org"
diff --git a/korundum/rubylib/tutorials/p6/p6.rb b/korundum/rubylib/tutorials/p6/p6.rb
new file mode 100644
index 00000000..ea7b2b1e
--- /dev/null
+++ b/korundum/rubylib/tutorials/p6/p6.rb
@@ -0,0 +1,26 @@
+require 'Korundum'
+
+class BookMarkList < KDE::ListView
+ k_dcop 'void add( QString )'
+
+ def initialize()
+ super(nil, "Bookmarks")
+ addColumn( i18n("My Bookmarks") );
+ end
+
+ def add( s )
+ insertItem( KDE::ListViewItem.new( self , s ) )
+ end
+end
+
+ about = KDE::AboutData.new("p6", "Tutorial - p6", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::UniqueApplication.new()
+
+ mylist = BookMarkList.new
+ mylist.resize( 300, 200 )
+
+ a.mainWidget = mylist
+ mylist.show
+
+ a.exec \ No newline at end of file
diff --git a/korundum/rubylib/tutorials/p7/p7.rb b/korundum/rubylib/tutorials/p7/p7.rb
new file mode 100644
index 00000000..650f4db5
--- /dev/null
+++ b/korundum/rubylib/tutorials/p7/p7.rb
@@ -0,0 +1,127 @@
+require 'Korundum'
+
+class Browser < KDE::MainWindow
+ k_dcop 'void setURL(QString)'
+
+ slots 'fileSetDefaultPage()',
+ 'changeLocation()',
+ 'bookLocation()',
+ 'gotoPreviousPage()',
+ 'openURLRequest(const KURL&, const KParts::URLArgs&)'
+
+ TOOLBAR_ID_ADDBOOKMARK = 1
+ TOOLBAR_ID_BACK = 2
+ TOOLBAR_ID_QUIT = 3
+
+ def initialize( name )
+ super(nil, name)
+ setCaption("KDE Tutorial - p7")
+ @history = []
+
+ filemenu = Qt::PopupMenu.new
+ filemenu.insertItem( i18n( "&Set default page" ),
+ self, SLOT( 'fileSetDefaultPage()' ) )
+ filemenu.insertItem(i18n( "&Quit" ), $kapp, SLOT( 'quit()' ))
+ about =
+ i18n("p7 1.0\n\n" +
+ "(C) 1999-2002 Antonio Larrosa Jimenez\n" +
+ "larrosa@kde.org\t\tantlarr@supercable.es\n" +
+ "Malaga (Spain)\n\n" +
+ "Simple KDE Tutorial\n" +
+ "This tutorial comes with ABSOLUTELY NO WARRANTY \n" +
+ "This is free software, and you are welcome to redistribute it\n" +
+ "under certain conditions\n");
+
+ helpmenu = helpMenu(about)
+ menu = menuBar()
+ menu.insertItem( i18n( "&File" ), filemenu)
+ menu.insertSeparator()
+ menu.insertItem(i18n("&Help"), helpmenu)
+
+ toolbar = KDE::ToolBar.new(self)
+
+ icons = KDE::IconLoader.new()
+ toolbar.insertButton(icons.loadIcon("reload", KDE::Icon::Toolbar), TOOLBAR_ID_ADDBOOKMARK,
+ SIGNAL('clicked(int)'),self,SLOT('bookLocation()'),true,
+ i18n("Add to Bookmarks"))
+ toolbar.insertButton(icons.loadIcon("back", KDE::Icon::Toolbar), TOOLBAR_ID_BACK,
+ SIGNAL('clicked(int)'),self,SLOT('gotoPreviousPage()'),
+ false, i18n("Back to previous page"))
+ toolbar.insertButton(icons.loadIcon("exit", KDE::Icon::Toolbar), TOOLBAR_ID_QUIT,
+ SIGNAL('clicked(int)'),$kapp,SLOT('quit()'),true,
+ i18n("Quit the application"))
+ addToolBar(toolbar)
+
+ vbox = Qt::VBox.new( self )
+
+ @location = Qt::LineEdit.new( vbox )
+
+ config = $kapp.config()
+ config.setGroup("Settings")
+ @location.text = config.readEntry( "defaultPage", "http://localhost")
+
+ connect( @location , SIGNAL( 'returnPressed()' ),
+ self, SLOT( 'changeLocation()' ) )
+
+ split = Qt::Splitter.new( vbox )
+ split.setOpaqueResize()
+
+ @browser = KDE::HTMLPart.new( split )
+ @browser.openURL( KDE::URL.new(@location.text()) )
+
+ connect( @browser.browserExtension(),
+ SIGNAL( 'openURLRequest( const KURL&, const KParts::URLArgs& )' ),
+ self, SLOT( 'openURLRequest(const KURL&, const KParts::URLArgs& )' ) )
+ setCentralWidget(vbox)
+ end
+
+ def changeLocation()
+ @history.push( @browser.url().url() );
+ toolBar().setItemEnabled( TOOLBAR_ID_BACK, true)
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def setURL( url )
+ @location.text = url
+ changeLocation()
+ end
+
+ def openURLRequest(url, part)
+ setURL( url.url() )
+ end
+
+ def gotoPreviousPage()
+ @location.text = @history.pop()
+ if @history.empty?
+ toolBar().setItemEnabled(TOOLBAR_ID_BACK, false)
+ end
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def bookLocation()
+ dcopRef = KDE::DCOPRef.new("p8", "BookMarkList")
+ if ! dcopRef.add(@location.text())
+ qWarning("Error with DCOP\n")
+ end
+ end
+
+ def fileSetDefaultPage()
+ config = $kapp.config()
+
+ config.group = "Settings"
+ config.writeEntry( "defaultPage", @browser.url().url() )
+ end
+end
+
+ about = KDE::AboutData.new("p7", "Tutorial - p7", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::UniqueApplication.new()
+
+ window = Browser.new( "Tutorial - p7" )
+ window.resize( 300, 200 )
+
+ a.mainWidget = window
+ window.show
+
+ a.exec
+
diff --git a/korundum/rubylib/tutorials/p8/p8.rb b/korundum/rubylib/tutorials/p8/p8.rb
new file mode 100644
index 00000000..711fe021
--- /dev/null
+++ b/korundum/rubylib/tutorials/p8/p8.rb
@@ -0,0 +1,39 @@
+require 'Korundum'
+
+class BookMarkList < KDE::ListView
+ k_dcop 'void add(QString)'
+
+ slots 'setURLInBrowser(QListViewItem *)'
+
+ def initialize()
+ super(nil, "Bookmarks")
+ addColumn( i18n("My Bookmarks") );
+ connect( self, SIGNAL('clicked(QListViewItem *)'),
+ self, SLOT('setURLInBrowser(QListViewItem *)'))
+ end
+
+ def add( s )
+ insertItem( KDE::ListViewItem.new( self , s ) )
+ end
+
+ def setURLInBrowser( item )
+ if item.nil? then return end
+ dcopRef = KDE::DCOPRef.new("p7", "Browser")
+ if ! dcopRef.setURL(item.text(0))
+ qWarning("Error with DCOP\n")
+ end
+ end
+end
+
+ about = KDE::AboutData.new("p8", "Tutorial - p8", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::UniqueApplication.new()
+
+ mylist = BookMarkList.new
+ mylist.resize( 300, 200 )
+
+ a.mainWidget = mylist
+ mylist.show
+
+ a.exec
+
diff --git a/korundum/rubylib/tutorials/p9/p9.rb b/korundum/rubylib/tutorials/p9/p9.rb
new file mode 100644
index 00000000..98bb9d0e
--- /dev/null
+++ b/korundum/rubylib/tutorials/p9/p9.rb
@@ -0,0 +1,110 @@
+require 'Korundum'
+
+class Browser < KDE::MainWindow
+ k_dcop 'void setURL(QString)'
+
+ slots 'fileSetDefaultPage()',
+ 'changeLocation()',
+ 'bookLocation()',
+ 'gotoPreviousPage()',
+ 'openURLRequest(const KURL&, const KParts::URLArgs&)'
+
+ def initialize( name )
+ super(nil, name)
+ @history = []
+
+ KDE::StdAction.quit(self, SLOT('close()'), actionCollection())
+
+ KDE::Action.new(i18n("&Set default page"), "gohome", KDE::Shortcut.new(0), self,
+ SLOT('fileSetDefaultPage()'), actionCollection(), "set_default_page")
+
+ KDE::Action.new(i18n("Add to Bookmarks"), "reload", KDE::Shortcut.new(0), self,
+ SLOT('bookLocation()'), actionCollection(), "add_to_bookmarks")
+
+ KDE::Action.new(i18n("Back to previous page"), "back", KDE::Shortcut.new(0), self,
+ SLOT('gotoPreviousPage()'), actionCollection(), "back")
+
+ actionCollection().action("back").setEnabled(false)
+
+ createGUI(Dir.getwd + "/p9ui.rc")
+
+ vbox = Qt::VBox.new( self )
+
+ @location = Qt::LineEdit.new( vbox )
+
+ config = $kapp.config()
+ config.setGroup("Settings")
+ @location.text = config.readEntry( "defaultPage", "http://localhost")
+
+ connect( @location , SIGNAL( 'returnPressed()' ),
+ self, SLOT( 'changeLocation()' ) )
+
+ @browser = KDE::HTMLPart.new( vbox )
+ @browser.openURL( KDE::URL.new(@location.text()) )
+
+ connect( @browser.browserExtension(),
+ SIGNAL( 'openURLRequest( const KURL&, const KParts::URLArgs& )' ),
+ self, SLOT( 'openURLRequest(const KURL&, const KParts::URLArgs& )' ) )
+ setCentralWidget(vbox)
+ end
+
+
+ def changeLocation()
+ @history.push( @browser.url().url() );
+ actionCollection().action("back").setEnabled(true)
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def setURL( url )
+ @location.text = url
+ changeLocation()
+ end
+
+ def openURLRequest(url, part)
+ setURL( url.url() )
+ end
+
+ def gotoPreviousPage()
+ @location.text = @history.pop()
+ if @history.empty?
+ actionCollection().action("back").setEnabled(false)
+ end
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def bookLocation()
+ dcopRef = KDE::DCOPRef.new("p8", "BookMarkList")
+ if ! dcopRef.add(@location.text())
+ qWarning("Error with DCOP\n")
+ end
+ end
+
+ def fileSetDefaultPage()
+ config = $kapp.config()
+
+ config.group = "Settings"
+ config.writeEntry( "defaultPage", @browser.url().url() )
+ end
+end
+
+ aboutdata = KDE::AboutData.new("p9", "Tutorial - p9",
+ "1.0", "Step 9 of a simple tutorial", KDE::AboutData::License_GPL,
+ "(C) 2000, 2001 Antonio Larrosa Jimenez","",
+ "http://devel-home.kde.org/~larrosa/tutorial.html")
+ aboutdata.addAuthor("Antonio Larrosa Jimenez",
+ "Original Developer/Mantainer","larrosa@kde.org",
+ "http://devel-home.kde.org/~larrosa/index.html")
+ aboutdata.addAuthor("Richard Dale",
+ "Ruby port","Richard_Dale@tipitina.demon.co.uk",
+ "")
+ KDE::CmdLineArgs.init(ARGV, aboutdata)
+
+ a = KDE::UniqueApplication.new()
+
+ window = Browser.new( "Tutorial - p9" )
+ window.resize( 300, 200 )
+
+ a.mainWidget = window
+ window.show
+
+ a.exec
diff --git a/korundum/rubylib/tutorials/p9/p9ui.rc b/korundum/rubylib/tutorials/p9/p9ui.rc
new file mode 100644
index 00000000..9e194c20
--- /dev/null
+++ b/korundum/rubylib/tutorials/p9/p9ui.rc
@@ -0,0 +1,14 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd" >
+<kpartgui name="p9" version="1">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="set_default_page"/>
+ </Menu>
+</MenuBar>
+<ToolBar fullWidth="true" name="mainToolBar">
+ <Action name="add_to_bookmarks"/>
+ <Action name="back"/>
+ <Separator/>
+ <Action name="file_quit"/>
+</ToolBar>
+</kpartgui> \ No newline at end of file