summaryrefslogtreecommitdiff
path: root/libopie2
Side-by-side diff
Diffstat (limited to 'libopie2') (more/less context) (show whitespace changes)
-rw-r--r--libopie2/.cvsignore6
-rw-r--r--libopie2/README148
-rw-r--r--libopie2/ROADMAP6
-rw-r--r--libopie2/STATUS68
-rw-r--r--libopie2/config.in10
-rw-r--r--libopie2/examples/.cvsignore6
-rw-r--r--libopie2/examples/config.in6
-rw-r--r--libopie2/examples/examples.pro4
-rw-r--r--libopie2/examples/opiecore/.cvsignore6
-rw-r--r--libopie2/examples/opiecore/oconfigdemo/.cvsignore6
-rw-r--r--libopie2/examples/opiecore/oconfigdemo/oconfigdemo.cpp31
-rw-r--r--libopie2/examples/opiecore/oconfigdemo/oconfigdemo.pro14
-rw-r--r--libopie2/examples/opiecore/odebugdemo/.cvsignore6
-rw-r--r--libopie2/examples/opiecore/odebugdemo/odebugdemo.cpp138
-rw-r--r--libopie2/examples/opiecore/odebugdemo/odebugdemo.pro14
-rw-r--r--libopie2/examples/opiecore/oglobalsettingsdemo/.cvsignore6
-rw-r--r--libopie2/examples/opiecore/oglobalsettingsdemo/oglobalsettingsdemo.cpp13
-rw-r--r--libopie2/examples/opiecore/oglobalsettingsdemo/oglobalsettingsdemo.pro14
-rw-r--r--libopie2/examples/opiecore/opiecore.pro3
-rw-r--r--libopie2/examples/opienet/.cvsignore6
-rw-r--r--libopie2/examples/opienet/miniwellenreiter/.cvsignore6
-rw-r--r--libopie2/examples/opienet/miniwellenreiter/miniwellenreiter.cpp199
-rw-r--r--libopie2/examples/opienet/miniwellenreiter/miniwellenreiter.pro13
-rw-r--r--libopie2/examples/opienet/onetworkdemo/.cvsignore6
-rw-r--r--libopie2/examples/opienet/onetworkdemo/onetworkdemo.cpp35
-rw-r--r--libopie2/examples/opienet/onetworkdemo/onetworkdemo.pro12
-rw-r--r--libopie2/examples/opienet/opienet.pro3
-rw-r--r--libopie2/examples/opieui/.cvsignore6
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/1.pngbin0 -> 1969 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/1small.pngbin0 -> 708 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/2.pngbin0 -> 2333 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/2small.pngbin0 -> 875 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/3.pngbin0 -> 2009 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/3small.pngbin0 -> 921 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/4.pngbin0 -> 2076 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/4small.pngbin0 -> 762 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/5.pngbin0 -> 2266 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/5small.pngbin0 -> 743 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/6.pngbin0 -> 2491 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/6small.pngbin0 -> 894 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/folder_closed.pngbin0 -> 675 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/folder_closed32.pngbin0 -> 2105 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/folder_opened.pngbin0 -> 743 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/folder_opened32.pngbin0 -> 2112 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/leaf.pngbin0 -> 717 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/leaf32.pngbin0 -> 1904 bytes
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/main.cpp29
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/opieui.pro17
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/opieuidemo.cpp205
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/opieuidemo.h56
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/oversatileviewdemo.cpp158
-rw-r--r--libopie2/examples/opieui/oversatileviewdemo/oversatileviewdemo.h73
-rw-r--r--libopie2/libopie2.control10
-rwxr-xr-xlibopie2/libopie2.postinst4
-rw-r--r--libopie2/libopie2.pro4
-rw-r--r--libopie2/opiecore/.cvsignore6
-rw-r--r--libopie2/opiecore/config.in6
-rw-r--r--libopie2/opiecore/oapplication.cpp110
-rw-r--r--libopie2/opiecore/oapplication.h114
-rw-r--r--libopie2/opiecore/oconfig.cpp201
-rw-r--r--libopie2/opiecore/oconfig.h167
-rw-r--r--libopie2/opiecore/odebug.cpp628
-rw-r--r--libopie2/opiecore/odebug.h474
-rw-r--r--libopie2/opiecore/oglobal.cpp36
-rw-r--r--libopie2/opiecore/oglobal.h48
-rw-r--r--libopie2/opiecore/oglobalsettings.cpp547
-rw-r--r--libopie2/opiecore/oglobalsettings.h368
-rw-r--r--libopie2/opiecore/opiecore.pro31
-rw-r--r--libopie2/opiedb/config.in7
-rw-r--r--libopie2/opiedb/opiedb.pro17
-rw-r--r--libopie2/opienet/.cvsignore6
-rw-r--r--libopie2/opienet/802_11_user.h419
-rw-r--r--libopie2/opienet/config.in7
-rw-r--r--libopie2/opienet/onetutils.cpp101
-rw-r--r--libopie2/opienet/onetutils.h125
-rw-r--r--libopie2/opienet/onetwork.cpp774
-rw-r--r--libopie2/opienet/onetwork.h307
-rw-r--r--libopie2/opienet/opcap.cpp609
-rw-r--r--libopie2/opienet/opcap.h294
-rw-r--r--libopie2/opienet/opienet.pro18
-rw-r--r--libopie2/opiepim/.cvsignore6
-rw-r--r--libopie2/opiepim/config.in7
-rw-r--r--libopie2/opiepim/opiepim.pro17
-rw-r--r--libopie2/opieui/.cvsignore6
-rw-r--r--libopie2/opieui/config.in7
-rw-r--r--libopie2/opieui/odialog.cpp53
-rw-r--r--libopie2/opieui/odialog.h89
-rw-r--r--libopie2/opieui/oimageeffect.cpp3794
-rw-r--r--libopie2/opieui/oimageeffect.h558
-rw-r--r--libopie2/opieui/olistview.cpp423
-rw-r--r--libopie2/opieui/olistview.h235
-rw-r--r--libopie2/opieui/opieui.pro46
-rw-r--r--libopie2/opieui/opixmapeffect.cpp328
-rw-r--r--libopie2/opieui/opixmapeffect.h215
-rw-r--r--libopie2/opieui/opixmapprovider.cpp27
-rw-r--r--libopie2/opieui/opixmapprovider.h54
-rw-r--r--libopie2/opieui/opopupmenu.cpp604
-rw-r--r--libopie2/opieui/opopupmenu.h256
-rw-r--r--libopie2/opieui/oselector.cpp716
-rw-r--r--libopie2/opieui/oselector.h518
-rw-r--r--libopie2/opieui/oseparator.cpp128
-rw-r--r--libopie2/opieui/oseparator.h90
-rw-r--r--libopie2/opieui/oversatileview.cpp1179
-rw-r--r--libopie2/opieui/oversatileview.h394
-rw-r--r--libopie2/opieui/oversatileviewitem.cpp132
-rw-r--r--libopie2/opieui/oversatileviewitem.h100
-rw-r--r--libopie2/pics/view_icon.pngbin0 -> 357 bytes
-rw-r--r--libopie2/pics/view_icon.xpm35
-rw-r--r--libopie2/pics/view_tree.pngbin0 -> 464 bytes
-rw-r--r--libopie2/pics/view_tree.xpm36
-rw-r--r--libopie2/qt3/opiecore/ocompletion.cpp1061
-rw-r--r--libopie2/qt3/opiecore/ocompletion.h603
-rw-r--r--libopie2/qt3/opiecore/ocompletionbase.cpp171
-rw-r--r--libopie2/qt3/opiecore/ocompletionbase.h403
-rw-r--r--libopie2/qt3/opiecore/opair.h99
-rw-r--r--libopie2/qt3/opiecore/osortablevaluelist.h117
-rw-r--r--libopie2/qt3/opiecore/otl.h325
-rw-r--r--libopie2/qt3/opieui/ocombobox.cpp666
-rw-r--r--libopie2/qt3/opieui/ocombobox.h790
-rw-r--r--libopie2/qt3/opieui/ocompletionbox.cpp408
-rw-r--r--libopie2/qt3/opieui/ocompletionbox.h232
-rw-r--r--libopie2/qt3/opieui/oeditlistbox.cpp416
-rw-r--r--libopie2/qt3/opieui/oeditlistbox.h250
-rw-r--r--libopie2/qt3/opieui/ojanuswidget.cpp1116
-rw-r--r--libopie2/qt3/opieui/ojanuswidget.h551
-rw-r--r--libopie2/qt3/opieui/olineedit.cpp729
-rw-r--r--libopie2/qt3/opieui/olineedit.h498
127 files changed, 25255 insertions, 0 deletions
diff --git a/libopie2/.cvsignore b/libopie2/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/README b/libopie2/README
new file mode 100644
index 0000000..96210db
--- a/dev/null
+++ b/libopie2/README
@@ -0,0 +1,148 @@
+/********************************************************************
+/* This is an overview of the opielibs2 project
+/********************************************************************/
+
+ Origin: opielibs is about creating classes to
+ * optimize Qt classes for the embedded environment
+ * provide sophisticated abstractions for developers
+ * provide complete documentation and working examples
+ * provide end users with a common look and feel
+ * reduce memory footprint through sharing code
+ * reduce possible bugs through reusing tested code
+
+--------------------------------------------------------
+1. General Overview
+--------------------------------------------------------
+
+libopie is functionally seperated into the following libraries:
+ - libopiecore
+ - libopieui
+ - libopiepim
+ - libopiedb
+ - libopienet
+
+1.1 Contents of libopiecore [ opiecore ]
+--------------------------------------------------------
+
+ - odbgstream
+ - ondbgstream
+
+ - oprocctrl
+ - oprocess
+ - odevice
+ - odevicebutton
+
+ - oconfig
+ - oconfiggroupsaver
+
+ - ocompletionbase
+ - ocompletion
+ - ocomptreenodelist
+ - ocomptreenode
+ - ocompletionwrapper
+
+ - oglobal
+ - oglobalsettings
+
+ - osortableitem
+ - osortablevaluelist
+
+1.2 Contents of libopieui [ opieui ]
+--------------------------------------------------------
+
+ - oapplication
+
+ - ofiledialog
+ - colordialog
+ - oclickablelabel
+ - ocolorbutton
+ - colorpopupmenu
+ - otabinfo
+ - otabbar
+ - otabwidget
+ - ofontmenu
+ - ofontselector
+ - ofileview
+ - oticker
+
+ - olistview
+ - olistviewitem
+ - oversatileview
+ - oversatileviewitem
+ - ocompletionbox
+ - olineedit
+ - ocombobox
+ - ohistorycombo
+
+ - omessagebox
+ - odialogbase
+
+ - todayconfigwidget (rather into opiepim?)
+ - orecurrancewidget (rather into opiepim?)
+ - otimepicker (rather into opiepim?)
+
+1.3 Contents of libopiepim [ opiepim ]
+--------------------------------------------------------
+
+ - ocheckitem
+ - todoevent
+ - todoresource
+ - todayplugininterface
+ - todovcalresource
+
+1.4 Contents of libopiedb [ opiedb ]
+--------------------------------------------------------
+
+ - tododb
+ - xmltree
+
+1.5 Contents of libopienet [ opienet ]
+--------------------------------------------------------
+
+ - onetwork
+ - onetworkinterface
+ - owirelessnetworkinterface
+ - ochannelhopper
+
+ - omonitoring
+ - ociscomonitoring
+ - owlanngmonitoring
+ - ohostapmonitoring
+ - oorinocomonitoring
+
+ - opacketcapturer
+ - opacket
+ - oethernetpacket
+ - owavelanpacket
+ - ollcpacket
+ - oippacket
+ - oudppacket
+ - otcppacket
+
+ <libmail stuff>
+ <libbend stuff>
+ <libftp stuff>
+
+
+--------------------------------------------------------
+2.0 Feature Description
+--------------------------------------------------------
+
+2.1 libopiecore
+
+...
+
+2.2 libopieui
+
+...
+
+2.3 libopiepim
+
+...
+
+2.4 libopiedb
+
+...
+
+2.5 libopienet
+
diff --git a/libopie2/ROADMAP b/libopie2/ROADMAP
new file mode 100644
index 0000000..966b67d
--- a/dev/null
+++ b/libopie2/ROADMAP
@@ -0,0 +1,6 @@
+ [done] * import current status of opiecore, opienet and opieui
+ * add contents of libopie1 to libopie2 and functionally split it
+ * make libopie2 a drop-in-replacement for libopie1
+ * add doxygen documentation to all classes
+ * backport qt3-only stuff (?)
+
diff --git a/libopie2/STATUS b/libopie2/STATUS
new file mode 100644
index 0000000..eb3442c
--- a/dev/null
+++ b/libopie2/STATUS
@@ -0,0 +1,68 @@
+
+==================================================================
+March 2003 - Initial checkin into the Opie CVS:
+==================================================================
+
+So, this is what I have been working on over the last months.
+It's a part of what I think could migrate into our next generation
+opielibs.
+Of course this won't happen after we released Opie 1.0 and switched
+to Qt3-Embedded and gcc 3.
+
+Right now, there is content only in opiecore, opienet and opieui.
+A good part of code has been adapted from the kdelibs, which overall
+are pretty good however in details of heterogenous quality. I'm also
+not sure if all I ported should be kept, e.g. the pixmapeffect stuff
+seems unnecesary to me. However, we should not forget that Opie will
+make its debut on more powerful devices with greater display
+resolution, e.g. the Sharp C700, so we shouldn't limit ourselves in
+what should go into the libraries.
+
+Generally spoken, a lot of things are still very rough and messy,
+but I will keep improving this. Some details about what is usable
+and what is not follows:
+(everything compiles of course, otherwise I wouldn't have checked in :-)
+
+[-----------]
+[ opiecore ]
+[-----------]
+oapplication, oconfig, oglobal seem to be usable yet, oglobalsettings
+is still very messy and should be revised. A lot more thinking about how
+we should keep opie preferences, especially when moving to multi-user, has to be made.
+This will affect what goes into oglobalsettings and what configuration data
+format we will use. If we switch to Qt3 we will have to decide if we stay
+with OConfig deriving from Config or rewrite it using QSettings.
+
+[-----------]
+[ opiedb ]
+[-----------]
+There is nothing here yet. The sqlite stuff should be here.
+
+[-----------]
+[ opienet ]
+[-----------]
+onetwork*, omonitoring* and the opacket stuff are pretty usable and not
+very far from being complete. documentation for these will come...
+Over the next days, opie-wellenreiter, opie-wirelessapplet and the
+forthcoming new opie-networkapplet will be using the
+new network classes.
+I think all the other network libraries spread throught opie, e.g.
+libbend, libmail, ftplib should be revised and become part of
+opienet eventually.
+
+[-----------]
+[ opiepim ]
+[-----------]
+Nothing here yet. The stuff currently in libopie/pim should be here.
+
+[-----------]
+[ opieui ]
+[-----------]
+Pretty messy yet, but some things are usable. Unfortunately, the UI
+stuff is very hard to backport to Qt2, so some things only work
+if compiled against Qt3, especially all the popupcompletion stuff.
+OListView however works nice and is currently used in opie-wellenreiter.
+
+==================================================================
+October 2002 - Started work on cornucopia aka opielib2
+================================================================== \ No newline at end of file
diff --git a/libopie2/config.in b/libopie2/config.in
new file mode 100644
index 0000000..7c4d9bb
--- a/dev/null
+++ b/libopie2/config.in
@@ -0,0 +1,10 @@
+menu "libopie2"
+ source libopie2/opiecore/config.in
+ source libopie2/opiedb/config.in
+ source libopie2/opienet/config.in
+ source libopie2/opiepim/config.in
+ source libopie2/opieui/config.in
+ comment ""
+ source libopie2/examples/config.in
+endmenu
+
diff --git a/libopie2/examples/.cvsignore b/libopie2/examples/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/examples/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/examples/config.in b/libopie2/examples/config.in
new file mode 100644
index 0000000..d18e479
--- a/dev/null
+++ b/libopie2/examples/config.in
@@ -0,0 +1,6 @@
+ config LIBOPIE2EXAMPLES
+ boolean "libopie2 examples"
+ default "n"
+ depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE && LIBOPIE2NET && LIBOPIE2UI && LIBOPIE2PIM && LIBOPIE2UI
+ comment "the examples need a libqpe, libopie2core, libopie2db, libopie2net, libopie2pim and libopie2ui"
+ depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE && LIBOPIE2NET && LIBOPIE2UI && LIBOPIE2PIM && LIBOPIE2UI)
diff --git a/libopie2/examples/examples.pro b/libopie2/examples/examples.pro
new file mode 100644
index 0000000..2ae7eb7
--- a/dev/null
+++ b/libopie2/examples/examples.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+unix:SUBDIRS = opieui opienet opiecore
+
+#include ( ../../../include.pro )
diff --git a/libopie2/examples/opiecore/.cvsignore b/libopie2/examples/opiecore/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/examples/opiecore/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/examples/opiecore/oconfigdemo/.cvsignore b/libopie2/examples/opiecore/oconfigdemo/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/examples/opiecore/oconfigdemo/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/examples/opiecore/oconfigdemo/oconfigdemo.cpp b/libopie2/examples/opiecore/oconfigdemo/oconfigdemo.cpp
new file mode 100644
index 0000000..a3f8e10
--- a/dev/null
+++ b/libopie2/examples/opiecore/oconfigdemo/oconfigdemo.cpp
@@ -0,0 +1,31 @@
+#include <opie2/oapplication.h>
+#include <opie2/oconfig.h>
+#include <qpe/config.h>
+
+int main( int argc, char** argv )
+{
+ OApplication* app = new OApplication( argc, argv, "MyConfigDemoApplication" );
+
+ OConfigGroupSaver c1( app->config(), "MyGroup" );
+ app->config()->writeEntry( "AnEntry", "InMyGroup" );
+ {
+ OConfigGroupSaver c2( c1.config(), "AnotherGroup" );
+ app->config()->writeEntry( "AnEntry", "InAnotherGroup" );
+ } // closing the scope returns to the last group
+
+ app->config()->writeEntry( "AnotherEntry", "InMyGroup" );
+
+ // do more stuff ...
+
+ // in this (special) case it is necessary to manually call OConfig::write() (see below)
+ app->config()->write();
+
+ // can't delete the app when using the OConfigGroupSaver on top level scope,
+ // because the destructor of the OConfigGroupSaver needs an application object
+ //delete app; // destructor deletes config which writes changes back to disk
+
+ return 0;
+
+}
+
+//#include "moc/oconfigdemo.moc"
diff --git a/libopie2/examples/opiecore/oconfigdemo/oconfigdemo.pro b/libopie2/examples/opiecore/oconfigdemo/oconfigdemo.pro
new file mode 100644
index 0000000..0109c57
--- a/dev/null
+++ b/libopie2/examples/opiecore/oconfigdemo/oconfigdemo.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+CONFIG = qt warn_on debug
+HEADERS =
+SOURCES = oconfigdemo.cpp
+
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+LIBS += -lopiecore2
+TARGET = oconfigdemo
+MOC_DIR = moc
+OBJECTS_DIR = obj
+
+include ( $(OPIEDIR)/include.pro )
+
diff --git a/libopie2/examples/opiecore/odebugdemo/.cvsignore b/libopie2/examples/opiecore/odebugdemo/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/examples/opiecore/odebugdemo/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/examples/opiecore/odebugdemo/odebugdemo.cpp b/libopie2/examples/opiecore/odebugdemo/odebugdemo.cpp
new file mode 100644
index 0000000..74886fa
--- a/dev/null
+++ b/libopie2/examples/opiecore/odebugdemo/odebugdemo.cpp
@@ -0,0 +1,138 @@
+/* QT */
+
+#include <qvbox.h>
+#include <qhbox.h>
+#include <qvbuttongroup.h>
+#include <qhbuttongroup.h>
+#include <qlineedit.h>
+#include <qradiobutton.h>
+#include <qpushbutton.h>
+
+/* OPIE */
+
+#include <qpe/config.h>
+
+#include <opie2/odebug.h>
+#include <opie2/oapplication.h>
+#include <opie2/oglobal.h>
+#include <opie2/oglobalsettings.h>
+
+class DemoApp : public OApplication
+{
+Q_OBJECT
+public:
+ DemoApp( int argc, char** argv ) : OApplication( argc, argv, "libopie2 debug demo" )
+ {
+ // you have access to your OApplication object via oApp
+ qDebug( "Process-wide OApplication object @ %0x", oApp );
+
+ // you have access to global settings via OGlobalSettings
+ int mode = OGlobalSettings::debugMode();
+
+ QVBox* vbox = new QVBox();
+ setMainWidget( vbox );
+
+ g = new QVButtonGroup( "Output Strategy", vbox );
+ QRadioButton* r0 = new QRadioButton( "file", g );
+ QRadioButton* r1 = new QRadioButton( "messagebox", g );
+ QRadioButton* r2 = new QRadioButton( "stderr", g );
+ QRadioButton* r3 = new QRadioButton( "syslog", g );
+ QRadioButton* r4 = new QRadioButton( "socket", g );
+ g->insert( r0, 0 );
+ g->insert( r1, 1 );
+ g->insert( r2, 2 );
+ g->insert( r3, 3 );
+ g->insert( r4, 4 );
+ g->setRadioButtonExclusive( true );
+ connect( g, SIGNAL( clicked(int) ), this, SLOT( chooseMethod(int) ) );
+
+ if ( mode != -1 ) g->setButton( mode );
+
+ QHButtonGroup* hbox = new QHButtonGroup( "Extra Output Information", vbox );
+ e = new QLineEdit( hbox );
+ QPushButton* pb = new QPushButton( hbox );
+
+ connect( e, SIGNAL( returnPressed() ), this, SLOT( updateDebugOutput() ) );
+ connect( pb, SIGNAL( clicked() ), this, SLOT( updateDebugOutput() ) );
+
+ // show the additional debug mode dependent output information
+ e->setText( OGlobalSettings::debugOutput() );
+
+ // buttos
+ QPushButton* info = new QPushButton( "Emit Debug(Info) Output!", vbox );
+ connect( info, SIGNAL( clicked() ), this, SLOT( emitInfoOutput() ) );
+ QPushButton* warn = new QPushButton( "Emit a Warning Output!", vbox );
+ connect( warn, SIGNAL( clicked() ), this, SLOT( emitWarningOutput() ) );
+ QPushButton* error = new QPushButton( "Emit an Error Output!", vbox );
+ connect( error, SIGNAL( clicked() ), this, SLOT( emitErrorOutput() ) );
+ QPushButton* fatal = new QPushButton( "Emit a Fatal Output!", vbox );
+ connect( fatal, SIGNAL( clicked() ), this, SLOT( emitFatalOutput() ) );
+
+ QPushButton* tb = new QPushButton( "Emit a Fatal Backtrace!", vbox );
+ connect( tb, SIGNAL( clicked() ), this, SLOT( emitTBOutput() ) );
+
+ info->show();
+ warn->show();
+ error->show();
+ fatal->show();
+ tb->show();
+ g->show();
+ hbox->show();
+ e->show();
+ vbox->show();
+ showMainWidget( vbox );
+ }
+
+public slots:
+ void chooseMethod(int method)
+ {
+ m = method;
+ qDebug( "choosing method: %d", method );
+ OConfig* g = OGlobal::config();
+ g->setGroup( "General" );
+ g->writeEntry( "debugMode", m );
+ e->setText( OGlobalSettings::debugOutput() );
+ }
+ void updateDebugOutput()
+ {
+ OConfig* g = OGlobal::config();
+ g->setGroup( "General" );
+ g->writeEntry( "debugOutput"+QString::number(OGlobalSettings::debugMode()), e->text() );
+ }
+ void emitInfoOutput()
+ {
+ odebug << "This is a debug message" << oendl;
+ }
+ void emitWarningOutput()
+ {
+ owarn << "This is a warning message" << oendl;
+ }
+ void emitErrorOutput()
+ {
+ oerr << "This is an errror message" << oendl;
+ }
+ void emitFatalOutput()
+ {
+ ofatal << "This is a fatal message" << oendl;
+ }
+ void emitTBOutput()
+ {
+ ofatal << "This is a fatal message + backtrace\n" + odBacktrace(); // odBacktrace includes \n
+ }
+
+private:
+ QButtonGroup* g;
+ int m;
+ QLineEdit* e;
+};
+
+int main( int argc, char** argv )
+{
+ DemoApp* app = new DemoApp( argc, argv );
+ app->exec();
+
+ return 0;
+
+}
+
+#include "moc/odebugdemo.moc"
diff --git a/libopie2/examples/opiecore/odebugdemo/odebugdemo.pro b/libopie2/examples/opiecore/odebugdemo/odebugdemo.pro
new file mode 100644
index 0000000..a725105
--- a/dev/null
+++ b/libopie2/examples/opiecore/odebugdemo/odebugdemo.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+CONFIG = qt warn_on debug
+HEADERS =
+SOURCES = odebugdemo.cpp
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+LIBS += -lopiecore2
+TARGET = odebugdemo
+MOC_DIR = moc
+OBJECTS_DIR = obj
+
+include ( $(OPIEDIR)/include.pro )
+
+
diff --git a/libopie2/examples/opiecore/oglobalsettingsdemo/.cvsignore b/libopie2/examples/opiecore/oglobalsettingsdemo/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/examples/opiecore/oglobalsettingsdemo/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/examples/opiecore/oglobalsettingsdemo/oglobalsettingsdemo.cpp b/libopie2/examples/opiecore/oglobalsettingsdemo/oglobalsettingsdemo.cpp
new file mode 100644
index 0000000..2f5220b
--- a/dev/null
+++ b/libopie2/examples/opiecore/oglobalsettingsdemo/oglobalsettingsdemo.cpp
@@ -0,0 +1,13 @@
+#include <opie2/oglobalsettings.h>
+#include <iostream.h>
+
+int main( int argc, char** argv )
+{
+ printf( "current debugmode seems to be '%d'\n", OGlobalSettings::debugMode() );
+ printf( "output information for this mode is '%s'\n", (const char*) OGlobalSettings::debugOutput() );
+
+ return 0;
+
+}
+
+//#include "moc/oconfigdemo.moc"
diff --git a/libopie2/examples/opiecore/oglobalsettingsdemo/oglobalsettingsdemo.pro b/libopie2/examples/opiecore/oglobalsettingsdemo/oglobalsettingsdemo.pro
new file mode 100644
index 0000000..7fbecce
--- a/dev/null
+++ b/libopie2/examples/opiecore/oglobalsettingsdemo/oglobalsettingsdemo.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+CONFIG = qt warn_on debug
+HEADERS =
+SOURCES = oglobalsettingsdemo.cpp
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+LIBS += -lopiecore2
+TARGET = oglobalsettingsdemo
+MOC_DIR = moc
+OBJECTS_DIR = obj
+
+include ( $(OPIEDIR)/include.pro )
+
+
diff --git a/libopie2/examples/opiecore/opiecore.pro b/libopie2/examples/opiecore/opiecore.pro
new file mode 100644
index 0000000..8f3aedc
--- a/dev/null
+++ b/libopie2/examples/opiecore/opiecore.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+unix:SUBDIRS = odebugdemo oconfigdemo oglobalsettingsdemo
+
diff --git a/libopie2/examples/opienet/.cvsignore b/libopie2/examples/opienet/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/examples/opienet/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/examples/opienet/miniwellenreiter/.cvsignore b/libopie2/examples/opienet/miniwellenreiter/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/examples/opienet/miniwellenreiter/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/examples/opienet/miniwellenreiter/miniwellenreiter.cpp b/libopie2/examples/opienet/miniwellenreiter/miniwellenreiter.cpp
new file mode 100644
index 0000000..aec9cc7
--- a/dev/null
+++ b/libopie2/examples/opienet/miniwellenreiter/miniwellenreiter.cpp
@@ -0,0 +1,199 @@
+#include <qdict.h>
+#include <qsocketnotifier.h>
+#include <qstring.h>
+#include <opie2/onetwork.h>
+#include <qapplication.h>
+#include <opie2/opcap.h>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+//======================== Station help class ===============================
+
+class Station
+{
+ public:
+ Station( QString t, int c, bool w ) : type(t), channel(c), wep(w), beacons(1) {};
+ ~Station() {};
+
+ QString type;
+ int channel;
+ bool wep;
+ int beacons;
+};
+
+QDict<Station> stations;
+
+//======================== Application class ===============================
+
+class Wellenreiter : public QApplication
+{
+Q_OBJECT
+public:
+ Wellenreiter( int argc, char** argv ) : QApplication( argc, argv )
+ {
+
+ ONetwork* net = ONetwork::instance();
+
+ if ( argc < 3 )
+ {
+ printf( "Usage: ./%s <interface> <driver> <interval>\n", argv[0] );
+ printf( "\n" );
+ printf( "Valid wireless interfaces (detected) are:\n" );
+
+ ONetwork::InterfaceIterator it = net->iterator();
+ while ( it.current() )
+ {
+ if ( it.current()->isWireless() )
+ {
+ printf( " - '%s' (MAC=%s) (IPv4=%s)\n", (const char*) it.current()->name(),
+ (const char*) it.current()->macAddress().toString(),
+ (const char*) it.current()->ipV4Address() );
+ }
+ ++it;
+ }
+ exit( -1 );
+ }
+
+ printf( "****************************************************\n" );
+ printf( "* Wellenreiter mini edition 1.0 (C) 2003 M-M-M *\n" );
+ printf( "****************************************************\n" );
+ printf( "\n\n" );
+
+ QString interface( argv[1] );
+ QString driver( argv[2] );
+
+ printf( "Trying to use '%s' as %s-controlled device...\n", (const char*) interface, (const char*) driver );
+
+ // sanity checks before downcasting
+ ONetworkInterface* iface = net->interface( interface );
+ if ( !iface )
+ {
+ printf( "Interface '%s' doesn't exist. Exiting.\n", (const char*) interface );
+ exit( -1 );
+ }
+ if ( !iface->isWireless() )
+ {
+ printf( "Interface '%s' doesn't support wireless extensions. Exiting.\n", (const char*) interface );
+ exit( -1 );
+ }
+
+ // downcast should be safe now
+ wiface = (OWirelessNetworkInterface*) iface;
+ printf( "Using wireless interface '%s' for scanning (current SSID is '%s')...\n", (const char*) interface, (const char*) wiface->SSID() );
+
+ /*
+
+ // ifconfig down the interface - this enable more crash-proof
+ // scanning with drivers like spectrum_cs...
+ if ( wiface->isUp() )
+ {
+ printf( "Interface status is up... switching to down... " );
+ wiface->setUp( false );
+ if ( wiface->isUp() )
+ {
+ printf( "failed (%s). Exiting.\n", strerror( errno ) );
+ exit( -1 );
+ }
+ else
+ {
+ printf( "ok.\n" );
+ }
+ }
+ else
+ printf( "Interface status is already down - good.\n" );
+
+ */
+
+ // ifconfig +promisc the interface to receive all packets
+ if ( !wiface->promiscuousMode() )
+ {
+ printf( "Interface status is not promisc... switching to promisc... " );
+ wiface->setPromiscuousMode( true );
+ if ( !wiface->promiscuousMode() )
+ {
+ printf( "failed (%s). Exiting.\n", strerror( errno ) );
+ exit( -1 );
+ }
+ else
+ {
+ printf( "ok.\n" );
+ }
+ }
+ else
+ printf( "Interface status is already promisc - good.\n" );
+
+ // connect a monitoring strategy to the interface
+ if ( driver == "orinoco" )
+ new OOrinocoMonitoringInterface( wiface );
+ else
+ {
+ printf( "Unknown driver. Exiting\n" );
+ exit( -1 );
+ }
+
+ // enable monitoring mode
+ printf( "Enabling monitor mode...\n" );
+ wiface->setMonitorMode( true );
+
+ // open a packet capturer
+ cap = new OPacketCapturer();
+ cap->open( interface );
+ if ( !cap->isOpen() )
+ {
+ printf( "Unable to open libpcap (%s). Exiting.\n", strerror( errno ) );
+ exit( -1 );
+ }
+
+ // set capturer to non-blocking mode
+ cap->setBlocking( false );
+
+ // start channel hopper
+ wiface->setChannelHopping( 1000 );
+
+ // connect
+ connect( cap, SIGNAL( receivedPacket(OPacket*) ), this, SLOT( receivePacket(OPacket*) ) );
+
+ }
+
+ ~Wellenreiter() {};
+
+public slots:
+ void receivePacket(OPacket* p)
+ {
+ if (!p)
+ {
+ printf( "(empty packet received)\n" );
+ return;
+ }
+
+ OWaveLanManagementPacket* beacon = (OWaveLanManagementPacket*) p->child( "802.11 Management" );
+
+ if ( beacon )
+ {
+ if ( stations.find( beacon->SSID() ) )
+ stations[beacon->SSID()]->beacons++;
+ else
+ {
+ printf( "found new network @ channel %d, SSID = '%s'\n", wiface->channel(), (const char*) beacon->SSID() );
+ stations.insert( beacon->SSID(), new Station( "unknown", wiface->channel(),
+ ((OWaveLanPacket*) beacon->parent())->usesWep() ) );
+ }
+ }
+ }
+private:
+ OPacketCapturer* cap;
+ OWirelessNetworkInterface* wiface;
+};
+
+
+int main( int argc, char** argv )
+{
+ Wellenreiter w( argc, argv );
+ w.exec();
+ return 0;
+}
+
+#include "miniwellenreiter.moc"
+
diff --git a/libopie2/examples/opienet/miniwellenreiter/miniwellenreiter.pro b/libopie2/examples/opienet/miniwellenreiter/miniwellenreiter.pro
new file mode 100644
index 0000000..7ce535c
--- a/dev/null
+++ b/libopie2/examples/opienet/miniwellenreiter/miniwellenreiter.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+CONFIG = qt warn_on debug
+HEADERS =
+SOURCES = miniwellenreiter.cpp
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+LIBS += -lopiecore2 -lopienet2
+TARGET = miniwellenreiter
+MOC_DIR = moc
+OBJECTS_DIR = obj
+
+include ( $(OPIEDIR)/include.pro )
+
diff --git a/libopie2/examples/opienet/onetworkdemo/.cvsignore b/libopie2/examples/opienet/onetworkdemo/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/examples/opienet/onetworkdemo/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/examples/opienet/onetworkdemo/onetworkdemo.cpp b/libopie2/examples/opienet/onetworkdemo/onetworkdemo.cpp
new file mode 100644
index 0000000..7703b4c
--- a/dev/null
+++ b/libopie2/examples/opienet/onetworkdemo/onetworkdemo.cpp
@@ -0,0 +1,35 @@
+#include <opie2/onetwork.h>
+
+int main( int argc, char** argv )
+{
+ qDebug( "OPIE Network Demo" );
+
+ ONetwork* net = ONetwork::instance();
+
+ ONetwork::InterfaceIterator it = net->iterator();
+
+ while ( it.current() )
+ {
+ qDebug( "DEMO: ONetwork contains Interface '%s'", (const char*) it.current()->name() );
+ qDebug( "DEMO: MAC Address is '%s'", (const char*) it.current()->macAddress().toString() );
+ qDebug( "Demo: IPv4 Address is '%s'", (const char*) it.current()->ipV4Address() );
+ if ( it.current()->isWireless() )
+ {
+ OWirelessNetworkInterface* iface = static_cast<OWirelessNetworkInterface*>( it.current() );
+ qDebug( "DEMO: '%s' seems to feature the wireless extensions.", (const char*) iface->name() );
+ qDebug( "DEMO: Current SSID is '%s'", (const char*) iface->SSID() );
+ qDebug( "DEMO: Current NickName is '%s'", (const char*) iface->nickName() );
+ qDebug( "DEMO: Antenna is tuned to '%f', that is channel %d", iface->frequency(), iface->channel() );
+
+ //if ( iface->mode() == OWirelessNetworkInterface::adhoc )
+ //{
+ qDebug( "DEMO: Associated AP has MAC Address '%s'", (const char*) iface->associatedAP() );
+ //}
+
+ }
+ ++it;
+ }
+
+ return 0;
+
+}
diff --git a/libopie2/examples/opienet/onetworkdemo/onetworkdemo.pro b/libopie2/examples/opienet/onetworkdemo/onetworkdemo.pro
new file mode 100644
index 0000000..2d71aa0
--- a/dev/null
+++ b/libopie2/examples/opienet/onetworkdemo/onetworkdemo.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+CONFIG = qt warn_on debug
+HEADERS =
+SOURCES = onetworkdemo.cpp
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+LIBS += -lopiecore2 -lopienet2
+TARGET = onetworkdemo
+MOC_DIR = moc
+OBJECTS_DIR = obj
+
+include ( $(OPIEDIR)/include.pro )
diff --git a/libopie2/examples/opienet/opienet.pro b/libopie2/examples/opienet/opienet.pro
new file mode 100644
index 0000000..c7800a9
--- a/dev/null
+++ b/libopie2/examples/opienet/opienet.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS = miniwellenreiter onetworkdemo
+
diff --git a/libopie2/examples/opieui/.cvsignore b/libopie2/examples/opieui/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/examples/opieui/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/examples/opieui/oversatileviewdemo/1.png b/libopie2/examples/opieui/oversatileviewdemo/1.png
new file mode 100644
index 0000000..0e2e41b
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/1.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/1small.png b/libopie2/examples/opieui/oversatileviewdemo/1small.png
new file mode 100644
index 0000000..ce6b262
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/1small.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/2.png b/libopie2/examples/opieui/oversatileviewdemo/2.png
new file mode 100644
index 0000000..8a0181d
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/2.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/2small.png b/libopie2/examples/opieui/oversatileviewdemo/2small.png
new file mode 100644
index 0000000..82a4431
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/2small.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/3.png b/libopie2/examples/opieui/oversatileviewdemo/3.png
new file mode 100644
index 0000000..8a58d6c
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/3.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/3small.png b/libopie2/examples/opieui/oversatileviewdemo/3small.png
new file mode 100644
index 0000000..073ba55
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/3small.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/4.png b/libopie2/examples/opieui/oversatileviewdemo/4.png
new file mode 100644
index 0000000..198891b
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/4.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/4small.png b/libopie2/examples/opieui/oversatileviewdemo/4small.png
new file mode 100644
index 0000000..7f1cc01
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/4small.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/5.png b/libopie2/examples/opieui/oversatileviewdemo/5.png
new file mode 100644
index 0000000..ee7344a
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/5.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/5small.png b/libopie2/examples/opieui/oversatileviewdemo/5small.png
new file mode 100644
index 0000000..105b038
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/5small.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/6.png b/libopie2/examples/opieui/oversatileviewdemo/6.png
new file mode 100644
index 0000000..72c3692
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/6.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/6small.png b/libopie2/examples/opieui/oversatileviewdemo/6small.png
new file mode 100644
index 0000000..1db2a30
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/6small.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/folder_closed.png b/libopie2/examples/opieui/oversatileviewdemo/folder_closed.png
new file mode 100644
index 0000000..4157333
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/folder_closed.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/folder_closed32.png b/libopie2/examples/opieui/oversatileviewdemo/folder_closed32.png
new file mode 100644
index 0000000..acc992c
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/folder_closed32.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/folder_opened.png b/libopie2/examples/opieui/oversatileviewdemo/folder_opened.png
new file mode 100644
index 0000000..5e7e37e
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/folder_opened.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/folder_opened32.png b/libopie2/examples/opieui/oversatileviewdemo/folder_opened32.png
new file mode 100644
index 0000000..acd3265
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/folder_opened32.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/leaf.png b/libopie2/examples/opieui/oversatileviewdemo/leaf.png
new file mode 100644
index 0000000..c8435ec
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/leaf.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/leaf32.png b/libopie2/examples/opieui/oversatileviewdemo/leaf32.png
new file mode 100644
index 0000000..5e90ead
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/leaf32.png
Binary files differ
diff --git a/libopie2/examples/opieui/oversatileviewdemo/main.cpp b/libopie2/examples/opieui/oversatileviewdemo/main.cpp
new file mode 100644
index 0000000..d8c01a4
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/main.cpp
@@ -0,0 +1,29 @@
+/**********************************************************************
+** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved.
+**
+** This file is part of Opie Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+**********************************************************************/
+
+#include "opieuidemo.h"
+
+#include <opie2/oapplication.h>
+
+int main( int argc, char **argv )
+{
+ OApplication a( argc, argv, "Opie UI Demo" );
+ qDebug( "." );
+ OpieUIDemo e;
+ qDebug( "." );
+ a.showMainWidget(&e);
+ qDebug( "." );
+ return a.exec();
+}
diff --git a/libopie2/examples/opieui/oversatileviewdemo/opieui.pro b/libopie2/examples/opieui/oversatileviewdemo/opieui.pro
new file mode 100644
index 0000000..8ad5fc9
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/opieui.pro
@@ -0,0 +1,17 @@
+TEMPLATE = app
+CONFIG = qt warn_on debug
+HEADERS = opieuidemo.h \
+ oversatileviewdemo.h
+SOURCES = opieuidemo.cpp \
+ oversatileviewdemo.cpp \
+ main.cpp
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+LIBS += -lopieui2 -lopiecore2
+TARGET = opieuidemo
+MOC_DIR = moc
+OBJECTS_DIR = obj
+
+include ( $(OPIEDIR)/include.pro )
+
+
diff --git a/libopie2/examples/opieui/oversatileviewdemo/opieuidemo.cpp b/libopie2/examples/opieui/oversatileviewdemo/opieuidemo.cpp
new file mode 100644
index 0000000..197669c
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/opieuidemo.cpp
@@ -0,0 +1,205 @@
+/**********************************************************************
+** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved.
+**
+** This file is part of Opie Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+***********************************************************************/
+
+// Qt
+
+#include <qcolor.h>
+#include <qpopupmenu.h>
+#include <qmenubar.h>
+#include <qmessagebox.h>
+#include <qvbox.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+// Qtopia
+
+#ifdef QWS
+#include <qpe/qpeapplication.h>
+#include <qpe/global.h>
+#endif
+
+// Opie
+
+#ifdef QWS
+#include <opie/odevice.h>
+using namespace Opie;
+#endif
+
+#include <opie2/ocompletionbox.h>
+#include <opie2/olineedit.h>
+#include <opie2/ocombobox.h>
+#include <opie2/oeditlistbox.h>
+#include <opie2/oselector.h>
+#include <opie2/opopupmenu.h>
+
+#include <qtabwidget.h>
+#include "oversatileviewdemo.h"
+
+// Local
+
+#include "opieuidemo.h"
+
+enum Demos { ocompletionbox, olineedit, ocombobox, oeditlistbox, oselector };
+
+OpieUIDemo::OpieUIDemo( QWidget* parent, const char* name, WFlags fl )
+ : QMainWindow( parent, name, fl )
+{
+
+ QMenuBar* mbar = this->menuBar();
+ OPopupMenu* demo = new OPopupMenu( this );
+ demo->setTitle( "Title" );
+ demo->setItemParameter( demo->insertItem( "OCompletionBox", this, SLOT( demo(int) ) ), ocompletionbox );
+ demo->setItemParameter( demo->insertItem( "OLineEdit", this, SLOT( demo(int) ) ), olineedit );
+ demo->setItemParameter( demo->insertItem( "OComboBox", this, SLOT( demo(int) ) ), ocombobox );
+ demo->setItemParameter( demo->insertItem( "OEditListBox", this, SLOT( demo(int) ) ), oeditlistbox );
+ demo->setItemParameter( demo->insertItem( "OSelector", this, SLOT( demo(int) ) ), oselector );
+ mbar->insertItem( "Demonstrate", demo );
+
+ build();
+
+}
+
+OpieUIDemo::~OpieUIDemo()
+{
+}
+
+void OpieUIDemo::build()
+{
+ main = new QTabWidget( this, "tabwidget" );
+ setCentralWidget( main );
+ main->show();
+
+ main->addTab( new OVersatileViewDemo( main ), "VersatileView" );
+}
+
+
+void OpieUIDemo::demo( int d )
+{
+ switch (d)
+ {
+ case ocompletionbox: demoOCompletionBox(); break;
+ case olineedit: demoOLineEdit(); break;
+ case ocombobox: demoOComboBox(); break;
+ case oeditlistbox: demoOEditListBox(); break;
+ case oselector: demoOSelector(); break;
+
+ }
+
+}
+
+void OpieUIDemo::demoOCompletionBox()
+{
+ qDebug( "ocompletionbox" );
+
+ OCompletionBox* box = new OCompletionBox( 0 );
+ box->insertItem( "This CompletionBox" );
+ box->insertItem( "Says 'Hello World'" );
+ box->insertItem( "Here are some" );
+ box->insertItem( "Additional Items" );
+ box->insertItem( "Complete Completion Box" );
+
+ connect( box, SIGNAL( activated( const QString& ) ), this, SLOT( messageBox( const QString& ) ) );
+ box->popup();
+
+}
+
+void OpieUIDemo::demoOLineEdit()
+{
+ qDebug( "olineedit" );
+
+ OLineEdit *edit = new OLineEdit( 0, "lineedit" );
+
+ edit->setCompletionMode( OGlobalSettings::CompletionPopup );
+ OCompletion* comp = edit->completionObject();
+
+ QStringList list;
+ list << "mickeyl@handhelds.org";
+ list << "mickey@tm.informatik.uni-frankfurt.de";
+ list << "mickey@vanille.de";
+
+ comp->setItems( list );
+
+ edit->show();
+
+}
+
+void OpieUIDemo::demoOComboBox()
+{
+ qDebug( "ocombobox" );
+
+ OComboBox *combo = new OComboBox( true, 0, "combobox" );
+
+ combo->setCompletionMode( OGlobalSettings::CompletionPopup );
+ OCompletion* comp = combo->completionObject();
+
+ QStringList ilist;
+ ilist << "kergoth@handhelds.org";
+ ilist << "harlekin@handhelds.org";
+ ilist << "groucho@handhelds.org";
+ combo->insertStringList( ilist );
+
+ QStringList clist;
+ clist << "mickeyl@handhelds.org";
+ clist << "mickey@tm.informatik.uni-frankfurt.de";
+ clist << "mickey@vanille.de";
+ comp->setItems( clist );
+
+ combo->show();
+
+}
+
+void OpieUIDemo::demoOEditListBox()
+{
+ qDebug( "oeditlistbox" );
+
+ OEditListBox* edit = new OEditListBox( "OEditListBox", 0, "editlistbox" );
+
+ edit->lineEdit()->setCompletionMode( OGlobalSettings::CompletionPopup );
+ OCompletion* comp = edit->lineEdit()->completionObject();
+ QStringList clist;
+ clist << "Completion everywhere";
+ clist << "Cool Completion everywhere";
+ clist << "History History History";
+ comp->setItems( clist );
+
+ QStringList list;
+ list << "kergoth@handhelds.org";
+ list << "harlekin@handhelds.org";
+ list << "groucho@handhelds.org";
+ list << "mickeyl@handhelds.org";
+ edit->insertStringList( list );
+
+ edit->show();
+
+}
+
+void OpieUIDemo::demoOSelector()
+{
+ qDebug( "oselector" );
+
+ OHSSelector* sel = new OHSSelector( 0, "gradientselector" );
+ //#sel->resize( QSize( 200, 30 ) );
+ //#sel->setColors( QColor( 90, 190, 60 ), QColor( 200, 55, 255 ) );
+ //#sel->setText( "Dark", "Light" );
+
+ sel->show();
+}
+
+void OpieUIDemo::messageBox( const QString& text )
+{
+ QString info;
+ info = "You have selected '" + text + "'";
+ QMessageBox::information( this, "OpieUIDemo", info );
+}
diff --git a/libopie2/examples/opieui/oversatileviewdemo/opieuidemo.h b/libopie2/examples/opieui/oversatileviewdemo/opieuidemo.h
new file mode 100644
index 0000000..0519ae6
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/opieuidemo.h
@@ -0,0 +1,56 @@
+/**********************************************************************
+** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved.
+**
+** This file is part of Opie Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+**********************************************************************/
+
+#ifndef OPIEUIDEMO_H
+#define OPIEUIDEMO_H
+
+#include <qmainwindow.h>
+
+class OVersatileView;
+class QTabWidget;
+class QVBox;
+
+class OpieUIDemo : public QMainWindow {
+ Q_OBJECT
+
+public:
+
+ OpieUIDemo( QWidget* parent = 0, const char* name = 0, WFlags fl = WType_TopLevel );
+ ~OpieUIDemo();
+
+ void demoOCompletionBox();
+ void demoOLineEdit();
+ void demoOComboBox();
+ void demoOEditListBox();
+ void demoOSelector();
+
+public slots:
+ void demo( int );
+ void messageBox( const QString& text );
+
+protected:
+ void build();
+ void buildVV( QVBox* b );
+
+private:
+ QTabWidget* main;
+
+ OVersatileView* vv;
+
+};
+
+
+
+#endif
diff --git a/libopie2/examples/opieui/oversatileviewdemo/oversatileviewdemo.cpp b/libopie2/examples/opieui/oversatileviewdemo/oversatileviewdemo.cpp
new file mode 100644
index 0000000..cf1e443
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/oversatileviewdemo.cpp
@@ -0,0 +1,158 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael 'Mickey' Lauer
+ <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include "oversatileviewdemo.h"
+#include <opie2/oversatileview.h>
+#include <opie2/oversatileviewitem.h>
+
+#include <qstring.h>
+#include <qpixmap.h>
+#include <qlistview.h>
+
+OVersatileViewDemo::OVersatileViewDemo( QWidget* parent, const char* name, WFlags f )
+ :QVBox( parent, name, f )
+{
+ vv = new OVersatileView( this );
+
+ vv->addColumn( "First" );
+ vv->addColumn( "2nd" );
+ vv->addColumn( "IIIrd" );
+
+ QString counter;
+
+ QPixmap leaf( "leaf.png" );
+ QPixmap opened( "folder_opened.png" );
+ QPixmap closed( "folder_closed.png" );
+
+ QPixmap leaf32( "leaf32.png" );
+ QPixmap opened32( "folder_opened32.png" );
+ QPixmap closed32( "folder_closed32.png" );
+
+ vv->setDefaultPixmaps( OVersatileView::Tree, leaf, opened, closed );
+ vv->setDefaultPixmaps( OVersatileView::Icons, leaf32, opened32, closed32 );
+
+ OVersatileViewItem* item;
+ OVersatileViewItem* item2;
+
+ for ( int i = 0; i < 5; ++i )
+ {
+ counter.sprintf( "%d", i );
+ item = new OVersatileViewItem( vv, "Item", "Text", "Some more", counter );
+ item->setRenameEnabled( true );
+ item2 = new OVersatileViewItem( item, "OSubitem", "123", "...", counter );
+ item2->setRenameEnabled( true );
+
+ }
+
+ connect( vv, SIGNAL( selectionChanged() ), this, SLOT( selectionChanged() ) );
+ connect( vv, SIGNAL( selectionChanged( OVersatileViewItem * ) ), this, SLOT( selectionChanged( OVersatileViewItem * ) ) );
+ connect( vv, SIGNAL( currentChanged( OVersatileViewItem * ) ), this, SLOT( currentChanged( OVersatileViewItem * ) ) );
+ connect( vv, SIGNAL( clicked( OVersatileViewItem * ) ), this, SLOT( clicked( OVersatileViewItem * ) ) );
+ connect( vv, SIGNAL( pressed( OVersatileViewItem * ) ), this, SLOT( pressed( OVersatileViewItem * ) ) );
+
+ connect( vv, SIGNAL( doubleClicked( OVersatileViewItem * ) ), this, SLOT( doubleClicked( OVersatileViewItem * ) ) );
+ connect( vv, SIGNAL( returnPressed( OVersatileViewItem * ) ), this, SLOT( returnPressed( OVersatileViewItem * ) ) );
+
+ connect( vv, SIGNAL( onItem( OVersatileViewItem * ) ), this, SLOT( onItem( OVersatileViewItem * ) ) );
+ connect( vv, SIGNAL( onViewport() ), this, SLOT( onViewport() ) );
+
+ connect( vv, SIGNAL( expanded( OVersatileViewItem * ) ), this, SLOT( expanded( OVersatileViewItem * ) ) );
+ connect( vv, SIGNAL( collapsed( OVersatileViewItem * ) ), this, SLOT( collapsed( OVersatileViewItem * ) ) );
+
+ connect( vv, SIGNAL( moved() ), this, SLOT( moved() ) );
+
+ connect( vv, SIGNAL( contextMenuRequested( OVersatileViewItem *, const QPoint&, int ) ), this, SLOT( contextMenuRequested( OVersatileViewItem *, const QPoint&, int ) ) );
+
+}
+
+OVersatileViewDemo::~OVersatileViewDemo()
+{
+}
+
+void OVersatileViewDemo::selectionChanged()
+{
+ qDebug( "received signal selectionChanged()" );
+}
+void OVersatileViewDemo::selectionChanged( OVersatileViewItem * item )
+{
+ qDebug( "received signal selectionChanged(OVersatileViewItem*)" );
+}
+void OVersatileViewDemo::currentChanged( OVersatileViewItem * item )
+{
+ qDebug( "received signal currentChanged( OVersatileViewItem * )" );
+}
+void OVersatileViewDemo::clicked( OVersatileViewItem * item )
+{
+ qDebug( "received signal clicked( OVersatileViewItem * )" );
+}
+void OVersatileViewDemo::pressed( OVersatileViewItem * item )
+{
+ qDebug( "received signal pressed( OVersatileViewItem * )" );
+}
+
+void OVersatileViewDemo::doubleClicked( OVersatileViewItem *item )
+{
+ qDebug( "received signal doubleClicked( OVersatileViewItem *item )" );
+}
+void OVersatileViewDemo::returnPressed( OVersatileViewItem *item )
+{
+ qDebug( "received signal returnPressed( OVersatileViewItem *item )" );
+}
+
+void OVersatileViewDemo::onItem( OVersatileViewItem *item )
+{
+ qDebug( "received signal onItem( OVersatileViewItem *item )" );
+}
+void OVersatileViewDemo::onViewport()
+{
+ qDebug( "received signal onViewport()" );
+}
+
+void OVersatileViewDemo::expanded( OVersatileViewItem *item )
+{
+ qDebug( "received signal expanded( OVersatileViewItem *item )" );
+}
+
+void OVersatileViewDemo::collapsed( OVersatileViewItem *item )
+{
+ qDebug( "received signal collapsed( OVersatileViewItem *item )" );
+}
+
+void OVersatileViewDemo::moved()
+{
+ qDebug( "received signal moved( OVersatileViewItem *item )" );
+}
+
+void OVersatileViewDemo::contextMenuRequested( OVersatileViewItem *item, const QPoint& pos, int col )
+{
+ qDebug( "received signal contextMenuRequested( OVersatileViewItem *item )" );
+}
diff --git a/libopie2/examples/opieui/oversatileviewdemo/oversatileviewdemo.h b/libopie2/examples/opieui/oversatileviewdemo/oversatileviewdemo.h
new file mode 100644
index 0000000..79318d0
--- a/dev/null
+++ b/libopie2/examples/opieui/oversatileviewdemo/oversatileviewdemo.h
@@ -0,0 +1,73 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OVERSATILEVIEWDEMO_H
+#define OVERSATILEVIEWDEMO_H
+
+#include <qvbox.h>
+
+class OVersatileView;
+class OVersatileViewItem;
+
+class OVersatileViewDemo: public QVBox
+{
+ Q_OBJECT
+
+ public:
+ OVersatileViewDemo( QWidget* parent=0, const char* name=0, WFlags f=0 );
+ virtual ~OVersatileViewDemo();
+
+ public slots:
+ void selectionChanged();
+ void selectionChanged( OVersatileViewItem * );
+ void currentChanged( OVersatileViewItem * );
+ void clicked( OVersatileViewItem * );
+ void pressed( OVersatileViewItem * );
+
+ void doubleClicked( OVersatileViewItem *item );
+ void returnPressed( OVersatileViewItem *item );
+
+ void onItem( OVersatileViewItem *item );
+ void onViewport();
+
+ void expanded( OVersatileViewItem *item );
+ void collapsed( OVersatileViewItem *item );
+
+ void moved();
+
+ void contextMenuRequested( OVersatileViewItem *item, const QPoint&, int col );
+
+ private:
+ OVersatileView* vv;
+
+};
+
+#endif
diff --git a/libopie2/libopie2.control b/libopie2/libopie2.control
new file mode 100644
index 0000000..eb90ab2
--- a/dev/null
+++ b/libopie2/libopie2.control
@@ -0,0 +1,10 @@
+Files: $OPIEDIR/lib/libopiecore2.so.1.8.1 $OPIEDIR/lib/libopiecore2.so.1.8 $OPIEDIR/lib/libopiecore2.so.1 $OPIEDIR/lib/libopienet2.so.1.8.1 $OPIEDIR/lib/libopienet2.so.1.8 $OPIEDIR/lib/libopienet2.so.1 $OPIEDIR/lib/libopieui2.so.1.8.1 $OPIEDIR/lib/libopieui2.so.1.8 $OPIEDIR/lib/libopieui2.so.1
+Priority: optional
+Section: opie/system
+Maintainer: Opie Team <opie@handhelds.org>
+Architecture: arm
+Version: 1.8.1
+Depends: libqpe1
+Provides: libopie2
+Replaces: libopie2
+Description: Opie library 2.0
diff --git a/libopie2/libopie2.postinst b/libopie2/libopie2.postinst
new file mode 100755
index 0000000..0c37b3d
--- a/dev/null
+++ b/libopie2/libopie2.postinst
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+[ -x /sbin/ldconfig ] && /sbin/ldconfig
+exit 0
diff --git a/libopie2/libopie2.pro b/libopie2/libopie2.pro
new file mode 100644
index 0000000..0b52abc
--- a/dev/null
+++ b/libopie2/libopie2.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+unix:SUBDIRS = opiecore opiedb opiepim opieui opienet examples
+
+include ( $(OPIEDIR)/include.pro )
diff --git a/libopie2/opiecore/.cvsignore b/libopie2/opiecore/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/opiecore/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/opiecore/config.in b/libopie2/opiecore/config.in
new file mode 100644
index 0000000..f4483a2
--- a/dev/null
+++ b/libopie2/opiecore/config.in
@@ -0,0 +1,6 @@
+ config LIBOPIE2CORE
+ boolean "libopie2core (application, configuration and debug related classes)"
+ default "n"
+ depends ( LIBQPE || LIBQPE-X11 )
+ comment "libopie2core needs a libqpe (yet)"
+ depends !( LIBQPE || LIBQPE-X11 )
diff --git a/libopie2/opiecore/oapplication.cpp b/libopie2/opiecore/oapplication.cpp
new file mode 100644
index 0000000..a0abcc2
--- a/dev/null
+++ b/libopie2/opiecore/oapplication.cpp
@@ -0,0 +1,110 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <opie2/oapplication.h>
+#include <opie2/oconfig.h>
+
+OApplication* OApplication::_instance = 0;
+
+/**************************************************************************************************/
+/* OApplicationPrivate
+/**************************************************************************************************/
+
+class OApplicationPrivate
+{
+ public:
+ OApplicationPrivate() {};
+ ~OApplicationPrivate() {};
+};
+
+/**************************************************************************************************/
+/* OApplication
+/**************************************************************************************************/
+
+
+OApplication::OApplication( int& argc, char** argv, const QCString& rAppName )
+ :OApplicationBaseClass( argc, argv ),
+ _appname( rAppName ),
+ _config( 0 )
+{
+ init();
+}
+
+
+OApplication::~OApplication()
+{
+ delete d;
+ if ( _config )
+ delete _config;
+ OApplication::_instance = 0;
+ // after deconstruction of the one-and-only application object,
+ // the construction of another object is allowed
+}
+
+
+OConfig* OApplication::config()
+{
+ if ( not _config )
+ {
+ _config = new OConfig( _appname );
+ }
+ return _config;
+}
+
+
+void OApplication::init()
+{
+ d = new OApplicationPrivate();
+ if ( !OApplication::_instance )
+ {
+ OApplication::_instance = this;
+ }
+ else
+ {
+ qFatal( "OApplication: Can't create more than one OApplication object. Aborting." );
+ }
+}
+
+void OApplication::setMainWidget( QWidget* widget )
+{
+ showMainWidget( widget );
+}
+
+void OApplication::showMainWidget( QWidget* widget, bool nomax )
+{
+ #ifdef Q_WS_QWS
+ QPEApplication::showMainWidget( widget, nomax );
+ #else
+ QApplication::setMainWidget( widget );
+ widget->show();
+ #endif
+ widget->setCaption( _appname );
+
+}
diff --git a/libopie2/opiecore/oapplication.h b/libopie2/opiecore/oapplication.h
new file mode 100644
index 0000000..736e786
--- a/dev/null
+++ b/libopie2/opiecore/oapplication.h
@@ -0,0 +1,114 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef OAPPLICATION_H
+#define OAPPLICATION_H
+
+#define oApp OApplication::oApplication()
+
+#ifdef QWS
+ #include <qpe/qpeapplication.h>
+ #define OApplicationBaseClass QPEApplication
+#else
+ #include <qapplication.h>
+ #define OApplicationBaseClass QApplication
+#endif
+
+class OApplicationPrivate;
+class OConfig;
+
+class OApplication: public OApplicationBaseClass
+{
+ public:
+
+ /**
+ * Constructor. Parses command-line arguments and sets the window caption.
+ *
+ * @param rAppName application name. Will be used for finding the
+ * associated message, icon and configuration files
+ *
+ */
+ OApplication( int& argc, char** argv, const QCString& rAppName );
+ /**
+ * Destructor. Destroys the application object and its children.
+ */
+ virtual ~OApplication();
+
+ /**
+ * Returns the current application object.
+ *
+ * This is similar to the global @ref QApplication pointer qApp. It
+ * allows access to the single global OApplication object, since
+ * more than one cannot be created in the same application. It
+ * saves you the trouble of having to pass the pointer explicitly
+ * to every function that may require it.
+ * @return the current application object
+ */
+ static const OApplication* oApplication() { return _instance; };
+
+ /**
+ * Returns the application name as given during creation.
+ *
+ * @return A reference to the application name
+ */
+ const QCString& appName() const { return _appname; };
+
+ /**
+ * Returns the application session config object.
+ *
+ * @return A pointer to the application's instance specific
+ * @ref OConfig object.
+ * @see OConfig
+ */
+ OConfig* config();
+
+ /**
+ * Sets the main widget - reimplemented to call showMainWidget()
+ * on Qt/Embedded.
+ */
+ virtual void setMainWidget( QWidget *mainWidget );
+
+ /**
+ * Shows the main widget - reimplemented to call setMainWidget()
+ * on platforms other than Qt/Embedded.
+ */
+ virtual void showMainWidget( QWidget* widget, bool nomax = false );
+
+ protected:
+ void init();
+
+ private:
+ const QCString _appname;
+ static OApplication* _instance;
+ OConfig* _config;
+ OApplicationPrivate* d;
+};
+
+#endif // OAPPLICATION_H
diff --git a/libopie2/opiecore/oconfig.cpp b/libopie2/opiecore/oconfig.cpp
new file mode 100644
index 0000000..40edbc7
--- a/dev/null
+++ b/libopie2/opiecore/oconfig.cpp
@@ -0,0 +1,201 @@
+/*
+                 This file is part of the Opie Project
+
+ (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ Inspired by the config classes from the KDE Project which are
+ =. (C) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/* QT */
+
+#include <qfont.h>
+#include <qcolor.h>
+
+/* OPIE */
+
+#include <opie2/oconfig.h>
+
+OConfig::OConfig( const QString &name, Domain domain )
+ :Config( name, domain )
+{
+}
+
+OConfig::~OConfig()
+{
+}
+
+QColor OConfig::readColorEntry( const QString& key, const QColor* pDefault ) const
+{
+ QColor aRetColor;
+ int nRed = 0, nGreen = 0, nBlue = 0;
+
+ QString aValue = readEntry( key );
+ if( !aValue.isEmpty() )
+ {
+ if ( aValue.at(0) == '#' )
+ {
+ aRetColor.setNamedColor(aValue);
+ }
+ else
+ {
+ bool bOK;
+
+ // find first part (red)
+ int nIndex = aValue.find( ',' );
+
+ if( nIndex == -1 )
+ {
+ // return a sensible default -- Bernd
+ if( pDefault )
+ aRetColor = *pDefault;
+ return aRetColor;
+ }
+
+ nRed = aValue.left( nIndex ).toInt( &bOK );
+
+ // find second part (green)
+ int nOldIndex = nIndex;
+ nIndex = aValue.find( ',', nOldIndex+1 );
+
+ if( nIndex == -1 )
+ {
+ // return a sensible default -- Bernd
+ if( pDefault )
+ aRetColor = *pDefault;
+ return aRetColor;
+ }
+ nGreen = aValue.mid( nOldIndex+1,
+ nIndex-nOldIndex-1 ).toInt( &bOK );
+
+ // find third part (blue)
+ nBlue = aValue.right( aValue.length()-nIndex-1 ).toInt( &bOK );
+
+ aRetColor.setRgb( nRed, nGreen, nBlue );
+ }
+ }
+ else {
+
+ if( pDefault )
+ aRetColor = *pDefault;
+ }
+
+ return aRetColor;
+}
+
+// FIXME: The whole font handling has to be revised for Opie
+
+QFont OConfig::readFontEntry( const QString& key, const QFont* pDefault ) const
+{
+ /*
+ QFont aRetFont;
+
+ QString aValue = readEntry( key );
+ if( !aValue.isNull() ) {
+ if ( aValue.contains( ',' ) > 5 ) {
+ // KDE3 and upwards entry
+ if ( !aRetFont.fromString( aValue ) && pDefault )
+ aRetFont = *pDefault;
+ }
+ else {
+ // backward compatibility with older font formats
+ // ### remove KDE 3.1 ?
+ // find first part (font family)
+ int nIndex = aValue.find( ',' );
+ if( nIndex == -1 ){
+ if( pDefault )
+ aRetFont = *pDefault;
+ return aRetFont;
+ }
+ aRetFont.setFamily( aValue.left( nIndex ) );
+
+ // find second part (point size)
+ int nOldIndex = nIndex;
+ nIndex = aValue.find( ',', nOldIndex+1 );
+ if( nIndex == -1 ){
+ if( pDefault )
+ aRetFont = *pDefault;
+ return aRetFont;
+ }
+
+ aRetFont.setPointSize( aValue.mid( nOldIndex+1,
+ nIndex-nOldIndex-1 ).toInt() );
+
+ // find third part (style hint)
+ nOldIndex = nIndex;
+ nIndex = aValue.find( ',', nOldIndex+1 );
+
+ if( nIndex == -1 ){
+ if( pDefault )
+ aRetFont = *pDefault;
+ return aRetFont;
+ }
+
+ aRetFont.setStyleHint( (QFont::StyleHint)aValue.mid( nOldIndex+1, nIndex-nOldIndex-1 ).toUInt() );
+
+ // find fourth part (char set)
+ nOldIndex = nIndex;
+ nIndex = aValue.find( ',', nOldIndex+1 );
+
+ if( nIndex == -1 ){
+ if( pDefault )
+ aRetFont = *pDefault;
+ return aRetFont;
+ }
+
+ QString chStr=aValue.mid( nOldIndex+1,
+ nIndex-nOldIndex-1 );
+ // find fifth part (weight)
+ nOldIndex = nIndex;
+ nIndex = aValue.find( ',', nOldIndex+1 );
+
+ if( nIndex == -1 ){
+ if( pDefault )
+ aRetFont = *pDefault;
+ return aRetFont;
+ }
+
+ aRetFont.setWeight( aValue.mid( nOldIndex+1,
+ nIndex-nOldIndex-1 ).toUInt() );
+
+ // find sixth part (font bits)
+ uint nFontBits = aValue.right( aValue.length()-nIndex-1 ).toUInt();
+
+ aRetFont.setItalic( nFontBits & 0x01 );
+ aRetFont.setUnderline( nFontBits & 0x02 );
+ aRetFont.setStrikeOut( nFontBits & 0x04 );
+ aRetFont.setFixedPitch( nFontBits & 0x08 );
+ aRetFont.setRawMode( nFontBits & 0x20 );
+ }
+ }
+ else
+ {
+ if( pDefault )
+ aRetFont = *pDefault;
+ }
+ return aRetFont;
+ */
+ return QFont("Helvetica",10);
+}
diff --git a/libopie2/opiecore/oconfig.h b/libopie2/opiecore/oconfig.h
new file mode 100644
index 0000000..afe14b1
--- a/dev/null
+++ b/libopie2/opiecore/oconfig.h
@@ -0,0 +1,167 @@
+/*
+                 This file is part of the Opie Project
+
+ (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ Inspired by the config classes from the KDE Project which are
+ =. (C) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef OCONFIG_H
+#define OCONFIG_H
+
+//FIXME: Implement for X11 or reuse libqpe/Config there also?
+
+#include <qpe/config.h>
+
+class QColor;
+class QFont;
+
+/**
+ * A Configuration class based on the Qtopia @ref Config class
+ * featuring additional handling of color and font entries
+ */
+
+class OConfig : public Config
+{
+ public:
+
+ /**
+ * Constructs a OConfig object.
+ *
+ * @param name A file to parse.
+ */
+ OConfig( const QString &name, Domain domain = User );
+
+ /**
+ * Destructs the OConfig object.
+ *
+ * Writes back any dirty configuration entries, and destroys
+ * dynamically created objects.
+ */
+ virtual ~OConfig();
+
+ /**
+ * Returns the name of the group in which we are
+ * searching for keys and from which we are retrieving entries.
+ *
+ * @return The current group.
+ */
+ const QString& group() { return git.key(); };
+
+ /**
+ * Reads a @ref QColor entry.
+ *
+ * Read the value of an entry specified by @p pKey in the current group
+ * and interpret it as a color.
+ *
+ * @param pKey The key to search for.
+ * @param pDefault A default value (null QColor by default) returned if the
+ * key was not found or if the value cannot be interpreted.
+ * @return The value for this key.
+ */
+ QColor readColorEntry( const QString& key, const QColor* pDefault ) const;
+
+ /**
+ * Reads a @ref QFont value.
+ *
+ * Read the value of an entry specified by @p pKey in the current group
+ * and interpret it as a font object.
+ *
+ * @param pKey The key to search for.
+ * @param pDefault A default value (null QFont by default) returned if the
+ * key was not found or if the read value cannot be interpreted.
+ * @return The value for this key.
+ */
+ QFont readFontEntry( const QString& key, const QFont* pDefault ) const;
+
+};
+
+/**
+ * Helper class to facilitate working with @ref OConfig / @ref OSimpleConfig
+ * groups.
+ *
+ * Careful programmers always set the group of a
+ * @ref OConfig object to the group they want to read from
+ * and set it back to the old one of afterwards. This is usually
+ * written as:
+ * <pre>
+ *
+ * QString oldgroup config()->group();
+ * config()->setGroup( "TheGroupThatIWant" );
+ * ...
+ * config()->writeEntry( "Blah", "Blubb" );
+ *
+ * config()->setGroup( oldgroup );
+ * </pre>
+ *
+ * In order to facilitate this task, you can use
+ * OConfigGroupSaver. Simply construct such an object ON THE STACK
+ * when you want to switch to a new group. Then, when the object goes
+ * out of scope, the group will automatically be restored. If you
+ * want to use several different groups within a function or method,
+ * you can still use OConfigGroupSaver: Simply enclose all work with
+ * one group (including the creation of the OConfigGroupSaver object)
+ * in one block.
+ *
+ * @author Matthias Kalle Dalheimer <Kalle@kde.org>
+ * @version $Id$
+ * @see OConfig
+ * @short Helper class for easier use of OConfig groups
+ */
+
+class OConfigGroupSaver
+{
+ public:
+ /**
+ * Constructor. You pass a pointer to the OConfigBase-derived
+ * object you want to work with and a string indicating the _new_
+ * group.
+ * @param config The OConfig-derived object this
+ * OConfigGroupSaver works on.
+ * @param group The new group that the config object should switch to.
+ */
+ OConfigGroupSaver( OConfig* config, QString group ) :_config(config), _oldgroup(config->group() )
+ { _config->setGroup( group ); }
+
+ OConfigGroupSaver( OConfig* config, const char *group ) :_config(config), _oldgroup(config->group())
+ { _config->setGroup( group ); }
+
+ OConfigGroupSaver( OConfig* config, const QCString &group ) : _config(config), _oldgroup(config->group())
+ { _config->setGroup( group ); }
+
+ ~OConfigGroupSaver() { _config->setGroup( _oldgroup ); }
+
+ OConfig* config() { return _config; };
+
+ private:
+ OConfig* _config;
+ QString _oldgroup;
+
+ OConfigGroupSaver( const OConfigGroupSaver& );
+ OConfigGroupSaver& operator=( const OConfigGroupSaver& );
+};
+
+#endif // OCONFIG_H
diff --git a/libopie2/opiecore/odebug.cpp b/libopie2/opiecore/odebug.cpp
new file mode 100644
index 0000000..b4eaf2d
--- a/dev/null
+++ b/libopie2/opiecore/odebug.cpp
@@ -0,0 +1,628 @@
+/*
+ This file is part of the Opie Project
+ (C) 2003 Michael 'Mickey' Lauer (mickey@tm.informatik.uni-frankfurt.de)
+ Inspired by the KDE debug classes, which are
+ (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+ (C) 2002 Holger Freyther (freyther@kde.org)
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+// Include this header without OPIE_NO_DEBUG defined to avoid having the oDebugInfo
+// functions inlined to noops (which would then conflict with their definition here).
+
+#include <opie2/odebug.h>
+
+#ifdef OPIE_NO_DEBUG
+#undef odDebug
+#undef odBacktrace
+#endif
+
+/* OPIE */
+
+#include <opie2/oapplication.h>
+#include <opie2/oglobalsettings.h>
+#include <opie2/oconfig.h>
+
+/* QT */
+
+#include <qbrush.h>
+#include <qdatetime.h>
+#include <qfile.h>
+#include <qhostaddress.h>
+#include <qmessagebox.h>
+#include <qintdict.h>
+#include <qpoint.h>
+#include <qrect.h>
+#include <qregion.h>
+#include <qsize.h>
+#include <qsocketdevice.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+
+/* UNIX */
+
+#include <stdlib.h> // abort
+#include <unistd.h> // getpid
+#include <stdarg.h> // vararg stuff
+#include <ctype.h> // isprint
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+
+#ifndef OPIE_NO_BACKTRACE
+#include <execinfo.h>
+#endif
+
+
+/*======================================================================================
+ * debug levels
+ *======================================================================================*/
+
+enum DebugLevels {
+ ODEBUG_INFO = 0,
+ ODEBUG_WARN = 1,
+ ODEBUG_ERROR = 2,
+ ODEBUG_FATAL = 3
+};
+
+/*======================================================================================
+ * oDebug private data
+ *======================================================================================*/
+
+/*======================================================================================
+ * the main debug function
+ *======================================================================================*/
+
+static void oDebugBackend( unsigned short level, unsigned int area, const char *data)
+{
+ //qDebug( "oDebugBackend: Level=%d, Area=%d, Data=%s", level, area, data );
+
+ // ML: OPIE doesn't use areacodes at the moment. See the KDE debug classes for an
+ // ML: example use. I think it's not necessary to implement such a strategy here.
+ // ML: Comments?
+
+ int priority = 0;
+ QString caption;
+ QString lev;
+ switch( level )
+ {
+ case ODEBUG_INFO: lev = "(Info)"; caption = "Info"; priority = LOG_INFO; break;
+ case ODEBUG_WARN: lev = "(Warn)"; caption = "Warning"; priority = LOG_WARNING; break;
+ case ODEBUG_FATAL: lev = "(Fatal)"; caption = "Fatal Error"; priority = LOG_CRIT; break;
+ default: qDebug( "oDebugBackend: Warning: Unknown debug level! - defaulting to ODEBUG_ERROR." );
+ case ODEBUG_ERROR: lev = "(Error)"; caption = "Error"; priority = LOG_ERR; break;
+ }
+
+ short output = OGlobalSettings::debugMode();
+ if (!oApp && (output == 1))
+ {
+ qDebug( "oDebugBackend: Warning: no oapplication object - can't use MsgBox" );
+ output = 2; // need an application object to use MsgBox
+ }
+
+ QString areaName = (oApp) ? oApp->appName() : "<unknown>";
+
+ // Output
+ switch( output )
+ {
+ case -1: // ignore
+ {
+ return;
+ }
+ case 0: // File
+ {
+ QString outputFilename = OGlobalSettings::debugOutput();
+
+ const int BUFSIZE = 4096;
+ char buf[BUFSIZE] = "";
+ buf[BUFSIZE-1] = '\0';
+ int nSize;
+
+ nSize = snprintf( buf, BUFSIZE-1, "%s: %s", (const char*) areaName, data);
+
+ QFile outputFile( outputFilename );
+ if ( outputFile.open( IO_WriteOnly | IO_Append ) )
+ {
+ if ( ( nSize == -1 ) || ( nSize >= BUFSIZE ) )
+ {
+ outputFile.writeBlock( buf, BUFSIZE-1 );
+ }
+ else
+ {
+ outputFile.writeBlock( buf, nSize );
+ }
+ }
+ else
+ {
+ qDebug( "ODebug: can't write to file '%s' (%s)", (const char*) outputFilename, strerror(errno) );
+ }
+ break;
+ } // automatic close of file here
+
+ case 1: // Message Box
+ {
+ // Since we are in opiecore here, we cannot use OMsgBox and use
+ // QMessageBox instead
+
+ caption += QString("(") + areaName + ")";
+ QMessageBox::warning( 0L, caption, data, ("&OK") ); // tr?
+ break;
+ }
+
+ case 2: // Shell
+ {
+ FILE *output = stderr;
+ fprintf( output, "%s: ", (const char*) areaName );
+ fputs( data, output);
+ break;
+ }
+
+ case 3: // syslog
+ {
+ syslog( priority, "%s", data);
+ break;
+ }
+
+ case 4: // socket
+ {
+ QString destination = OGlobalSettings::debugOutput();
+ if ( destination && destination.find(":") != -1 )
+ {
+ QString host = destination.left( destination.find(":") );
+ QString port = destination.right( destination.length()-host.length()-1 );
+ QHostAddress addr;
+ addr.setAddress( host );
+ // TODO: sanity check the address
+ QString line;
+ line.sprintf( "%s: %s", (const char*) areaName, (const char*) data );
+ QSocketDevice s( QSocketDevice::Datagram );
+ int result = s.writeBlock( (const char*) line, line.length(), addr, port.toInt() );
+ if ( result == -1 )
+ {
+ qDebug( "ODebug: can't send to address '%s:%d' (%s)", (const char*) host, port.toInt(), strerror(errno) );
+ }
+ }
+ break;
+ }
+ }
+
+ // check if we should abort
+
+ /*
+
+ if( ( nLevel == ODEBUG_FATAL )
+ && ( !oDebug_data->config || oDebug_data->config->readNumEntry( "AbortFatal", 1 ) ) )
+ abort();
+
+ */
+}
+
+/*======================================================================================
+ * odbgstream
+ *======================================================================================*/
+
+odbgstream& perror( odbgstream &s)
+{
+ return s << QString::fromLocal8Bit(strerror(errno));
+}
+
+odbgstream odDebug(int area)
+{
+ return odbgstream(area, ODEBUG_INFO);
+}
+odbgstream odDebug(bool cond, int area)
+{
+ if (cond) return odbgstream(area, ODEBUG_INFO);
+ else return odbgstream(0, 0, false);
+}
+
+odbgstream odError(int area)
+{
+ return odbgstream("ERROR: ", area, ODEBUG_ERROR);
+}
+
+odbgstream odError(bool cond, int area)
+{
+ if (cond) return odbgstream("ERROR: ", area, ODEBUG_ERROR); else return odbgstream(0,0,false);
+}
+
+odbgstream odWarning(int area)
+{
+ return odbgstream("WARNING: ", area, ODEBUG_WARN);
+}
+
+odbgstream odWarning(bool cond, int area)
+{
+ if (cond) return odbgstream("WARNING: ", area, ODEBUG_WARN); else return odbgstream(0,0,false);
+}
+
+odbgstream odFatal(int area)
+{
+ return odbgstream("FATAL: ", area, ODEBUG_FATAL);
+}
+
+odbgstream odFatal(bool cond, int area)
+{
+ if (cond) return odbgstream("FATAL: ", area, ODEBUG_FATAL); else return odbgstream(0,0,false);
+}
+
+odbgstream::odbgstream(unsigned int _area, unsigned int _level, bool _print)
+ :area(_area), level(_level), print(_print)
+{
+}
+
+
+odbgstream::odbgstream(const char * initialString, unsigned int _area, unsigned int _level, bool _print)
+ :output(QString::fromLatin1(initialString)), area(_area), level(_level), print(_print)
+{
+}
+
+
+odbgstream::odbgstream(odbgstream &str)
+ :output(str.output), area(str.area), level(str.level), print(str.print)
+{
+ str.output.truncate(0);
+}
+
+
+odbgstream::odbgstream(const odbgstream &str)
+ :output(str.output), area(str.area), level(str.level), print(str.print)
+{
+}
+
+odbgstream& odbgstream::operator<<(bool i)
+{
+ if (!print) return *this;
+ output += QString::fromLatin1(i ? "true" : "false");
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<(short i)
+{
+ if (!print) return *this;
+ QString tmp; tmp.setNum(i); output += tmp;
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<(unsigned short i)
+{
+ if (!print) return *this;
+ QString tmp; tmp.setNum(i); output += tmp;
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<(unsigned char i)
+{
+ return operator<<( static_cast<char>( i ) );
+}
+
+
+odbgstream& odbgstream::operator<<(int i)
+{
+ if (!print) return *this;
+ QString tmp; tmp.setNum(i); output += tmp;
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<(unsigned int i)
+{
+ if (!print) return *this;
+ QString tmp; tmp.setNum(i); output += tmp;
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<(long i)
+{
+ if (!print) return *this;
+ QString tmp; tmp.setNum(i); output += tmp;
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<(unsigned long i)
+{
+ if (!print) return *this;
+ QString tmp; tmp.setNum(i); output += tmp;
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<(const QString& string)
+{
+ if (!print) return *this;
+ output += string;
+ if (output.at(output.length() -1 ) == '\n')
+ flush();
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<(const char *string)
+{
+ if (!print) return *this;
+ output += QString::fromUtf8(string);
+ if (output.at(output.length() - 1) == '\n')
+ flush();
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<(const QCString& string)
+{
+ *this << string.data();
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<(const void * p)
+{
+ form("%p", p);
+ return *this;
+}
+
+odbgstream& odbgstream::operator<<(double d)
+{
+ QString tmp; tmp.setNum(d); output += tmp;
+ return *this;
+}
+
+/*
+odbgstream::odbgstream &form(const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format ( printf, 2, 3 ) ) )
+#endif
+ ;
+*/
+
+void odbgstream::flush()
+{
+ if ( output.isEmpty() || !print )
+ {
+ return;
+ }
+ else
+ {
+ oDebugBackend( level, area, output.local8Bit().data() );
+ output = QString::null;
+ }
+}
+
+odbgstream& odbgstream::form(const char *format, ...)
+{
+ char buf[4096];
+ va_list arguments;
+ va_start( arguments, format );
+ buf[sizeof(buf)-1] = '\0';
+ vsnprintf( buf, sizeof(buf)-1, format, arguments );
+ va_end(arguments);
+ *this << buf;
+ return *this;
+}
+
+odbgstream::~odbgstream()
+{
+ if (!output.isEmpty())
+ {
+ fprintf(stderr, "ASSERT: debug output not ended with \\n\n");
+ *this << "\n";
+ }
+}
+
+odbgstream& odbgstream::operator<<(char ch)
+{
+ if (!print) return *this;
+ if (!isprint(ch))
+ {
+ output += "\\x" + QString::number( static_cast<uint>( ch ) + 0x100, 16 ).right(2);
+ }
+ else
+ {
+ output += ch;
+ if (ch == '\n') flush();
+ }
+ return *this;
+}
+
+odbgstream& odbgstream::operator<<( QWidget* widget )
+{
+ QString string, temp;
+ // -----
+ if(widget==0)
+ {
+ string=(QString)"[Null pointer]";
+ } else
+ {
+ temp.setNum((ulong)widget, 16);
+ string=(QString)"["+widget->className()+" pointer " + "(0x" + temp + ")";
+ if(widget->name(0)==0)
+ {
+ string += " to unnamed widget, ";
+ } else
+ {
+ string += (QString)" to widget " + widget->name() + ", ";
+ }
+ string += "geometry="
+ + QString().setNum(widget->width())
+ + "x"+QString().setNum(widget->height())
+ + "+"+QString().setNum(widget->x())
+ + "+"+QString().setNum(widget->y())
+ + "]";
+ }
+ if (!print) return *this;
+
+ output += string;
+ if (output.at(output.length()-1) == '\n')
+ {
+ flush();
+ }
+ return *this;
+}
+
+/*
+ * either use 'output' directly and do the flush if needed
+ * or use the QString operator which calls the char* operator
+ *
+ */
+odbgstream& odbgstream::operator<<( const QDateTime& time)
+{
+ *this << time.toString();
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<( const QDate& date)
+{
+ *this << date.toString();
+
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<( const QTime& time )
+{
+ *this << time.toString();
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<( const QPoint& p )
+{
+ *this << "(" << p.x() << ", " << p.y() << ")";
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<( const QSize& s )
+{
+ *this << "[" << s.width() << "x" << s.height() << "]";
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<( const QRect& r )
+{
+ *this << "[" << r.left() << ", " << r.top() << " - " << r.right() << ", " << r.bottom() << "]";
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<( const QRegion& reg )
+{
+ /* Qt2 doesn't have a QMemArray... :(
+ *this << "[ ";
+ QMemArray<QRect>rs=reg.rects();
+ for (uint i=0;i<rs.size();++i)
+ *this << QString("[%1, %2 - %3, %4] ").arg(rs[i].left()).arg(rs[i].top()).arg(rs[i].right()).arg(rs[i].bottom() ) ;
+ *this <<"]";
+ */
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<( const QStringList& l )
+{
+ *this << "(";
+ *this << l.join(",");
+ *this << ")";
+
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<( const QColor& c )
+{
+ if ( c.isValid() )
+ *this << c.name();
+ else
+ *this << "(invalid/default)";
+ return *this;
+}
+
+
+odbgstream& odbgstream::operator<<( const QBrush& b)
+{
+ static const char* const s_brushStyles[] = {
+ "NoBrush", "SolidPattern", "Dense1Pattern", "Dense2Pattern", "Dense3Pattern",
+ "Dense4Pattern", "Dense5Pattern", "Dense6Pattern", "Dense7Pattern",
+ "HorPattern", "VerPattern", "CrossPattern", "BDiagPattern", "FDiagPattern",
+ "DiagCrossPattern" };
+
+ *this <<"[ style: ";
+ *this <<s_brushStyles[ b.style() ];
+ *this <<" color: ";
+ // can't use operator<<(str, b.color()) because that terminates a odbgstream (flushes)
+ if ( b.color().isValid() )
+ *this <<b.color().name() ;
+ else
+ *this <<"(invalid/default)";
+ if ( b.pixmap() )
+ *this <<" has a pixmap";
+ *this <<" ]";
+ return *this;
+}
+
+
+
+QString odBacktrace( int levels )
+{
+ QString s;
+#ifndef OPIE_NO_BACKTRACE
+ void* trace[256];
+ int n = backtrace(trace, 256);
+ char** strings = backtrace_symbols (trace, n);
+
+ if ( levels != -1 )
+ n = QMIN( n, levels );
+ s = "[\n";
+
+ for (int i = 0; i < n; ++i)
+ s += QString::number(i) +
+ QString::fromLatin1(": ") +
+ QString::fromLatin1(strings[i]) + QString::fromLatin1("\n");
+ s += "]\n";
+ free (strings);
+#endif
+ return s;
+}
+
+void odClearDebugConfig()
+{
+ /*
+ delete oDebug_data->config;
+ oDebug_data->config = 0;
+ */
+}
+
+#ifdef OPIE_NO_DEBUG
+#define odDebug ondDebug
+#define odBacktrace ondBacktrace
+#endif
diff --git a/libopie2/opiecore/odebug.h b/libopie2/opiecore/odebug.h
new file mode 100644
index 0000000..85941fd
--- a/dev/null
+++ b/libopie2/opiecore/odebug.h
@@ -0,0 +1,474 @@
+/*
+ This file is part of the Opie Project
+ (C) 2003 Michael 'Mickey' Lauer (mickey@tm.informatik.uni-frankfurt.de)
+ Inspired by the KDE debug classes, which are
+ (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+ (C) 2002 Holger Freyther (freyther@kde.org)
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef ODEBUG_H
+#define ODEBUG_H
+
+#include <qstring.h>
+
+class QWidget;
+class QDateTime;
+class QDate;
+class QTime;
+class QPoint;
+class QSize;
+class QRect;
+class QRegion;
+class QStringList;
+class QColor;
+class QBrush;
+
+class odbgstream;
+class ondbgstream;
+
+#ifdef __GNUC__
+#define o_funcinfo "[" << __PRETTY_FUNCTION__ << "] "
+#else
+#define o_funcinfo "[" << __FILE__ << ":" << __LINE__ << "] "
+#endif
+
+#define o_lineinfo "[" << __FILE__ << ":" << __LINE__ << "] "
+
+#define owarn odWarning()
+#define oerr odError()
+#define odebug odDebug()
+#define ofatal odFatal()
+#define oendl "\n"
+
+class odbgstreamprivate;
+/**
+ * odbgstream is a text stream that allows you to print debug messages.
+ * Using the overloaded "<<" operator you can send messages. Usually
+ * you do not create the odbgstream yourself, but use @ref odDebug() (odebug)
+ * @ref odWarning() (owarn), @ref odError() (oerr) or @ref odFatal (ofatal) to obtain one.
+ *
+ * Example:
+ * <pre>
+ * int i = 5;
+ * odebug << "The value of i is " << i << oendl;
+ * </pre>
+ * @see odbgstream
+ */
+
+/*======================================================================================
+ * odbgstream
+ *======================================================================================*/
+
+class odbgstream
+{
+ public:
+ /**
+ * @internal
+ */
+ odbgstream(unsigned int _area, unsigned int _level, bool _print = true);
+ odbgstream(const char * initialString, unsigned int _area, unsigned int _level, bool _print = true);
+ odbgstream(odbgstream &str);
+ odbgstream(const odbgstream &str);
+ virtual ~odbgstream();
+
+ /**
+ * Prints the given value.
+ * @param i the boolean to print (as "true" or "false")
+ * @return this stream
+ */
+ odbgstream &operator<<(bool i);
+ /**
+ * Prints the given value.
+ * @param i the short to print
+ * @return this stream
+ */
+ odbgstream &operator<<(short i);
+ /**
+ * Prints the given value.
+ * @param i the unsigned short to print
+ * @return this stream
+ */
+ odbgstream &operator<<(unsigned short i);
+ /**
+ * Prints the given value.
+ * @param i the char to print
+ * @return this stream
+ */
+ odbgstream &operator<<(char i);
+ /**
+ * Prints the given value.
+ * @param i the unsigned char to print
+ * @return this stream
+ */
+ odbgstream &operator<<(unsigned char i);
+ /**
+ * Prints the given value.
+ * @param i the int to print
+ * @return this stream
+ */
+ odbgstream &operator<<(int i);
+ /**
+ * Prints the given value.
+ * @param i the unsigned int to print
+ * @return this stream
+ */
+ odbgstream &operator<<(unsigned int i);
+ /**
+ * Prints the given value.
+ * @param i the long to print
+ * @return this stream
+ */
+ odbgstream &operator<<(long i);
+ /**
+ * Prints the given value.
+ * @param i the unsigned long to print
+ * @return this stream
+ */
+ odbgstream &operator<<(unsigned long i);
+ /**
+ * Flushes the output.
+ */
+ virtual void flush();
+ /**
+ * Prints the given value.
+ * @param string the string to print
+ * @return this stream
+ */
+ odbgstream &operator<<(const QString& string);
+ /**
+ * Prints the given value.
+ * @param string the string to print
+ * @return this stream
+ */
+ odbgstream &operator<<(const char *string);
+ /**
+ * Prints the given value.
+ * @param string the string to print
+ * @return this stream
+ */
+ odbgstream &operator<<(const QCString& string);
+ /**
+ * Prints the given value.
+ * @param p a pointer to print (in number form)
+ * @return this stream
+ */
+ odbgstream& operator<<(const void * p);
+ /**
+ * Prints the given value.
+ * @param d the double to print
+ * @return this stream
+ */
+ odbgstream& operator<<(double d);
+ /**
+ * Prints the string @p format which can contain
+ * printf-style formatted values.
+ * @param format the printf-style format
+ * @return this stream
+ */
+ odbgstream &form(const char *format, ...);
+ /** Operator to print out basic information about a QWidget.
+ * Output of class names only works if the class is moc'ified.
+ * @param widget the widget to print
+ * @return this stream
+ */
+ odbgstream& operator<< (QWidget* widget);
+
+ /**
+ * Prints the given value.
+ * @param dateTime the datetime to print
+ * @return this stream
+ */
+ odbgstream& operator<< ( const QDateTime& dateTime );
+
+ /**
+ * Prints the given value.
+ * @param date the date to print
+ * @return this stream
+ */
+ odbgstream& operator<< ( const QDate& date );
+
+ /**
+ * Prints the given value.
+ * @param time the time to print
+ * @return this stream
+ */
+ odbgstream& operator<< ( const QTime& time );
+
+ /**
+ * Prints the given value.
+ * @param point the point to print
+ * @return this stream
+ */
+ odbgstream& operator<< ( const QPoint& point );
+
+ /**
+ * Prints the given value.
+ * @param size the QSize to print
+ * @return this stream
+ */
+ odbgstream& operator<< ( const QSize& size );
+
+ /**
+ * Prints the given value.
+ * @param rect the QRect to print
+ * @return this stream
+ */
+ odbgstream& operator<< ( const QRect& rect);
+
+ /**
+ * Prints the given value.
+ * @param region the QRegion to print
+ * @return this stream
+ */
+ odbgstream& operator<< ( const QRegion& region);
+
+ /**
+ * Prints the given value.
+ * @param list the stringlist to print
+ * @return this stream
+ */
+ odbgstream& operator<< ( const QStringList& list);
+
+ /**
+ * Prints the given value.
+ * @param color the color to print
+ * @return this stream
+ */
+ odbgstream& operator<< ( const QColor& color);
+
+ /**
+ * Prints the given value.
+ * @param brush the brush to print
+ * @return this stream
+ */
+ odbgstream& operator<< ( const QBrush& brush );
+
+ private:
+ QString output;
+ unsigned int area, level;
+ bool print;
+ odbgstreamprivate* d;
+};
+
+/**
+ * Prints an "\n".
+ * @param s the debug stream to write to
+ * @return the debug stream (@p s)
+ */
+inline odbgstream& endl( odbgstream &s) { s << "\n"; return s; }
+/**
+ * Flushes the stream.
+ * @param s the debug stream to write to
+ * @return the debug stream (@p s)
+ */
+inline odbgstream& flush( odbgstream &s) { s.flush(); return s; }
+
+odbgstream &perror( odbgstream &s);
+
+/**
+ * ondbgstream is a dummy variant of @ref odbgstream. All functions do
+ * nothing.
+ * @see ondDebug()
+ */
+class ondbgstream {
+ public:
+ /// Empty constructor.
+ ondbgstream() {}
+ ~ondbgstream() {}
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream &operator<<(short int ) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream &operator<<(unsigned short int ) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream &operator<<(char ) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream &operator<<(unsigned char ) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream &operator<<(int ) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream &operator<<(unsigned int ) { return *this; }
+ /**
+ * Does nothing.
+ */
+ void flush() {}
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream &operator<<(const QString& ) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream &operator<<(const QCString& ) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream &operator<<(const char *) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream& operator<<(const void *) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream& operator<<(void *) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream& operator<<(double) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream& operator<<(long) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream& operator<<(unsigned long) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream& operator << (QWidget*) { return *this; }
+ /**
+ * Does nothing.
+ * @return this stream
+ */
+ ondbgstream &form(const char *, ...) { return *this; }
+
+ ondbgstream& operator<<( const QDateTime& ) { return *this; }
+ ondbgstream& operator<<( const QDate& ) { return *this; }
+ ondbgstream& operator<<( const QTime& ) { return *this; }
+ ondbgstream& operator<<( const QPoint & ) { return *this; }
+ ondbgstream& operator<<( const QSize & ) { return *this; }
+ ondbgstream& operator<<( const QRect & ) { return *this; }
+ ondbgstream& operator<<( const QRegion & ) { return *this; }
+ ondbgstream& operator<<( const QStringList & ) { return *this; }
+ ondbgstream& operator<<( const QColor & ) { return *this; }
+ ondbgstream& operator<<( const QBrush & ) { return *this; }
+};
+
+/*======================================================================================
+ * related functions
+ *======================================================================================*/
+
+/**
+ * Does nothing.
+ * @param a stream
+ * @return the given @p s
+ */
+inline ondbgstream& endl( ondbgstream & s) { return s; }
+/**
+ * Does nothing.
+ * @param a stream
+ * @return the given @p s
+ */
+inline ondbgstream& flush( ondbgstream & s) { return s; }
+inline ondbgstream& perror( ondbgstream & s) { return s; }
+
+/**
+ * Returns a debug stream. You can use it to print debug
+ * information.
+ * @param area an id to identify the output, 0 for default
+ */
+odbgstream odDebug(int area = 0);
+odbgstream odDebug(bool cond, int area = 0);
+/**
+ * Returns a backtrace.
+ * @param levels the number of levels (-1 for unlimited) of the backtrace
+ * @return a backtrace
+ */
+QString odBacktrace(int levels = -1);
+/**
+ * Returns a dummy debug stream. The stream does not print anything.
+ * @param area an id to identify the output, 0 for default
+ * @see odDebug()
+ */
+inline ondbgstream ondDebug(int = 0) { return ondbgstream(); }
+inline ondbgstream ondDebug(bool , int = 0) { return ondbgstream(); }
+inline QString ondBacktrace() { return QString::null; }
+inline QString ondBacktrace(int) { return QString::null; }
+
+/**
+ * Returns a warning stream. You can use it to print warning
+ * information.
+ * @param area an id to identify the output, 0 for default
+ */
+odbgstream odWarning(int area = 0);
+odbgstream odWarning(bool cond, int area = 0);
+/**
+ * Returns an error stream. You can use it to print error
+ * information.
+ * @param area an id to identify the output, 0 for default
+ */
+odbgstream odError(int area = 0);
+odbgstream odError(bool cond, int area = 0);
+/**
+ * Returns a fatal error stream. You can use it to print fatal error
+ * information.
+ * @param area an id to identify the output, 0 for default
+ */
+odbgstream odFatal(int area = 0);
+odbgstream odFatal(bool cond, int area = 0);
+
+/**
+ * Deletes the odebugrc cache and therefore forces KDebug to reread the
+ * config file
+ */
+void odClearDebugConfig();
+
+#ifdef OPIE_NO_DEBUG
+#define odDebug ondDebug
+#define odBacktrace ondBacktrace
+#endif
+
+#endif
+
diff --git a/libopie2/opiecore/oglobal.cpp b/libopie2/opiecore/oglobal.cpp
new file mode 100644
index 0000000..2eb4108
--- a/dev/null
+++ b/libopie2/opiecore/oglobal.cpp
@@ -0,0 +1,36 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+#include <opie2/oglobal.h>
+
+OConfig* OGlobal::config()
+{
+ return &globalconfig;
+}
diff --git a/libopie2/opiecore/oglobal.h b/libopie2/opiecore/oglobal.h
new file mode 100644
index 0000000..8345c6a
--- a/dev/null
+++ b/libopie2/opiecore/oglobal.h
@@ -0,0 +1,48 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef OGLOBAL_H
+#define OGLOBAL_H
+
+#include <qpe/global.h>
+#include <opie2/oconfig.h>
+
+static OConfig globalconfig = OConfig( "global" );
+
+//FIXME: Is it wise or even necessary to inherit OGlobal from Global?
+
+class OGlobal : public Global
+{
+ public:
+
+ static OConfig* config();
+};
+
+#endif // OGLOBAL_H
diff --git a/libopie2/opiecore/oglobalsettings.cpp b/libopie2/opiecore/oglobalsettings.cpp
new file mode 100644
index 0000000..184ee69
--- a/dev/null
+++ b/libopie2/opiecore/oglobalsettings.cpp
@@ -0,0 +1,547 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ Inspired by the KDE globalsettings which are
+ Copyright (C) 2000 David Faure <faure@kde.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/* OPIE */
+
+#include <opie2/oglobalsettings.h>
+#include <opie2/oconfig.h>
+#include <opie2/oglobal.h>
+
+/* QT */
+
+#include <qdir.h>
+#include <qpixmap.h>
+#include <qfontinfo.h>
+
+/* UNIX */
+
+#include <stdlib.h>
+
+QString* OGlobalSettings::s_desktopPath = 0;
+QString* OGlobalSettings::s_autostartPath = 0;
+QString* OGlobalSettings::s_trashPath = 0;
+QString* OGlobalSettings::s_documentPath = 0;
+QFont *OGlobalSettings::_generalFont = 0;
+QFont *OGlobalSettings::_fixedFont = 0;
+QFont *OGlobalSettings::_toolBarFont = 0;
+QFont *OGlobalSettings::_menuFont = 0;
+QFont *OGlobalSettings::_windowTitleFont = 0;
+QFont *OGlobalSettings::_taskbarFont = 0;
+
+QColor *OGlobalSettings::OpieGray = 0;
+QColor *OGlobalSettings::OpieHighlight = 0;
+QColor *OGlobalSettings::OpieAlternate = 0;
+
+OGlobalSettings::OMouseSettings *OGlobalSettings::s_mouseSettings = 0;
+
+//FIXME: Add manipulators to the accessors
+
+int OGlobalSettings::dndEventDelay()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, "General" );
+ return c->readNumEntry("DndDelay", 2);
+}
+
+bool OGlobalSettings::singleClick()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, "OPIE" );
+ return c->readBoolEntry("SingleClick", OPIE_DEFAULT_SINGLECLICK);
+}
+
+bool OGlobalSettings::insertTearOffHandle()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, "OPIE" );
+ return c->readBoolEntry("InsertTearOffHandle", OPIE_DEFAULT_INSERTTEAROFFHANDLES);
+}
+
+bool OGlobalSettings::changeCursorOverIcon()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, "OPIE" );
+ return c->readBoolEntry("ChangeCursor", OPIE_DEFAULT_CHANGECURSOR);
+}
+
+bool OGlobalSettings::visualActivate()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, "OPIE" );
+ return c->readBoolEntry("VisualActivate", OPIE_DEFAULT_VISUAL_ACTIVATE);
+}
+
+unsigned int OGlobalSettings::visualActivateSpeed()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, "OPIE" );
+ return
+ c->readNumEntry(
+ "VisualActivateSpeed",
+ OPIE_DEFAULT_VISUAL_ACTIVATE_SPEED
+ );
+}
+
+int OGlobalSettings::autoSelectDelay()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, "OPIE" );
+ return c->readNumEntry("AutoSelectDelay", OPIE_DEFAULT_AUTOSELECTDELAY);
+}
+
+OGlobalSettings::Completion OGlobalSettings::completionMode()
+{
+ int completion;
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, "General" );
+ completion = c->readNumEntry("completionMode", -1);
+ if ((completion < (int) CompletionNone) ||
+ (completion > (int) CompletionPopupAuto))
+ {
+ completion = (int) CompletionPopup; // Default
+ }
+ return (Completion) completion;
+}
+
+
+bool OGlobalSettings::showContextMenusOnPress ()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs (c, "ContextMenus");
+
+ return cgs.config()->readBoolEntry("ShowOnPress", true);
+}
+
+
+int OGlobalSettings::contextMenuKey ()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs (c, "Shortcuts");
+
+ //OShortcut cut (cgs.config()->readEntry ("PopupMenuContext", "Menu"));
+ //return cut.keyCodeQt();
+
+ return 0; // FIXME
+}
+
+
+OGlobalSettings::Debug OGlobalSettings::debugMode()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, "General" );
+ int debug = c->readNumEntry( "debugMode", -1 );
+ if ( (debug < (int) DebugNone) || (debug > (int) DebugSocket) )
+ {
+ debug = (int) DebugStdErr; // Default
+ }
+ return (Debug) debug;
+}
+
+
+QString OGlobalSettings::debugOutput()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, "General" );
+ QString deflt = QString::null;
+ switch( debugMode() )
+ {
+ case DebugNone: break; // no additional information needed
+ case DebugFiles: deflt = "/var/log/opiedebug.log"; break; // file to save output in
+ case DebugMsgBox: break; // no additional information needed
+ case DebugStdErr: break; // no additional information needed
+ case DebugSysLog: break; // no additional information needed
+ case DebugSocket: deflt = "127.0.0.1:8913"; break; // address to send packets to
+ }
+
+ return c->readEntry( "debugOutput"+ QString::number(debugMode()), deflt );
+}
+
+
+QColor OGlobalSettings::toolBarHighlightColor()
+{
+ initColors();
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("Toolbar style") );
+ return c->readColorEntry("HighlightColor", OpieHighlight);
+}
+
+QColor OGlobalSettings::inactiveTitleColor()
+{
+ if (!OpieGray) OpieGray = new QColor(220, 220, 220);
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("WM") );
+ return c->readColorEntry( "inactiveBackground", OpieGray );
+}
+
+QColor OGlobalSettings::inactiveTextColor()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("WM") );
+ return c->readColorEntry( "inactiveForeground", &Qt::darkGray );
+}
+
+QColor OGlobalSettings::activeTitleColor()
+{
+ initColors();
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("WM") );
+ return c->readColorEntry( "activeBackground", OpieHighlight);
+}
+
+QColor OGlobalSettings::activeTextColor()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("WM") );
+ return c->readColorEntry( "activeForeground", &Qt::white );
+}
+
+int OGlobalSettings::contrast()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("OPIE") );
+ return c->readNumEntry( "contrast", 7 );
+}
+
+// following functions should work in OPIE - how to sync with appearance changes?
+
+QColor OGlobalSettings::baseColor()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
+ return c->readColorEntry( "Base", &Qt::white );
+}
+
+QColor OGlobalSettings::textColor()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
+ return c->readColorEntry( "Text", &Qt::black );
+}
+
+QColor OGlobalSettings::highlightedTextColor()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
+ return c->readColorEntry( "HighlightedText", &Qt::white );
+}
+
+QColor OGlobalSettings::highlightColor()
+{
+ initColors();
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
+ return c->readColorEntry( "Highlight", OpieHighlight );
+}
+
+QColor OGlobalSettings::alternateBackgroundColor()
+{
+ initColors();
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
+ *OpieAlternate = calculateAlternateBackgroundColor( baseColor() );
+ return c->readColorEntry( "alternateBackground", OpieAlternate );
+}
+
+QColor OGlobalSettings::calculateAlternateBackgroundColor(const QColor& base)
+{
+ if (base == Qt::white)
+ return QColor(238,246,255);
+ else
+ {
+ int h, s, v;
+ base.hsv( &h, &s, &v );
+ if (v > 128)
+ return base.dark(106);
+ else if (base != Qt::black)
+ return base.light(110);
+
+ return QColor(32,32,32);
+ }
+}
+
+QColor OGlobalSettings::linkColor()
+{
+ initColors();
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
+ return c->readColorEntry( "linkColor", OpieGray );
+}
+
+QColor OGlobalSettings::visitedLinkColor()
+{
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
+ return c->readColorEntry( "visitedLinkColor", &Qt::magenta );
+}
+
+// FIXME: font stuff currently uses a different format in OPIE, so the
+// functions below are not yet applicable. The whole font stuff for OPIE
+// has to be revised anyway
+
+QFont OGlobalSettings::generalFont()
+{
+ if (_generalFont)
+ return *_generalFont;
+
+ _generalFont = new QFont("helvetica", 10);
+ _generalFont->setPixelSize(10);
+ _generalFont->setStyleHint(QFont::SansSerif);
+
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
+ *_generalFont = c->readFontEntry("font", _generalFont);
+
+ return *_generalFont;
+}
+
+QFont OGlobalSettings::fixedFont()
+{
+ if (_fixedFont)
+ return *_fixedFont;
+
+ _fixedFont = new QFont("courier", 12);
+ _fixedFont->setPixelSize(12);
+ _fixedFont->setStyleHint(QFont::TypeWriter);
+
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("General") );
+ *_fixedFont = c->readFontEntry("fixed", _fixedFont);
+
+ return *_fixedFont;
+}
+
+QFont OGlobalSettings::toolBarFont()
+{
+ if(_toolBarFont)
+ return *_toolBarFont;
+
+ _toolBarFont = new QFont("helvetica", 10);
+ _toolBarFont->setPixelSize(10);
+ _toolBarFont->setStyleHint(QFont::SansSerif);
+
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("General") );
+ *_toolBarFont = c->readFontEntry("toolBarFont", _toolBarFont);
+
+ return *_toolBarFont;
+}
+
+QFont OGlobalSettings::menuFont()
+{
+ if(_menuFont)
+ return *_menuFont;
+
+ _menuFont = new QFont("helvetica", 12);
+ _menuFont->setPixelSize(12);
+ _menuFont->setStyleHint(QFont::SansSerif);
+
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("General") );
+ *_menuFont = c->readFontEntry("menuFont", _menuFont);
+
+ return *_menuFont;
+}
+
+QFont OGlobalSettings::windowTitleFont()
+{
+ if(_windowTitleFont)
+ return *_windowTitleFont;
+
+ _windowTitleFont = new QFont("helvetica", 12, QFont::Bold);
+ _windowTitleFont->setPixelSize(12);
+ _windowTitleFont->setStyleHint(QFont::SansSerif);
+
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("WM") );
+ *_windowTitleFont = c->readFontEntry("activeFont", _windowTitleFont); // inconsistency
+
+ return *_windowTitleFont;
+}
+
+QFont OGlobalSettings::taskbarFont()
+{
+ if(_taskbarFont)
+ return *_taskbarFont;
+
+ _taskbarFont = new QFont("helvetica", 8);
+ _taskbarFont->setPixelSize(8);
+ _taskbarFont->setStyleHint(QFont::SansSerif);
+
+ OConfig *c = OGlobal::config();
+ OConfigGroupSaver cgs( c, QString::fromLatin1("General") );
+ *_taskbarFont = c->readFontEntry("taskbarFont", _taskbarFont);
+
+ return *_taskbarFont;
+}
+
+// FIXME: the whole path stuff has to be revised for OPIE
+
+void OGlobalSettings::initStatic() // should be called initPaths(). Don't put anything else here.
+{
+ if ( s_desktopPath != 0 )
+ return;
+
+ s_desktopPath = new QString();
+ s_autostartPath = new QString();
+ s_trashPath = new QString();
+ s_documentPath = new QString();
+
+ OConfig *config = OGlobal::config();
+ //bool dollarExpansion = config->isDollarExpansion();
+ //config->setDollarExpansion(true);
+ OConfigGroupSaver cgs( config, "Paths" );
+
+ // Desktop Path
+ *s_desktopPath = QDir::homeDirPath() + "/" + "Desktop" + "/";
+ *s_desktopPath = config->readEntry( "Desktop", *s_desktopPath);
+ if ( (*s_desktopPath)[0] != '/' )
+ s_desktopPath->prepend( QDir::homeDirPath() + "/" );
+ *s_desktopPath = QDir::cleanDirPath( *s_desktopPath );
+ if ( s_desktopPath->right(1) != "/")
+ *s_desktopPath += "/";
+
+ // Trash Path
+ *s_trashPath = *s_desktopPath + QObject::tr("Trash") + "/";
+ *s_trashPath = config->readEntry( "Trash" , *s_trashPath);
+ if ( (*s_trashPath)[0] != '/' )
+ s_trashPath->prepend( QDir::homeDirPath() + "/" );
+ *s_trashPath = QDir::cleanDirPath( *s_trashPath );
+ if ( s_trashPath->right(1) != "/")
+ *s_trashPath += "/";
+ // We need to save it in any case, in case the language changes later on,
+ if ( !config->hasKey( "Trash" ) )
+ {
+ //config->writePathEntry( "Trash", *s_trashPath, true, true );
+ config->writeEntry( "Trash", *s_trashPath );
+ //config->sync();
+ }
+
+/* // Autostart Path
+ *s_autostartPath = OGlobal::dirs()->localkdedir() + "Autostart" + "/";
+ *s_autostartPath = config->readEntry( "Autostart" , *s_autostartPath);
+ if ( (*s_autostartPath)[0] != '/' )
+ s_autostartPath->prepend( QDir::homeDirPath() + "/" );
+ *s_autostartPath = QDir::cleanDirPath( *s_autostartPath );
+ if ( s_autostartPath->right(1) != "/")
+ *s_autostartPath += "/";
+*/
+ // Document Path
+ *s_documentPath = QString::null;
+ *s_documentPath = config->readEntry( "Documents" , *s_documentPath);
+ if ( (*s_documentPath)[0] != '/' )
+ s_documentPath->prepend( QDir::homeDirPath() + "/" );
+ *s_documentPath = QDir::cleanDirPath( *s_documentPath );
+ if ( s_documentPath->right(1) != "/")
+ *s_documentPath += "/";
+
+ //config->setDollarExpansion(dollarExpansion);
+
+ // Make sure this app gets the notifications about those paths
+ //if (kapp)
+ //kapp->addKipcEventMask(KIPC::SettingsChanged);
+}
+
+void OGlobalSettings::initColors()
+{
+ if ( not OpieHighlight ) OpieHighlight = new QColor( 156, 118, 32 );
+ if ( not OpieAlternate ) OpieAlternate = new QColor( 238, 246, 255 );
+ if ( not OpieGray ) OpieGray = new QColor( 220, 210, 215 );
+}
+
+void OGlobalSettings::rereadFontSettings()
+{
+ delete _generalFont;
+ _generalFont = 0L;
+ delete _fixedFont;
+ _fixedFont = 0L;
+ delete _menuFont;
+ _menuFont = 0L;
+ delete _toolBarFont;
+ _toolBarFont = 0L;
+ delete _windowTitleFont;
+ _windowTitleFont = 0L;
+ delete _taskbarFont;
+ _taskbarFont = 0L;
+}
+
+void OGlobalSettings::rereadPathSettings()
+{
+ qDebug( "OGlobalSettings::rereadPathSettings" );
+ delete s_autostartPath;
+ s_autostartPath = 0L;
+ delete s_trashPath;
+ s_trashPath = 0L;
+ delete s_desktopPath;
+ s_desktopPath = 0L;
+ delete s_documentPath;
+ s_documentPath = 0L;
+}
+
+OGlobalSettings::OMouseSettings & OGlobalSettings::mouseSettings()
+{
+ if ( ! s_mouseSettings )
+ {
+ s_mouseSettings = new OMouseSettings;
+ OMouseSettings & s = *s_mouseSettings; // for convenience
+
+ OConfigGroupSaver cgs( OGlobal::config(), "Mouse" );
+ QString setting = OGlobal::config()->readEntry("MouseButtonMapping");
+ if (setting == "RightHanded")
+ s.handed = OMouseSettings::RightHanded;
+ else if (setting == "LeftHanded")
+ s.handed = OMouseSettings::LeftHanded;
+ else
+ {
+
+ // FIXME: Implement for Opie / Qt Embedded
+
+ }
+ }
+ return *s_mouseSettings;
+}
+
+void OGlobalSettings::rereadMouseSettings()
+{
+ delete s_mouseSettings;
+ s_mouseSettings = 0L;
+}
+
+// FIXME: This won't be necessary, or will it? :-D
+
+bool OGlobalSettings::isMultiHead()
+{
+ QCString multiHead = getenv("OPIE_MULTIHEAD");
+ if (!multiHead.isEmpty()) {
+ return (multiHead.lower() == "true");
+ }
+ return false;
+}
diff --git a/libopie2/opiecore/oglobalsettings.h b/libopie2/opiecore/oglobalsettings.h
new file mode 100644
index 0000000..6481251
--- a/dev/null
+++ b/libopie2/opiecore/oglobalsettings.h
@@ -0,0 +1,368 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ Inspired by KDE OGlobalSettings
+ Copyright (C) 2000 David Faure <faure@kde.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef OGLOBALSETTINGS_H
+#define OGLOBALSETTINGS_H
+
+#include <qstring.h>
+#include <qcolor.h>
+#include <qfont.h>
+
+#define OPIE_DEFAULT_SINGLECLICK true
+#define OPIE_DEFAULT_INSERTTEAROFFHANDLES true
+#define OPIE_DEFAULT_AUTOSELECTDELAY -1
+#define OPIE_DEFAULT_CHANGECURSOR true
+#define OPIE_DEFAULT_LARGE_CURSOR false
+#define OPIE_DEFAULT_VISUAL_ACTIVATE true
+#define OPIE_DEFAULT_VISUAL_ACTIVATE_SPEED 50
+
+//FIXME: There's still a whole lot of stuff in here which has to be revised
+//FIXME: before public usage... lack of time to do it at once - so it will
+//FIXME: happen step-by-step. ML.
+
+/**
+ * Access the OPIE global configuration settings.
+ *
+ */
+class OGlobalSettings
+{
+ public:
+
+ /**
+ * Returns a threshold in pixels for drag & drop operations.
+ * As long as the mouse movement has not exceeded this number
+ * of pixels in either X or Y direction no drag operation may
+ * be started. This prevents spurious drags when the user intended
+ * to click on something but moved the mouse a bit while doing so.
+ *
+ * For this to work you must save the position of the mouse (oldPos)
+ * in the @ref QWidget::mousePressEvent().
+ * When the position of the mouse (newPos)
+ * in a @ref QWidget::mouseMoveEvent() exceeds this threshold
+ * you may start a drag
+ * which should originate from oldPos.
+ *
+ * Example code:
+ * <pre>
+ * void OColorCells::mousePressEvent( QMouseEvent *e )
+ * {
+ * mOldPos = e->pos();
+ * }
+ *
+ * void OColorCells::mouseMoveEvent( QMouseEvent *e )
+ * {
+ * if( !(e->state() && LeftButton)) return;
+ *
+ * int delay = OGlobalSettings::dndEventDelay();
+ * QPoint newPos = e->pos();
+ * if(newPos.x() > mOldPos.x()+delay || newPos.x() < mOldPos.x()-delay ||
+ * newPos.y() > mOldPos.y()+delay || newPos.y() < mOldPos.y()-delay)
+ * {
+ * // Drag color object
+ * int cell = posToCell(mOldPos); // Find color at mOldPos
+ * if ((cell != -1) && colors[cell].isValid())
+ * {
+ * OColorDrag *d = OColorDrag::makeDrag( colors[cell], this);
+ * d->dragCopy();
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ */
+
+ static int dndEventDelay();
+
+ /**
+ * Returns whether OPIE runs in single (default) or double click
+ * mode.
+ *
+ * @return @p true if single click mode, or @p false if double click mode.
+ *
+ * see @ref http://opie.handhelds.org/documentation/standards/opie/style/mouse/index.html
+ **/
+ static bool singleClick();
+
+ /**
+ * Returns whether tear-off handles are inserted in OPopupMenus.
+ **/
+ static bool insertTearOffHandle();
+
+ /**
+ * @return the OPIE setting for "change cursor over icon"
+ */
+ static bool changeCursorOverIcon();
+
+ /**
+ * @return whether to show some feedback when an item (specifically an
+ * icon) is activated.
+ */
+ static bool visualActivate();
+ static unsigned int visualActivateSpeed();
+
+ /**
+ * Returns the OPIE setting for the auto-select option
+ *
+ * @return the auto-select delay or -1 if auto-select is disabled.
+ */
+ static int autoSelectDelay();
+
+ /**
+ * Returns the OPIE setting for the shortcut key to open
+ * context menus.
+ *
+ * @return the key that pops up context menus.
+ */
+ static int contextMenuKey();
+
+ /**
+ * Returns the OPIE setting for context menus.
+ *
+ * @return whether context menus should be shown on button press
+ * or button release (click).
+ */
+ static bool showContextMenusOnPress ();
+
+ /**
+ * This enum describes the completion mode used for by the @ref OCompletion class.
+ * See <a href="http://opie.handhelds.org/documentation/standards/opie/style/keys/completion.html">
+ * the styleguide</a>.
+ **/
+ enum Completion {
+ /**
+ * No completion is used.
+ */
+ CompletionNone=1,
+ /**
+ * Text is automatically filled in whenever possible.
+ */
+ CompletionAuto,
+ /**
+ * Same as automatic except shortest match is used for completion.
+ */
+ CompletionMan,
+ /**
+ * Complete text much in the same way as a typical *nix shell would.
+ */
+ CompletionShell,
+ /**
+ * Lists all possible matches in a popup list-box to choose from.
+ */
+ CompletionPopup,
+ /**
+ * Lists all possible matches in a popup list-box to choose from, and automatically
+ * fill the result whenever possible.
+ */
+ CompletionPopupAuto
+ };
+ /**
+ * Returns the preferred completion mode setting.
+ *
+ * @return @ref Completion. Default is @p CompletionPopup.
+ */
+ static Completion completionMode();
+
+ /**
+ * This enum describes the debug mode used for by the @ref odbgstream class.
+ * See <a href="http://opie.handhelds.org/documentation/standards/opie/style/debug/debug.html">
+ * the styleguide</a>.
+ **/
+ enum Debug {
+ /**
+ * Debug messages are ignored.
+ */
+ DebugNone=-1,
+ /**
+ * Debug output is sent to files /var/log/***.
+ */
+ DebugFiles=0,
+ /**
+ * Debug output is written in a QMessageBox.
+ */
+ DebugMsgBox=1,
+ /**
+ * Debug output is sent to stderr.
+ */
+ DebugStdErr=2,
+ /**
+ * Debug output is sent to syslog.
+ */
+ DebugSysLog=3,
+ /**
+ * Debug output is sent via udp over a socket.
+ */
+ DebugSocket=4
+ };
+ /**
+ * Returns the preferred debug mode setting.
+ *
+ * @return @ref Debug. Default is @p DebugStdErr.
+ */
+ static Debug debugMode();
+
+ /**
+ * Returns additional information for debug output (dependent on the debug mode).
+ *
+ * @return Additional debug output information.
+ */
+ static QString debugOutput();
+ /**
+ * This is a structure containing the possible mouse settings.
+ */
+ struct OMouseSettings
+ {
+ enum { RightHanded = 0, LeftHanded = 1 };
+ int handed; // left or right
+ };
+
+ /**
+ * This returns the current mouse settings.
+ */
+ static OMouseSettings & mouseSettings();
+
+ /**
+ * The path to the desktop directory of the current user.
+ */
+ static QString desktopPath() { initStatic(); return *s_desktopPath; }
+
+ /**
+ * The path to the autostart directory of the current user.
+ */
+ static QString autostartPath() { initStatic(); return *s_autostartPath; }
+
+ /**
+ * The path to the trash directory of the current user.
+ */
+ static QString trashPath() { initStatic(); return *s_trashPath; }
+
+ /**
+ * The path where documents are stored of the current user.
+ */
+ static QString documentPath() { initStatic(); return *s_documentPath; }
+
+
+ /**
+ * The default color to use when highlighting toolbar buttons
+ */
+ static QColor toolBarHighlightColor();
+ static QColor inactiveTitleColor();
+ static QColor inactiveTextColor();
+ static QColor activeTitleColor();
+ static QColor activeTextColor();
+ static int contrast();
+
+ /**
+ * The default colors to use for text and links.
+ */
+ static QColor baseColor(); // Similair to QColorGroup::base()
+ static QColor textColor(); // Similair to QColorGroup::text()
+ static QColor linkColor();
+ static QColor visitedLinkColor();
+ static QColor highlightedTextColor(); // Similair to QColorGroup::hightlightedText()
+ static QColor highlightColor(); // Similair to QColorGroup::highlight()
+
+ /**
+ * Returns the alternate background color used by @ref OListView with
+ * @ref OListViewItem. Any other list that uses alternating background
+ * colors should use this too, to obey to the user's preferences. Returns
+ * an invalid color if the user doesn't want alternating backgrounds.
+ * @see #calculateAlternateBackgroundColor
+ */
+ static QColor alternateBackgroundColor();
+ /**
+ * Calculates a color based on @p base to be used as alternating
+ * color for e.g. listviews.
+ * @see #alternateBackgroundColor
+ */
+ static QColor calculateAlternateBackgroundColor(const QColor& base);
+
+
+ static QFont generalFont();
+ static QFont fixedFont();
+ static QFont toolBarFont();
+ static QFont menuFont();
+ static QFont windowTitleFont();
+ static QFont taskbarFont();
+
+ /**
+ * Returns if the user specified multihead. In case the display
+ * has multiple screens, the return value of this function specifies
+ * if the user wants OPIE to run on all of them or just on the primary
+ */
+ static bool isMultiHead();
+
+private:
+ /**
+ * reads in all paths from kdeglobals
+ */
+ static void initStatic();
+ /**
+ * initialise kde2Blue
+ */
+ static void initColors();
+ /**
+ * drop cached values for fonts (called by OApplication)
+ */
+ static void rereadFontSettings();
+ /**
+ * drop cached values for paths (called by OApplication)
+ */
+ static void rereadPathSettings();
+ /**
+ * drop cached values for mouse settings (called by OApplication)
+ */
+ static void rereadMouseSettings();
+
+
+ static QString* s_desktopPath;
+ static QString* s_autostartPath;
+ static QString* s_trashPath;
+ static QString* s_documentPath;
+ static QFont *_generalFont;
+ static QFont *_fixedFont;
+ static QFont *_toolBarFont;
+ static QFont *_menuFont;
+ static QFont *_windowTitleFont;
+ static QFont *_taskbarFont;
+ static QColor * kde2Gray;
+ static QColor * kde2Blue;
+ static QColor * kde2AlternateColor;
+ static OMouseSettings *s_mouseSettings;
+
+ static QColor * OpieGray;
+ static QColor * OpieBlue;
+ static QColor * OpieAlternate;
+ static QColor * OpieHighlight;
+
+ friend class OApplication;
+};
+
+#endif
diff --git a/libopie2/opiecore/opiecore.pro b/libopie2/opiecore/opiecore.pro
new file mode 100644
index 0000000..ed7d6d7
--- a/dev/null
+++ b/libopie2/opiecore/opiecore.pro
@@ -0,0 +1,31 @@
+TEMPLATE = lib
+CONFIG += qt warn_on debug
+DESTDIR = $(OPIEDIR)/lib
+HEADERS = oapplication.h \
+ oconfig.h \
+ ocompletionbase.h \
+ ocompletion.h \
+ odebug.h \
+ oglobal.h \
+ oglobalsettings.h \
+ osortablevaluelist.h
+
+SOURCES = oapplication.cpp \
+ oconfig.cpp \
+ ocompletionbase.cpp \
+ ocompletion.cpp \
+ odebug.cpp \
+ oglobal.cpp \
+ oglobalsettings.cpp
+
+INTERFACES =
+TARGET = opiecore2
+VERSION = 1.8.1
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+LIBS = -lqpe
+MOC_DIR = moc
+OBJECTS_DIR = obj
+
+include ( $(OPIEDIR)/include.pro )
+
diff --git a/libopie2/opiedb/config.in b/libopie2/opiedb/config.in
new file mode 100644
index 0000000..0205a83
--- a/dev/null
+++ b/libopie2/opiedb/config.in
@@ -0,0 +1,7 @@
+ config LIBOPIE2DB
+ boolean "libopie2db (database related classes)"
+ default "n"
+ depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE
+ comment "libopie2db needs a libqpe and libopie2core"
+ depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE)
+
diff --git a/libopie2/opiedb/opiedb.pro b/libopie2/opiedb/opiedb.pro
new file mode 100644
index 0000000..0d0ab78
--- a/dev/null
+++ b/libopie2/opiedb/opiedb.pro
@@ -0,0 +1,17 @@
+TEMPLATE = lib
+CONFIG += qt warn_on debug
+DESTDIR = $(OPIEDIR)/lib
+HEADERS =
+
+SOURCES =
+INTERFACES =
+TARGET = opiedb2
+VERSION = 1.8.1
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+
+MOC_DIR = moc
+OBJECTS_DIR = obj
+
+include ( $(OPIEDIR)/include.pro )
+
diff --git a/libopie2/opienet/.cvsignore b/libopie2/opienet/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/opienet/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/opienet/802_11_user.h b/libopie2/opienet/802_11_user.h
new file mode 100644
index 0000000..0b3f198
--- a/dev/null
+++ b/libopie2/opienet/802_11_user.h
@@ -0,0 +1,419 @@
+#ifndef IEEE_802_11
+#define IEEE_802_11
+
+enum ieee_802_11_link_status_failure_reason {
+ reserved0, Unspecified=1, Previous_not_valid,
+ Sender_Quits_ESS_or_IBSS,
+ Due_Inactivity, AP_Overload,
+ Class_2_from_NonAuth,
+ Class_3_from_NonAuth,
+ Sender_Quits_BSS,
+ Association_requester_not_authenticated,
+ Reserved10
+};
+
+
+#define IEEE_802_11_LINK_STATUS_FAILURE_REASON_STRINGS \
+{ \
+ {reserved0, 0xff," Reserved reason "},\
+ {Unspecified, 0xff," Unspecified Reason "},\
+ {Previous_not_valid, 0xff," Previous Authentication no longer valid "},\
+ {Sender_Quits_ESS_or_IBSS,0xff," Deauthenticated because sending station is leaving (has left) IBSS or ESS "},\
+ {Due_Inactivity, 0xff," Disassociated due to inactivity "},\
+ {AP_Overload, 0xff," Disassociated because AP is unable to handle all currently associated stations "},\
+ {Class_2_from_NonAuth, 0xff," Class 2 frame received from non-Authenticated station"},\
+ {Class_3_from_NonAuth, 0xff," Class 3 frame received from non­Associated station"},\
+ {Sender_Quits_BSS, 0xff," Disassociated because sending station is leaving (has left) BSS"},\
+ {Association_requester_not_authenticated,0xff," Station requesting (Re)Association is not Authenticated with responding station"},\
+ {Reserved10, 0xff," Reserved"},\
+ {0,0,NULL}\
+};
+
+
+
+struct ieee_802_11_header {
+ u_int16_t frame_control;// needs to be subtyped
+ u_int16_t duration;
+ u_int8_t mac1[6];
+ u_int8_t mac2[6];
+ u_int8_t mac3[6];
+ u_int16_t SeqCtl;
+ u_int8_t mac4[6];
+// u_int16_t gapLen;
+// u_int8_t gap[8];
+};
+
+
+struct ieee_802_3_header {
+
+ u_int16_t status;
+ u_int16_t payload_length;
+ u_int8_t dst_mac[6];
+ u_int8_t src_mac[6];
+
+};
+
+#define P80211_OUI_LEN 3
+
+struct ieee_802_11_snap_header {
+
+ u_int8_t dsap; /* always 0xAA */
+ u_int8_t ssap; /* always 0xAA */
+ u_int8_t ctrl; /* always 0x03 */
+ u_int8_t oui[P80211_OUI_LEN]; /* organizational universal id */
+
+} __attribute__ ((packed));
+
+#define P80211_LLC_OUI_LEN 3
+
+struct ieee_802_11_802_1H_header {
+
+ u_int8_t dsap;
+ u_int8_t ssap; /* always 0xAA */
+ u_int8_t ctrl; /* always 0x03 */
+ u_int8_t oui[P80211_OUI_LEN]; /* organizational universal id */
+ u_int16_t unknown1; /* packet type ID fields */
+ u_int16_t unknown2; /* here is something like length in some cases */
+} __attribute__ ((packed));
+
+struct ieee_802_11_802_2_header {
+
+ u_int8_t dsap;
+ u_int8_t ssap; /* always 0xAA */
+ u_int8_t ctrl; /* always 0x03 */
+ u_int8_t oui[P80211_OUI_LEN]; /* organizational universal id */
+ u_int16_t type; /* packet type ID field */
+
+} __attribute__ ((packed));
+
+
+
+// following is incoplete and may be incorrect and need reorganization
+
+#define ieee_802_11_frame_type_Management 0x00
+#define ieee_802_11_frame_type_Control 0x01
+#define ieee_802_11_frame_type_Data 0x10
+#define ieee_802_11_frame_type_Reserved 0x11
+
+#define ieee_802_11_frame_subtype_Association_Req 0x0 // Association Request
+#define ieee_802_11_frame_subtype_Association_Resp 0x1 // Association Response
+#define ieee_802_11_frame_subtype_Reassociation_Req 0x2 // Reassociation Request
+#define ieee_802_11_frame_subtype_Reassociation_Resp 0x3 // Reassociation Response
+#define ieee_802_11_frame_subtype_Probe_Req 0x4 // Probe Request
+#define ieee_802_11_frame_subtype_Probe_Resp 0x5 // Probe Response
+#define ieee_802_11_frame_subtype_Beacon 0x8 // Beacon
+#define ieee_802_11_frame_subtype_ATIM 0x9 // ATIM
+#define ieee_802_11_frame_subtype_Disassociation 0xA // Disassociation
+#define ieee_802_11_frame_subtype_Authentication 0xB // Authentication
+#define ieee_802_11_frame_subtype_Deauthentication 0xC // Deauthentication
+#define ieee_802_11_frame_subtype_PS_Poll 0xA // PS-Poll
+#define ieee_802_11_frame_subtype_RTS 0xB // RTS
+#define ieee_802_11_frame_subtype_CTS 0xC // CTS
+#define ieee_802_11_frame_subtype_ACK 0xD // ACK
+#define ieee_802_11_frame_subtype_CFEnd 0xE // CF-End
+#define ieee_802_11_frame_subtype_CFEnd_CFAck 0xF // CF-End + CF-Ack
+#define ieee_802_11_frame_subtype_Data 0x0 // Data
+#define ieee_802_11_frame_subtype_Data_CFAck 0x1 // Data + CF-Ack
+#define ieee_802_11_frame_subtype_Data_CF_Poll 0x2 // Data + CF-Poll
+#define ieee_802_11_frame_subtype_Data_CF_AckCF_Poll 0x3 // Data + CF-Ack + CF-Poll
+#define ieee_802_11_frame_subtype_NullFunction 0x4 // Null Function (no data)
+#define ieee_802_11_frame_subtype_CF_Ack 0x5 // CF-Ack (no data)
+#define ieee_802_11_frame_subtype_CF_Poll 0x6 // CF-Poll (no data)
+#define ieee_802_11_frame_subtype_CF_AckCF_Poll 0x7 // CF-Ack + CF-Poll (no data)
+
+
+#define ieee_802_11_frame_subtype_strings {\
+ { ieee_802_11_frame_subtype_Association_Req, 0xF,"f Association Request"},\
+ { ieee_802_11_frame_subtype_Association_Resp, 0xF,"1 Association Response"},\
+ { ieee_802_11_frame_subtype_Reassociation_Req, 0xF,"2 Reassociation Request"},\
+ { ieee_802_11_frame_subtype_Reassociation_Resp, 0xF,"3 Reassociation Response"},\
+ { ieee_802_11_frame_subtype_Probe_Req , 0xF,"4 Probe Request"},\
+ { ieee_802_11_frame_subtype_Probe_Resp , 0xF,"5 Probe Response"},\
+ { ieee_802_11_frame_subtype_Beacon , 0xF,"8 Beacon"},\
+ { ieee_802_11_frame_subtype_ATIM , 0xF,"9 ATIM"},\
+ { ieee_802_11_frame_subtype_Disassociation, 0xF,"A Disassociation"},\
+ { ieee_802_11_frame_subtype_Authentication, 0xF,"B Authentication"},\
+ { ieee_802_11_frame_subtype_Deauthentication, 0xF,"C Deauthentication"},\
+ { ieee_802_11_frame_subtype_PS_Poll , 0xF,"A PS-Poll"},\
+ { ieee_802_11_frame_subtype_RTS , 0xF,"B RTS"},\
+ { ieee_802_11_frame_subtype_CTS , 0xF,"C CTS"},\
+ { ieee_802_11_frame_subtype_ACK , 0xF,"D ACK"},\
+ { ieee_802_11_frame_subtype_CFEnd , 0xF,"E CF-End"},\
+ { ieee_802_11_frame_subtype_CFEnd_CFAck , 0xF,"F CF-End + CF-Ack"},\
+ { ieee_802_11_frame_subtype_Data , 0xF,"0 Data"},\
+ { ieee_802_11_frame_subtype_Data_CFAck , 0xF,"1 Data + CF-Ack"},\
+ { ieee_802_11_frame_subtype_Data_CFPoll , 0xF,"2 Data + CF-Poll"},\
+ { ieee_802_11_frame_subtype_Data_CFAck_CFPoll, 0xF,"3 Data + CF-Ack + CF-Poll"},\
+ { ieee_802_11_frame_subtype_Null_Function , 0xF,"4 Null Function (no data)"},\
+ { ieee_802_11_frame_subtype_CFAck , 0xF,"5 CF-Ack (no data)"},\
+ { ieee_802_11_frame_subtype_CFPoll , 0xF,"6 CF-Poll (no data)"},\
+ { ieee_802_11_frame_subtype_CFAck_CFPoll, 0xF,"y7 CF-Ack + CF-Poll (no data)"},\
+ { 0,0,NULL}\
+}
+struct ieee_802_11_frame_subtype_class {
+ u_int8_t subtype;
+ u_int8_t mask;
+ u_int8_t klass;
+ u_int8_t type;
+};
+#define ieee_802_11_frame_subtype_classes {\
+ { ieee_802_11_frame_subtype_Association_Req, 0xF,2,ieee_802_11_frame_type_Management},\
+ { ieee_802_11_frame_subtype_Association_Resp, 0xF,2,ieee_802_11_frame_type_Management},\
+ { ieee_802_11_frame_subtype_Reassociation_Req, 0xF,2,ieee_802_11_frame_type_Management},\
+ { ieee_802_11_frame_subtype_Reassociation_Resp, 0xF,2,ieee_802_11_frame_type_Management},\
+ { ieee_802_11_frame_subtype_Probe_Req , 0xF,1,ieee_802_11_frame_type_Management},\
+ { ieee_802_11_frame_subtype_Probe_Resp , 0xF,1,ieee_802_11_frame_type_Management},\
+ { ieee_802_11_frame_subtype_Beacon , 0xF,1,ieee_802_11_frame_type_Management},\
+ { ieee_802_11_frame_subtype_ATIM , 0xF,1,ieee_802_11_frame_type_Management},\
+ { ieee_802_11_frame_subtype_Disassociation, 0xF,2,ieee_802_11_frame_type_Management},\
+ { ieee_802_11_frame_subtype_Authentication, 0xF,1,ieee_802_11_frame_type_Management},\
+ { ieee_802_11_frame_subtype_Deauthentication, 0xF,3,ieee_802_11_frame_type_Management},\
+ { ieee_802_11_frame_subtype_PS-Poll , 0xF,3,ieee_802_11_frame_type_Control},\
+ { ieee_802_11_frame_subtype_RTS , 0xF,1,ieee_802_11_frame_type_Control},\
+ { ieee_802_11_frame_subtype_CTS , 0xF,1,ieee_802_11_frame_type_Control},\
+ { ieee_802_11_frame_subtype_ACK , 0xF,1,ieee_802_11_frame_type_Control},\
+ { ieee_802_11_frame_subtype_CFEnd , 0xF,1,ieee_802_11_frame_type_Control},\
+ { ieee_802_11_frame_subtype_CFEnd_CFAck , 0xF,1,ieee_802_11_frame_type_Control},\
+ { ieee_802_11_frame_subtype_Data , 0xF,3,ieee_802_11_frame_type_Data},\
+ { ieee_802_11_frame_subtype_Data_CFAck , 0xF,3,ieee_802_11_frame_type_Data},\
+ { ieee_802_11_frame_subtype_Data_CF_Poll 0xF,3,ieee_802_11_frame_type_Data},\
+ { ieee_802_11_frame_subtype_Data_CF_AckCF_Poll, 0xF,3,ieee_802_11_frame_type_Data},\
+ { ieee_802_11_frame_subtype_NullFunction 0xF,1,ieee_802_11_frame_type_Data},\
+ { ieee_802_11_frame_subtype_CF_Ack , 0xF,1,ieee_802_11_frame_type_Data},\
+ { ieee_802_11_frame_subtype_CF_Poll , 0xF,1,ieee_802_11_frame_type_Data},\
+ { ieee_802_11_frame_subtype_CF_AckCF_Poll, 0xF,1,ieee_802_11_frame_type_Data},\
+ { 0,0,NULL}\
+}
+
+#define IEEE802_11_FC_LEN 2
+
+#define T_MGMT 0x0 /* management */
+#define T_CTRL 0x1 /* control */
+#define T_DATA 0x2 /* data */
+#define T_RESV 0x3 /* reserved */
+
+#define ST_ASSOC_REQUEST 0x0
+#define ST_ASSOC_RESPONSE 0x1
+#define ST_REASSOC_REQUEST 0x2
+#define ST_REASSOC_RESPONSE 0x3
+#define ST_PROBE_REQUEST 0x4
+#define ST_PROBE_RESPONSE 0x5
+/* RESERVED 0x6 */
+/* RESERVED 0x7 */
+#define ST_BEACON 0x8
+#define ST_ATIM 0x9
+#define ST_DISASSOC 0xA
+#define ST_AUTH 0xB
+#define ST_DEAUTH 0xC
+/* RESERVED 0xD */
+/* RESERVED 0xE */
+/* RESERVED 0xF */
+
+
+#define CTRL_PS_POLL 0xA
+#define CTRL_RTS 0xB
+#define CTRL_CTS 0xC
+#define CTRL_ACK 0xD
+#define CTRL_CF_END 0xE
+#define CTRL_END_ACK 0xF
+
+/*
+ * Bits in the frame control field.
+ */
+#define FC_VERSION(fc) ((fc) & 0x3)
+#define FC_TYPE(fc) (((fc) >> 2) & 0x3)
+#define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF)
+#define FC_TO_DS(fc) ((fc) & 0x0100)
+#define FC_FROM_DS(fc) ((fc) & 0x0200)
+#define FC_MORE_FLAG(fc) ((fc) & 0x0400)
+#define FC_RETRY(fc) ((fc) & 0x0800)
+#define FC_POWER_MGMT(fc) ((fc) & 0x1000)
+#define FC_MORE_DATA(fc) ((fc) & 0x2000)
+#define FC_WEP(fc) ((fc) & 0x4000)
+#define FC_ORDER(fc) ((fc) & 0x8000)
+
+
+struct ieee_802_11_mgmt_header {
+ u_int16_t fc;
+ u_int16_t duration;
+ u_int8_t da[6];
+ u_int8_t sa[6];
+ u_int8_t bssid[6];
+ u_int16_t seq_ctrl;
+};
+
+
+struct ieee_802_11_data_header {
+ u_int16_t frame_control;
+ u_int16_t duration;
+ u_int8_t mac1[6];
+ u_int8_t mac2[6];
+ u_int8_t mac3[6];
+ u_int16_t SeqCtl;
+ u_int8_t mac4[6];
+// u_int16_t gapLen;
+// u_int8_t gap[8];
+};
+
+#define CAPABILITY_ESS(cap) ((cap) & 0x0001)
+#define CAPABILITY_IBSS(cap) ((cap) & 0x0002)
+#define CAPABILITY_CFP(cap) ((cap) & 0x0004)
+#define CAPABILITY_CFP_REQ(cap) ((cap) & 0x0008)
+#define CAPABILITY_PRIVACY(cap) ((cap) & 0x0010)
+
+struct ssid_t {
+ u_int8_t element_id;
+ u_int8_t length;
+ u_char ssid[33]; /* 32 + 1 for null */
+};
+
+
+struct rates_t {
+ u_int8_t element_id;
+ u_int8_t length;
+ u_int8_t rate[8];
+};
+
+
+struct challenge_t {
+ u_int8_t element_id;
+ u_int8_t length;
+ u_int8_t text[254]; /* 1-253 + 1 for null */
+};
+
+
+struct fh_t {
+ u_int8_t element_id;
+ u_int8_t length;
+ u_int16_t dwell_time;
+ u_int8_t hop_set;
+ u_int8_t hop_pattern;
+ u_int8_t hop_index;
+};
+
+
+struct ds_t {
+ u_int8_t element_id;
+ u_int8_t length;
+ u_int8_t channel;
+};
+
+
+struct cf_t {
+ u_int8_t element_id;
+ u_int8_t length;
+ u_int8_t count;
+ u_int8_t period;
+ u_int16_t max_duration;
+ u_int16_t dur_remaing;
+};
+
+
+struct tim_t {
+ u_int8_t element_id;
+ u_int8_t length;
+ u_int8_t count;
+ u_int8_t period;
+ u_int8_t bitmap_control;
+ u_int8_t bitmap[251];
+};
+
+#define E_SSID 0
+#define E_RATES 1
+#define E_FH 2
+#define E_DS 3
+#define E_CF 4
+#define E_TIM 5
+#define E_IBSS 6
+#define E_CHALLENGE 16
+#define E_CISCO 133
+
+
+struct ieee_802_11_mgmt_body {
+ u_int8_t timestamp[8];
+ u_int16_t beacon_interval;
+// u_int16_t listen_interval;
+// u_int16_t status_code;
+// u_int16_t aid;
+// u_char ap[6];
+// u_int16_t reason_code;
+// u_int16_t auth_alg;
+// u_int16_t auth_trans_seq_num;
+// struct challenge_t challenge;
+ u_int16_t capability_info;
+ struct ssid_t ssid;
+ struct rates_t rates;
+ struct ds_t ds;
+ struct cf_t cf;
+ struct fh_t fh;
+ struct tim_t tim;
+};
+
+
+struct ieee_802_11_data_body {
+//FIXME
+};
+
+struct ctrl_rts_t {
+ u_int16_t fc;
+ u_int16_t duration;
+ u_int8_t ra[6];
+ u_int8_t ta[6];
+ u_int8_t fcs[4];
+};
+
+#define CTRL_RTS_LEN (2+2+6+6+4)
+
+struct ctrl_cts_t {
+ u_int16_t fc;
+ u_int16_t duration;
+ u_int8_t ra[6];
+ u_int8_t fcs[4];
+};
+
+#define CTRL_CTS_LEN (2+2+6+4)
+
+struct ctrl_ack_t {
+ u_int16_t fc;
+ u_int16_t duration;
+ u_int8_t ra[6];
+ u_int8_t fcs[4];
+};
+
+#define CTRL_ACK_LEN (2+2+6+4)
+
+struct ctrl_ps_poll_t {
+ u_int16_t fc;
+ u_int16_t aid;
+ u_int8_t bssid[6];
+ u_int8_t ta[6];
+ u_int8_t fcs[4];
+};
+
+#define CTRL_PS_POLL_LEN (2+2+6+6+4)
+
+struct ctrl_end_t {
+ u_int16_t fc;
+ u_int16_t duration;
+ u_int8_t ra[6];
+ u_int8_t bssid[6];
+ u_int8_t fcs[4];
+};
+
+#define CTRL_END_LEN (2+2+6+6+4)
+
+struct ctrl_end_ack_t {
+ u_int16_t fc;
+ u_int16_t duration;
+ u_int8_t ra[6];
+ u_int8_t bssid[6];
+ u_int8_t fcs[4];
+};
+
+#define CTRL_END_ACK_LEN (2+2+6+6+4)
+
+#define IV_IV(iv) ((iv) & 0xFFFFFF)
+#define IV_PAD(iv) (((iv) >> 24) & 0x3F)
+#define IV_KEYID(iv) (((iv) >> 30) & 0x03)
+
+#endif
diff --git a/libopie2/opienet/config.in b/libopie2/opienet/config.in
new file mode 100644
index 0000000..5b235da
--- a/dev/null
+++ b/libopie2/opienet/config.in
@@ -0,0 +1,7 @@
+ config LIBOPIE2NET
+ boolean "libopie2net (network and packet capturing related classes)"
+ default "n"
+ depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE
+ comment "libopie2net needs a libqpe and libopie2core"
+ depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE)
+
diff --git a/libopie2/opienet/onetutils.cpp b/libopie2/opienet/onetutils.cpp
new file mode 100644
index 0000000..8006f41
--- a/dev/null
+++ b/libopie2/opienet/onetutils.cpp
@@ -0,0 +1,101 @@
+/*
+                 This file is part of the Opie Project
+
+              (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include <opie2/onetutils.h>
+
+#include <net/if.h>
+
+#include <cstdio>
+using namespace std;
+
+/*======================================================================================
+ * OMacAddress
+ *======================================================================================*/
+
+// static initializer for broadcast and unknown MAC Adresses
+const unsigned char __broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+const OMacAddress& OMacAddress::broadcast = OMacAddress( __broadcast );
+const unsigned char __unknown[6] = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 };
+const OMacAddress& OMacAddress::unknown = OMacAddress( __unknown );
+
+
+//TODO: Incorporate Ethernet Manufacturer database here!
+
+OMacAddress::OMacAddress( unsigned char* p )
+{
+ memcpy( _bytes, p, 6 ); // D'OH! memcpy in my sources... eeek...
+}
+
+
+OMacAddress::OMacAddress( const unsigned char* p )
+{
+ memcpy( _bytes, p, 6 );
+}
+
+
+OMacAddress::OMacAddress( struct ifreq& ifr )
+{
+ memcpy( _bytes, ifr.ifr_hwaddr.sa_data, 6 );
+}
+
+
+OMacAddress::~OMacAddress()
+{
+}
+
+
+QString OMacAddress::toString() const
+{
+ QString s;
+ s.sprintf( "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+ _bytes[0]&0xff, _bytes[1]&0xff, _bytes[2]&0xff,
+ _bytes[3]&0xff, _bytes[4]&0xff, _bytes[5]&0xff );
+ return s;
+}
+
+
+bool operator==( const OMacAddress &m1, const OMacAddress &m2 )
+{
+ return memcmp( &m1._bytes, &m2._bytes, 6 ) == 0;
+}
+
+void dumpBytes( const unsigned char* data, int num )
+{
+ printf( "Dumping %d bytes @ %0x", num, data );
+ printf( "-------------------------------------------\n" );
+
+ for ( int i = 0; i < num; ++i )
+ {
+ printf( "%02x ", data[i] );
+ if ( !((i+1) % 32) ) printf( "\n" );
+ }
+ printf( "\n\n" );
+}
diff --git a/libopie2/opienet/onetutils.h b/libopie2/opienet/onetutils.h
new file mode 100644
index 0000000..0dabe8d
--- a/dev/null
+++ b/libopie2/opienet/onetutils.h
@@ -0,0 +1,125 @@
+/*
+                 This file is part of the Opie Project
+
+              (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef ONETUTILS_H
+#define ONETUTILS_H
+
+#include <qdict.h>
+#include <qmap.h>
+#include <qstring.h>
+#include <qhostaddress.h>
+
+struct ifreq;
+
+/*======================================================================================
+ * OMacAddress
+ *======================================================================================*/
+
+class OMacAddress
+{
+ public:
+ OMacAddress( unsigned char* );
+ OMacAddress( const unsigned char* );
+ OMacAddress( struct ifreq& );
+ ~OMacAddress();
+
+ QString toString() const;
+
+ public:
+ static const OMacAddress& broadcast; // ff:ff:ff:ff:ff:ff
+ static const OMacAddress& unknown; // 44:44:44:44:44:44
+
+ private:
+ unsigned char _bytes[6];
+
+ friend bool operator==( const OMacAddress &m1, const OMacAddress &m2 );
+
+};
+
+bool operator==( const OMacAddress &m1, const OMacAddress &m2 );
+
+
+/*======================================================================================
+ * OHostAddress
+ *======================================================================================*/
+
+class OHostAddress : public QHostAddress
+{
+ public:
+ OHostAddress();
+ ~OHostAddress();
+};
+
+
+/*======================================================================================
+ * Miscellaneous
+ *======================================================================================*/
+
+/* dump bytes */
+
+void dumpBytes( const unsigned char* data, int num );
+
+/* Network to host order macros */
+
+#ifdef LBL_ALIGN
+#define EXTRACT_16BITS(p) \
+ ((u_int16_t)((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | \
+ (u_int16_t)*((const u_int8_t *)(p) + 1)))
+#define EXTRACT_32BITS(p) \
+ ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 0) << 24 | \
+ (u_int32_t)*((const u_int8_t *)(p) + 1) << 16 | \
+ (u_int32_t)*((const u_int8_t *)(p) + 2) << 8 | \
+ (u_int32_t)*((const u_int8_t *)(p) + 3)))
+#else
+#define EXTRACT_16BITS(p) \
+ ((u_int16_t)ntohs(*(const u_int16_t *)(p)))
+#define EXTRACT_32BITS(p) \
+ ((u_int32_t)ntohl(*(const u_int32_t *)(p)))
+#endif
+
+#define EXTRACT_24BITS(p) \
+ ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 0) << 16 | \
+ (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \
+ (u_int32_t)*((const u_int8_t *)(p) + 2)))
+
+/* Little endian protocol host order macros */
+#define EXTRACT_LE_8BITS(p) (*(p))
+#define EXTRACT_LE_16BITS(p) \
+ ((u_int16_t)((u_int16_t)*((const u_int8_t *)(p) + 1) << 8 | \
+ (u_int16_t)*((const u_int8_t *)(p) + 0)))
+#define EXTRACT_LE_32BITS(p) \
+ ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 3) << 24 | \
+ (u_int32_t)*((const u_int8_t *)(p) + 2) << 16 | \
+ (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \
+ (u_int32_t)*((const u_int8_t *)(p) + 0)))
+
+#endif // ONETUTILS_H
+
diff --git a/libopie2/opienet/onetwork.cpp b/libopie2/opienet/onetwork.cpp
new file mode 100644
index 0000000..1d3b9fe
--- a/dev/null
+++ b/libopie2/opienet/onetwork.cpp
@@ -0,0 +1,774 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) 2003 by the Wellenreiter team:
+ Martin J. Muench <mjm@remote-exploit.org>
+ Max Moser <mmo@remote-exploit.org
+ Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* OPIE */
+
+#include <opie2/onetwork.h>
+
+/* QT */
+
+#include <qfile.h>
+#include <qtextstream.h>
+
+/* UNIX */
+
+#include <arpa/inet.h>
+#include <cerrno>
+#include <cstring>
+#include <cstdlib>
+#include <math.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <linux/wireless.h>
+
+using namespace std;
+
+/*======================================================================================
+ * ONetwork
+ *======================================================================================*/
+
+ONetwork* ONetwork::_instance = 0;
+
+ONetwork::ONetwork()
+{
+ qDebug( "ONetwork::ONetwork()" );
+ synchronize();
+}
+
+void ONetwork::synchronize()
+{
+ // gather available interfaces by inspecting /proc/net/dev
+ // we could use SIOCGIFCONF here, but we aren't interested in virtual (e.g. eth0:0) devices
+
+ _interfaces.clear();
+ QString str;
+ QFile f( "/proc/net/dev" );
+ bool hasFile = f.open( IO_ReadOnly );
+ if ( !hasFile )
+ {
+ qDebug( "ONetwork: /proc/net/dev not existing. No network devices available" );
+ return;
+ }
+ QTextStream s( &f );
+ s.readLine();
+ s.readLine();
+ while ( !s.atEnd() )
+ {
+ s >> str;
+ str.truncate( str.find( ':' ) );
+ qDebug( "ONetwork: found interface '%s'", (const char*) str );
+ ONetworkInterface* iface;
+ if ( isWirelessInterface( str ) )
+ {
+ iface = new OWirelessNetworkInterface( str );
+ qDebug( "ONetwork: interface '%s' has Wireless Extensions", (const char*) str );
+ }
+ else
+ {
+ iface = new ONetworkInterface( str );
+ }
+ _interfaces.insert( str, iface );
+ s.readLine();
+ }
+}
+
+
+ONetworkInterface* ONetwork::interface( QString iface ) const
+{
+ return _interfaces[iface];
+}
+
+
+ONetwork* ONetwork::instance()
+{
+ if ( !_instance ) _instance = new ONetwork();
+ return _instance;
+}
+
+
+ONetwork::InterfaceIterator ONetwork::iterator() const
+{
+ return ONetwork::InterfaceIterator( _interfaces );
+}
+
+
+bool ONetwork::isWirelessInterface( const char* name ) const
+{
+ int sfd = socket( AF_INET, SOCK_DGRAM, 0 );
+ iwreqstruct iwr;
+ memset( &iwr, 0, sizeof( iwreqstruct ) );
+ strcpy( (char*) &iwr.ifr_name, name );
+ int result = ::ioctl( sfd, SIOCGIWNAME, &iwr );
+ if ( result == -1 )
+ qDebug( "ONetwork::ioctl(): SIOCGIWNAME failed: %d (%s)", result, strerror( errno ) );
+ else
+ qDebug( "ONetwork::ioctl(): SIOCGIWNAME ok." );
+ return ( result != -1 );
+}
+
+/*======================================================================================
+ * ONetworkInterface
+ *======================================================================================*/
+
+ONetworkInterface::ONetworkInterface( const QString& name )
+ :_name( name ), _sfd( socket( AF_INET, SOCK_DGRAM, 0 ) ), _mon( 0 )
+{
+ qDebug( "ONetworkInterface::ONetworkInterface()" );
+ init();
+}
+
+
+ifreqstruct& ONetworkInterface::ifr() const
+{
+ return _ifr;
+}
+
+
+void ONetworkInterface::init()
+{
+ qDebug( "ONetworkInterface::init()" );
+
+ memset( &_ifr, 0, sizeof( struct ifreq ) );
+
+ if ( _sfd == -1 )
+ {
+ qDebug( "ONetworkInterface::init(): Warning - can't get socket for device '%s'", (const char*) _name );
+ return;
+ }
+}
+
+
+bool ONetworkInterface::ioctl( int call, ifreqstruct& ifreq ) const
+{
+ int result = ::ioctl( _sfd, call, &ifreq );
+ if ( result == -1 )
+ qDebug( "ONetworkInterface::ioctl(): Call %d - Status: Failed: %d (%s)", call, result, strerror( errno ) );
+ else
+ qDebug( "ONetworkInterface::ioctl(): Call %d - Status: Ok.", call );
+ return ( result != -1 );
+}
+
+
+bool ONetworkInterface::ioctl( int call ) const
+{
+ strcpy( _ifr.ifr_name, (const char*) _name );
+ return ioctl( call, _ifr );
+}
+
+
+bool ONetworkInterface::isLoopback() const
+{
+ ioctl( SIOCGIFFLAGS );
+ return _ifr.ifr_flags & IFF_LOOPBACK;
+}
+
+
+bool ONetworkInterface::setUp( bool b )
+{
+ ioctl( SIOCGIFFLAGS );
+ if ( b ) _ifr.ifr_flags |= IFF_UP;
+ else _ifr.ifr_flags &= (~IFF_UP);
+ return ioctl( SIOCSIFFLAGS );
+}
+
+
+bool ONetworkInterface::isUp() const
+{
+ ioctl( SIOCGIFFLAGS );
+ return _ifr.ifr_flags & IFF_UP;
+}
+
+
+QString ONetworkInterface::ipV4Address() const
+{
+ if ( ioctl( SIOCGIFADDR ) )
+ {
+ struct sockaddr_in *sa = (struct sockaddr_in *) &_ifr.ifr_addr;
+ //FIXME: Use QHostAddress here
+ return QString( inet_ntoa( sa->sin_addr ) );
+ }
+ else
+ return "<unknown>";
+}
+
+
+OMacAddress ONetworkInterface::macAddress() const
+{
+ if ( ioctl( SIOCGIFHWADDR ) )
+ {
+ return OMacAddress( _ifr );
+ }
+ else
+ {
+ return OMacAddress::unknown;
+ }
+}
+
+
+void ONetworkInterface::setMonitoring( OMonitoringInterface* m )
+{
+ _mon = m;
+ qDebug( "ONetwork::setMonitoring(): Installed monitoring interface '%s'", (const char*) m->name() );
+}
+
+
+OMonitoringInterface* ONetworkInterface::monitoring() const
+{
+ return _mon;
+}
+
+
+const QString& ONetworkInterface::name() const
+{
+ return _name;
+}
+
+
+ONetworkInterface::~ONetworkInterface()
+{
+ qDebug( "ONetworkInterface::~ONetworkInterface()" );
+ if ( _sfd != -1 ) ::close( _sfd );
+}
+
+
+bool ONetworkInterface::setPromiscuousMode( bool b )
+{
+ ioctl( SIOCGIFFLAGS );
+ if ( b ) _ifr.ifr_flags |= IFF_PROMISC;
+ else _ifr.ifr_flags &= (~IFF_PROMISC);
+ return ioctl( SIOCSIFFLAGS );
+}
+
+
+bool ONetworkInterface::promiscuousMode() const
+{
+ ioctl( SIOCGIFFLAGS );
+ return _ifr.ifr_flags & IFF_PROMISC;
+}
+
+
+bool ONetworkInterface::isWireless() const
+{
+ return ioctl( SIOCGIWNAME );
+}
+
+
+/*======================================================================================
+ * OChannelHopper
+ *======================================================================================*/
+
+OChannelHopper::OChannelHopper( OWirelessNetworkInterface* iface )
+ :QObject( 0, "Mickey's funky hopper" ),
+ _iface( iface ), _interval( 0 ), _channel( 0 ), _tid( 0 )
+{
+}
+
+
+OChannelHopper::~OChannelHopper()
+{
+}
+
+
+void OChannelHopper::timerEvent( QTimerEvent* )
+{
+ //FIXME: Get available channels from OWirelessNetworkInterface
+ if ( --_channel < 0 ) _channel = 13;
+ _iface->setChannel( _channel );
+ qDebug( "OChannelHopper::timerEvent(): set channel %d on interface '%s'",
+ _channel, (const char*) _iface->name() );
+}
+
+
+void OChannelHopper::setInterval( int interval )
+{
+ if ( interval == _interval )
+ return;
+
+ if ( _interval )
+ killTimer( _tid );
+
+ _interval = interval;
+
+ if ( _interval )
+ {
+ _tid = startTimer( interval );
+ }
+}
+
+
+int OChannelHopper::interval() const
+{
+ return _interval;
+}
+
+
+/*======================================================================================
+ * OWirelessNetworkInterface
+ *======================================================================================*/
+
+OWirelessNetworkInterface::OWirelessNetworkInterface( const QString& name )
+ :ONetworkInterface( name ), _hopper( this )
+{
+ qDebug( "OWirelessNetworkInterface::OWirelessNetworkInterface()" );
+ init();
+}
+
+
+OWirelessNetworkInterface::~OWirelessNetworkInterface()
+{
+}
+
+
+iwreqstruct& OWirelessNetworkInterface::iwr() const
+{
+ return _iwr;
+}
+
+
+void OWirelessNetworkInterface::init()
+{
+ qDebug( "OWirelessNetworkInterface::init()" );
+
+ memset( &_iwr, 0, sizeof( struct iwreq ) );
+
+ // IEEE802.11(b) radio frequency channels
+ //FIXME: get these directly from the interface
+ //FIXME: check if these channels are off-by-one
+
+ iwrangestruct range;
+ _iwr.u.data.pointer = (char*) &range;
+ _iwr.u.data.length = sizeof( iwrangestruct );
+ if ( !wioctl( SIOCGIWRANGE ) )
+ {
+ qDebug( "OWirelessNetworkInterface::init(): SIOCGIWRANGE failed (%s)", strerror( errno ) );
+ return;
+ }
+
+ //TODO: Find out what the difference between num_channel and
+ // num_frequency is about.
+
+ for ( int i = 0; i < range.num_frequency; ++i )
+ {
+ int freq = (int) ( double( range.freq[i].m ) * pow( 10, range.freq[i].e ) / 1000000.0 );
+ _channels.insert( freq, i );
+ }
+}
+
+
+QString OWirelessNetworkInterface::associatedAP() const
+{
+ //FIXME: use OMacAddress
+ QString mac;
+
+ if ( ioctl( SIOCGIWAP ) )
+ {
+ mac.sprintf( "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+ _ifr.ifr_hwaddr.sa_data[0]&0xff,
+ _ifr.ifr_hwaddr.sa_data[1]&0xff,
+ _ifr.ifr_hwaddr.sa_data[2]&0xff,
+ _ifr.ifr_hwaddr.sa_data[3]&0xff,
+ _ifr.ifr_hwaddr.sa_data[4]&0xff,
+ _ifr.ifr_hwaddr.sa_data[5]&0xff );
+ }
+ else
+ {
+ mac = "<Unknown>";
+ }
+ return mac;
+}
+
+
+int OWirelessNetworkInterface::channel() const
+{
+ if ( !wioctl( SIOCGIWFREQ ) )
+ {
+ return -1;
+ }
+ else
+ {
+ //FIXME: This is off-by-one !? Why?
+ return _channels[ static_cast<int>(double( _iwr.u.freq.m ) * pow( 10, _iwr.u.freq.e ) / 1000000) ];
+ }
+}
+
+
+void OWirelessNetworkInterface::setChannel( int c ) const
+{
+ if ( !_mon )
+ {
+ memset( &_iwr, 0, sizeof( iwreqstruct ) );
+ _iwr.u.freq.m = c;
+ _iwr.u.freq.e = 0;
+ wioctl( SIOCSIWFREQ );
+ }
+ else
+ {
+ _mon->setChannel( c );
+ }
+}
+
+
+double OWirelessNetworkInterface::frequency() const
+{
+ if ( !wioctl( SIOCGIWFREQ ) )
+ {
+ return -1.0;
+ }
+ else
+ {
+ return double( _iwr.u.freq.m ) * pow( 10, _iwr.u.freq.e ) / 1000000000.0;
+ }
+}
+
+
+int OWirelessNetworkInterface::channels() const
+{
+ return _channels.count();
+}
+
+
+void OWirelessNetworkInterface::setChannelHopping( int interval )
+{
+ _hopper.setInterval( interval );
+}
+
+
+int OWirelessNetworkInterface::channelHopping() const
+{
+ return _hopper.interval();
+}
+
+
+void OWirelessNetworkInterface::setMonitorMode( bool b )
+{
+ if ( _mon )
+ _mon->setEnabled( b );
+ else
+ qDebug( "ONetwork(): can't switch monitor mode without installed monitoring interface" );
+}
+
+bool OWirelessNetworkInterface::monitorMode() const
+{
+ return _mon ? _mon->enabled() : false;
+}
+
+
+QString OWirelessNetworkInterface::nickName() const
+{
+ char str[IW_ESSID_MAX_SIZE];
+ _iwr.u.data.pointer = &str[0];
+ _iwr.u.data.length = IW_ESSID_MAX_SIZE;
+ if ( !wioctl( SIOCGIWNICKN ) )
+ {
+ return "<unknown>";
+ }
+ else
+ {
+ str[_iwr.u.data.length] = 0x0; // some drivers (e.g. wlan-ng) don't zero-terminate the string
+ return str;
+ }
+}
+
+
+QString OWirelessNetworkInterface::SSID() const
+{
+ char str[IW_ESSID_MAX_SIZE];
+ _iwr.u.essid.pointer = &str[0];
+ _iwr.u.essid.length = IW_ESSID_MAX_SIZE;
+ if ( !wioctl( SIOCGIWESSID ) )
+ {
+ return "<unknown>";
+ }
+ else
+ {
+ return str;
+ }
+}
+
+
+void OWirelessNetworkInterface::setSSID( const QString& ssid )
+{
+ _iwr.u.essid.pointer = const_cast<char*>( (const char*) ssid );
+ _iwr.u.essid.length = ssid.length();
+ wioctl( SIOCSIWESSID );
+}
+
+
+bool OWirelessNetworkInterface::wioctl( int call, iwreqstruct& iwreq ) const
+{
+ int result = ::ioctl( _sfd, call, &iwreq );
+ if ( result == -1 )
+ qDebug( "ONetworkInterface::wioctl(): Call %d - Status: Failed: %d (%s)", call, result, strerror( errno ) );
+ else
+ qDebug( "ONetworkInterface::wioctl(): Call %d - Status: Ok.", call );
+ return ( result != -1 );
+}
+
+
+bool OWirelessNetworkInterface::wioctl( int call ) const
+{
+ strcpy( _iwr.ifr_name, (const char*) _name );
+ return wioctl( call, _iwr );
+}
+
+
+/*======================================================================================
+ * OMonitoringInterface
+ *======================================================================================*/
+
+OMonitoringInterface::OMonitoringInterface( ONetworkInterface* iface )
+ :_enabled( false ), _if( static_cast<OWirelessNetworkInterface*>( iface ) )
+{
+}
+
+
+OMonitoringInterface::~OMonitoringInterface()
+{
+}
+
+
+void OMonitoringInterface::setChannel( int c )
+{
+ // use standard WE channel switching protocol
+ memset( &_if->_iwr, 0, sizeof( iwreqstruct ) );
+ _if->_iwr.u.freq.m = c;
+ _if->_iwr.u.freq.e = 0;
+ _if->wioctl( SIOCSIWFREQ );
+}
+
+
+bool OMonitoringInterface::enabled() const
+{
+ return _enabled;
+}
+
+void OMonitoringInterface::setEnabled( bool b )
+{
+ // open a packet capturer here or leave this to
+ // the client code?
+
+ /*
+
+ if ( b )
+ {
+ OPacketCapturer* opcap = new OPacketCapturer();
+ opcap->open( _if->name() );
+ }
+ */
+
+ _enabled = b;
+
+}
+
+/*======================================================================================
+ * OCiscoMonitoringInterface
+ *======================================================================================*/
+
+OCiscoMonitoringInterface::OCiscoMonitoringInterface( ONetworkInterface* iface )
+ :OMonitoringInterface( iface )
+{
+ iface->setMonitoring( this );
+}
+
+
+OCiscoMonitoringInterface::~OCiscoMonitoringInterface()
+{
+}
+
+
+void OCiscoMonitoringInterface::setEnabled( bool b )
+{
+ QString fname;
+ fname.sprintf( "/proc/driver/aironet/%s", (const char*) _if->name() );
+ QFile f( fname );
+ if ( !f.exists() ) return;
+
+ if ( f.open( IO_WriteOnly ) )
+ {
+ QTextStream s( &f );
+ s << "Mode: r";
+ s << "Mode: y";
+ s << "XmitPower: 1";
+
+ OMonitoringInterface::setEnabled( b );
+
+ }
+
+ // flushing and closing will be done automatically when f goes out of scope
+}
+
+
+QString OCiscoMonitoringInterface::name() const
+{
+ return "cisco";
+}
+
+
+void OCiscoMonitoringInterface::setChannel( int )
+{
+ // cisco devices automatically switch channels when in monitor mode
+}
+
+
+/*======================================================================================
+ * OWlanNGMonitoringInterface
+ *======================================================================================*/
+
+
+OWlanNGMonitoringInterface::OWlanNGMonitoringInterface( ONetworkInterface* iface )
+ :OMonitoringInterface( iface )
+{
+ iface->setMonitoring( this );
+}
+
+
+OWlanNGMonitoringInterface::~OWlanNGMonitoringInterface()
+{
+}
+
+
+void OWlanNGMonitoringInterface::setEnabled( bool b )
+{
+ //FIXME: do nothing if its already in the same mode
+
+ QString enable = b ? "true" : "false";
+ QString cmd;
+ cmd.sprintf( "$(which wlanctl-ng) %s lnxreq_wlansniff channel=%d enable=%s", (const char*) _if->name(), 1, (const char*) enable );
+ system( cmd );
+
+ OMonitoringInterface::setEnabled( b );
+}
+
+
+QString OWlanNGMonitoringInterface::name() const
+{
+ return "wlan-ng";
+}
+
+
+void OWlanNGMonitoringInterface::setChannel( int )
+{
+ // wlan-ng devices automatically switch channels when in monitor mode
+}
+
+
+/*======================================================================================
+ * OHostAPMonitoringInterface
+ *======================================================================================*/
+
+OHostAPMonitoringInterface::OHostAPMonitoringInterface( ONetworkInterface* iface )
+ :OMonitoringInterface( iface )
+{
+ iface->setMonitoring( this );
+}
+
+OHostAPMonitoringInterface::~OHostAPMonitoringInterface()
+{
+}
+
+void OHostAPMonitoringInterface::setEnabled( bool b )
+{
+ // IW_MODE_MONITOR was introduced in Wireless Extensions Version 15
+ // Wireless Extensions < Version 15 need iwpriv commandos for monitoring
+
+ #if WIRELESS_EXT > 14
+ _if->_iwr.u.mode = IW_MODE_MONITOR;
+ _if->wioctl( SIOCSIWMODE );
+ #else
+ int* args = (int*) &_if._iwr.u.name;
+ args[0] = 2;
+ args[1] = 0;
+ _if->wioctl( SIOCDEVPRIVATE );
+ #endif
+
+ OMonitoringInterface::setEnabled( b );
+}
+
+
+QString OHostAPMonitoringInterface::name() const
+{
+ return "hostap";
+}
+
+
+/*======================================================================================
+ * OOrinocoNetworkInterface
+ *======================================================================================*/
+
+OOrinocoMonitoringInterface::OOrinocoMonitoringInterface( ONetworkInterface* iface )
+ :OMonitoringInterface( iface )
+{
+ iface->setMonitoring( this );
+}
+
+
+OOrinocoMonitoringInterface::~OOrinocoMonitoringInterface()
+{
+}
+
+
+void OOrinocoMonitoringInterface::setChannel( int c )
+{
+ // call iwpriv <device> monitor 2 <channel>
+ int* args = (int*) &_if->_iwr.u.name;
+ args[0] = 2;
+ args[1] = c;
+ _if->wioctl( SIOCIWFIRSTPRIV + 0x8 );
+}
+
+
+void OOrinocoMonitoringInterface::setEnabled( bool b )
+{
+ if ( b )
+ {
+ setChannel( 1 );
+ }
+ else
+ {
+ // call iwpriv <device> monitor 0 0
+ int* args = (int*) &_if->_iwr.u.name;
+ args[0] = 0;
+ args[1] = 0;
+ _if->wioctl( SIOCIWFIRSTPRIV + 0x8 );
+ }
+
+ OMonitoringInterface::setEnabled( b );
+}
+
+
+QString OOrinocoMonitoringInterface::name() const
+{
+ return "orinoco";
+}
diff --git a/libopie2/opienet/onetwork.h b/libopie2/opienet/onetwork.h
new file mode 100644
index 0000000..9a68a74
--- a/dev/null
+++ b/libopie2/opienet/onetwork.h
@@ -0,0 +1,307 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) 2003 by the Wellenreiter team:
+ Martin J. Muench <mjm@remote-exploit.org>
+ Max Moser <mmo@remote-exploit.org
+ Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef ONETWORK_H
+#define ONETWORK_H
+
+/* QT */
+
+#include <qdict.h>
+#include <qmap.h>
+#include <qobject.h>
+#include <qhostaddress.h>
+
+/* OPIE */
+
+#include <opie2/onetutils.h>
+
+// ML: Yeah, I hate to include kernel headers, but it's necessary here
+// ML: Recent RedHat and MandrakePatches to the Kernel and WE broke something
+// ML: #include <net/if.h> e.g. conflicts with #include <linux/wireless.h>
+#define IFNAMSIZ 16
+#include <linux/wireless.h>
+#include <net/if.h>
+
+class ONetworkInterface;
+class OWirelessNetworkInterface;
+class OChannelHopper;
+class OMonitoringInterface;
+
+typedef struct ifreq ifreqstruct;
+typedef struct iwreq iwreqstruct;
+typedef struct iw_event iweventstruct;
+typedef struct iw_freq iwfreqstruct;
+typedef struct iw_priv_args iwprivargsstruct;
+typedef struct iw_range iwrangestruct;
+
+/*======================================================================================
+ * ONetwork
+ *======================================================================================*/
+
+class ONetwork : public QObject
+{
+ Q_OBJECT
+
+ public:
+ typedef QDict<ONetworkInterface> InterfaceMap;
+ typedef QDictIterator<ONetworkInterface> InterfaceIterator;
+
+ public:
+ static ONetwork* instance();
+ InterfaceIterator iterator() const;
+ bool isWirelessInterface( const char* ) const;
+ ONetworkInterface* interface( QString ) const;
+
+ protected:
+ ONetwork();
+ void synchronize();
+
+ private:
+ static ONetwork* _instance;
+ InterfaceMap _interfaces;
+};
+
+
+/*======================================================================================
+ * ONetworkInterface
+ *======================================================================================*/
+
+class ONetworkInterface
+{
+ friend class OMonitoringInterface;
+ friend class OCiscoMonitoringInterface;
+ friend class OWlanNGMonitoringInterface;
+ friend class OHostAPMonitoringInterface;
+ friend class OOrinocoMonitoringInterface;
+
+ public:
+ ONetworkInterface( const QString& name );
+ virtual ~ONetworkInterface();
+
+ const QString& name() const;
+ void setMonitoring( OMonitoringInterface* );
+ OMonitoringInterface* monitoring() const;
+ bool setPromiscuousMode( bool );
+ bool promiscuousMode() const;
+ bool setUp( bool );
+ bool isUp() const;
+ bool isLoopback() const;
+ bool isWireless() const;
+ QString ipV4Address() const;
+ OMacAddress macAddress() const;
+
+ protected:
+ const QString _name;
+ const int _sfd;
+ mutable ifreqstruct _ifr;
+ OMonitoringInterface* _mon;
+
+ protected:
+ ifreqstruct& ifr() const;
+ virtual void init();
+ bool ioctl( int call ) const;
+ bool ioctl( int call, ifreqstruct& ) const;
+};
+
+/*======================================================================================
+ * OChannelHopper
+ *======================================================================================*/
+
+class OChannelHopper : public QObject
+{
+ public:
+ OChannelHopper( OWirelessNetworkInterface* );
+ virtual ~OChannelHopper();
+ virtual void timerEvent( QTimerEvent* );
+ void setInterval( int );
+ int interval() const;
+
+ private:
+ OWirelessNetworkInterface* _iface;
+ int _interval;
+ int _channel;
+ int _tid;
+};
+
+
+/*======================================================================================
+ * OWirelessNetworkInterface
+ *======================================================================================*/
+
+class OWirelessNetworkInterface : public ONetworkInterface
+{
+ friend class OMonitoringInterface;
+ friend class OCiscoMonitoringInterface;
+ friend class OWlanNGMonitoringInterface;
+ friend class OHostAPMonitoringInterface;
+ friend class OOrinocoMonitoringInterface;
+
+ public:
+ enum Mode { AdHoc, Managed, Monitor };
+
+ OWirelessNetworkInterface( const QString& name );
+ virtual ~OWirelessNetworkInterface();
+
+ virtual void setChannel( int ) const;
+ virtual int channel() const;
+ virtual double frequency() const;
+ virtual int channels() const;
+ //virtual double frequency(int) const;
+
+ virtual void setMode( Mode ) {};
+ virtual bool mode() const {};
+
+ virtual void setMonitorMode( bool );
+ virtual bool monitorMode() const;
+
+ virtual void setChannelHopping( int interval );
+ virtual int channelHopping() const;
+
+ virtual void setNickName( const QString& ) {};
+ virtual QString nickName() const;
+
+ virtual bool isAssociated() const {};
+ virtual QString associatedAP() const;
+
+ virtual void setSSID( const QString& );
+ virtual QString SSID() const;
+
+ protected:
+ mutable iwreqstruct _iwr;
+ QMap<int,int> _channels;
+
+ protected:
+ virtual void init();
+ iwreqstruct& iwr() const;
+ bool wioctl( int call ) const;
+ bool wioctl( int call, iwreqstruct& ) const;
+
+ private:
+ OChannelHopper _hopper;
+};
+
+
+/*======================================================================================
+ * OMonitoringInterface
+ *======================================================================================*/
+
+
+class OMonitoringInterface
+{
+ public:
+ OMonitoringInterface();
+ OMonitoringInterface( ONetworkInterface* );
+ virtual ~OMonitoringInterface();
+
+ public:
+ virtual void setEnabled( bool );
+ virtual bool enabled() const;
+ virtual void setChannel( int );
+
+ virtual QString name() const = 0;
+
+ protected:
+ bool _enabled;
+ const OWirelessNetworkInterface* _if;
+
+};
+
+
+/*======================================================================================
+ * OCiscoMonitoring
+ *======================================================================================*/
+
+
+class OCiscoMonitoringInterface : public OMonitoringInterface
+{
+ public:
+ OCiscoMonitoringInterface( ONetworkInterface* );
+ virtual ~OCiscoMonitoringInterface();
+
+ virtual void setEnabled( bool );
+ virtual QString name() const;
+ virtual void setChannel( int );
+
+};
+
+/*======================================================================================
+ * OWlanNGMonitoringInterface
+ *======================================================================================*/
+
+class OWlanNGMonitoringInterface : public OMonitoringInterface
+{
+ public:
+ OWlanNGMonitoringInterface( ONetworkInterface* );
+ virtual ~OWlanNGMonitoringInterface();
+
+ public:
+ virtual void setEnabled( bool );
+ virtual QString name() const;
+ virtual void setChannel( int );
+
+};
+
+/*======================================================================================
+ * OHostAPMonitoringInterface
+ *======================================================================================*/
+
+class OHostAPMonitoringInterface : public OMonitoringInterface
+{
+ public:
+ OHostAPMonitoringInterface( ONetworkInterface* );
+ virtual ~OHostAPMonitoringInterface();
+
+ public:
+ virtual void setEnabled( bool );
+ virtual QString name() const;
+ };
+
+/*======================================================================================
+ * OOrinocoMonitoringInterface
+ *======================================================================================*/
+
+class OOrinocoMonitoringInterface : public OMonitoringInterface
+{
+ public:
+ OOrinocoMonitoringInterface( ONetworkInterface* );
+ virtual ~OOrinocoMonitoringInterface();
+
+ public:
+ virtual void setChannel( int );
+ virtual void setEnabled( bool );
+ virtual QString name() const;
+
+};
+
+#endif // ONETWORK_H
+
diff --git a/libopie2/opienet/opcap.cpp b/libopie2/opienet/opcap.cpp
new file mode 100644
index 0000000..48f874f
--- a/dev/null
+++ b/libopie2/opienet/opcap.cpp
@@ -0,0 +1,609 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) 2003 by the Wellenreiter team:
+ Martin J. Muench <mjm@remote-exploit.org>
+ Max Moser <mmo@remote-exploit.org
+ Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* OPIE */
+
+#include <opie2/opcap.h>
+
+/* QT */
+
+#include <qapplication.h> // don't use oapplication here (will decrease reusability in other projects)
+#include <qsocketnotifier.h>
+
+/*======================================================================================
+ * OPacket
+ *======================================================================================*/
+
+OPacket::OPacket( packetheaderstruct header, const unsigned char* data, QObject* parent )
+ :QObject( parent, "Generic" ), _hdr( header ), _data( data )
+{
+ qDebug( "OPacket::OPacket(): (Len %d, CapLen %d)" /*, ctime((const time_t*) header.ts.tv_sec)*/, header.len, header.caplen );
+
+ if ( packetCapturer()->dataLink() == DLT_EN10MB )
+ {
+ qDebug( "OPacket::OPacket(): Received Packet. Datalink = ETHERNET" );
+ new OEthernetPacket( (const struct ether_header*) data, this );
+ }
+ else
+ {
+ qDebug( "OPacket::OPacket(): Received Packet. Datalink = IEEE802.11" );
+ new OWaveLanPacket( (const struct ieee_802_11_header*) data, this );
+ }
+}
+
+
+OPacket::~OPacket()
+{
+}
+
+
+OPacketCapturer* OPacket::packetCapturer() const
+{
+ return parent()->inherits( "OPacketCapturer" ) ? static_cast<OPacketCapturer*>( parent() ) : 0;
+}
+
+
+timevalstruct OPacket::timeval() const
+{
+ return _hdr.ts;
+}
+
+
+int OPacket::caplen() const
+{
+ return _hdr.caplen;
+}
+
+
+void OPacket::dump() const
+{
+ printf( "OPacket::dump()\n" );
+ printf( "----------------\n" );
+
+ for ( int i = 0; i < _hdr.caplen; ++i )
+ {
+ printf( "%02x ", _data[i] );
+ if ( !((i+1) % 32) ) printf( "\n" );
+ }
+ printf( "\n\n" );
+}
+
+
+
+int OPacket::len() const
+{
+ return _hdr.len;
+}
+
+/*======================================================================================
+ * OEthernetPacket
+ *======================================================================================*/
+
+OEthernetPacket::OEthernetPacket( const struct ether_header* data, QObject* parent )
+ :QObject( parent, "Ethernet" ), _ether( data )
+
+{
+
+ qDebug( "Source = %s", (const char*) sourceAddress().toString() );
+ qDebug( "Destination = %s", (const char*) destinationAddress().toString() );
+
+ if ( sourceAddress() == OMacAddress::broadcast )
+ qDebug( "Source is broadcast address" );
+ if ( destinationAddress() == OMacAddress::broadcast )
+ qDebug( "Destination is broadcast address" );
+
+ switch ( type() )
+ {
+ case ETHERTYPE_IP: new OIPPacket( (const struct iphdr*) (data+1), this ); break;
+ case ETHERTYPE_ARP: { qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = ARP" ); break; }
+ case ETHERTYPE_REVARP: { qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = RARP" ); break; }
+ default: qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = UNKNOWN" );
+ }
+
+}
+
+
+OEthernetPacket::~OEthernetPacket()
+{
+}
+
+
+OMacAddress OEthernetPacket::sourceAddress() const
+{
+ return OMacAddress( _ether->ether_shost );
+}
+
+
+OMacAddress OEthernetPacket::destinationAddress() const
+{
+ return OMacAddress( _ether->ether_dhost );
+}
+
+int OEthernetPacket::type() const
+{
+ return ntohs( _ether->ether_type );
+}
+
+
+/*======================================================================================
+ * OIPPacket
+ *======================================================================================*/
+
+
+OIPPacket::OIPPacket( const struct iphdr* data, QObject* parent )
+ :QObject( parent, "IP" ), _iphdr( data )
+
+{
+ qDebug( "OIPPacket::OIPPacket(): decoding IP header..." );
+
+ //qDebug( "FromAddress: %s", (const char*) inet_ntoa( *src ) );
+ //qDebug( " ToAddress: %s", (const char*) inet_ntoa( *dst ) );
+
+ qDebug( "FromAddress: %s", (const char*) fromIPAddress().toString() );
+ qDebug( " toAddress: %s", (const char*) toIPAddress().toString() );
+
+ switch ( protocol() )
+ {
+ case IPPROTO_UDP: new OUDPPacket( (const struct udphdr*) (data+1), this ); break;
+ case IPPROTO_TCP: new OTCPPacket( (const struct tcphdr*) (data+1), this ); break;
+ default: qDebug( "OIPPacket::OIPPacket(): unknown IP protocol type = %d", protocol() );
+ }
+
+}
+
+OIPPacket::~OIPPacket()
+{
+}
+
+
+QHostAddress OIPPacket::fromIPAddress() const
+{
+ return EXTRACT_32BITS( &_iphdr->saddr );
+}
+
+
+QHostAddress OIPPacket::toIPAddress() const
+{
+ return EXTRACT_32BITS( &_iphdr->saddr );
+}
+
+
+int OIPPacket::tos() const
+{
+ return _iphdr->tos;
+}
+
+
+int OIPPacket::len() const
+{
+ return EXTRACT_16BITS( &_iphdr->tot_len );
+}
+
+
+int OIPPacket::id() const
+{
+ return EXTRACT_16BITS( &_iphdr->id );
+}
+
+
+int OIPPacket::offset() const
+{
+ return EXTRACT_16BITS( &_iphdr->frag_off );
+}
+
+
+int OIPPacket::ttl() const
+{
+ return _iphdr->ttl;
+}
+
+
+int OIPPacket::protocol() const
+{
+ return _iphdr->protocol;
+}
+
+
+int OIPPacket::checksum() const
+{
+ return EXTRACT_16BITS( &_iphdr->check );
+}
+
+/*======================================================================================
+ * OUDPPacket
+ *======================================================================================*/
+
+
+OUDPPacket::OUDPPacket( const struct udphdr* data, QObject* parent )
+ :QObject( parent, "UDP" ), _udphdr( data )
+
+{
+ qDebug( "OUDPPacket::OUDPPacket(): decoding UDP header..." );
+}
+
+OUDPPacket::~OUDPPacket()
+{
+}
+
+
+/*======================================================================================
+ * OTCPPacket
+ *======================================================================================*/
+
+
+OTCPPacket::OTCPPacket( const struct tcphdr* data, QObject* parent )
+ :QObject( parent, "TCP" ), _tcphdr( data )
+
+{
+ qDebug( "OTCPPacket::OTCPPacket(): decoding TCP header..." );
+}
+
+OTCPPacket::~OTCPPacket()
+{
+}
+
+
+/*======================================================================================
+ * OWaveLanPacket
+ *======================================================================================*/
+
+
+OWaveLanPacket::OWaveLanPacket( const struct ieee_802_11_header* data, QObject* parent )
+ :QObject( parent, "802.11" ), _wlanhdr( data )
+
+{
+ qDebug( "OWaveLanPacket::OWaveLanPacket(): decoding IEEE 802.11 header..." );
+ qDebug( "type: %0X", type() );
+ qDebug( "subType: %0X", subType() );
+ qDebug( "duration: %d", duration() );
+ qDebug( "powermanagement: %d", usesPowerManagement() );
+ qDebug( "wep: %d", usesWep() );
+ qDebug( "MAC1: %s", (const char*) macAddress1().toString() );
+ qDebug( "MAC2: %s", (const char*) macAddress2().toString() );
+ qDebug( "MAC3: %s", (const char*) macAddress3().toString() );
+ qDebug( "MAC4: %s", (const char*) macAddress4().toString() );
+
+ switch ( type() )
+ {
+ case T_MGMT: new OWaveLanManagementPacket( (const struct ieee_802_11_mgmt_header*) data, this ); break;
+ case T_DATA: new OWaveLanDataPacket( (const struct ieee_802_11_data_header*) data, this ); break;
+ //case T_CTRL: new OWaveLanControlPacket( (const struct ieee_802_11_ctrl_header*) data, this ); break;
+ default: qDebug( "OWaveLanPacket::OWaveLanPacket(): Warning: Unknown type!" );
+ }
+}
+
+OWaveLanPacket::~OWaveLanPacket()
+{
+}
+
+
+int OWaveLanPacket::duration() const
+{
+ return _wlanhdr->duration;
+}
+
+
+OMacAddress OWaveLanPacket::macAddress1() const
+{
+ return OMacAddress( _wlanhdr->mac1 );
+}
+
+
+OMacAddress OWaveLanPacket::macAddress2() const
+{
+ return OMacAddress( _wlanhdr->mac2 );
+}
+
+
+OMacAddress OWaveLanPacket::macAddress3() const
+{
+ return OMacAddress( _wlanhdr->mac3 );
+}
+
+
+OMacAddress OWaveLanPacket::macAddress4() const
+{
+ return OMacAddress( _wlanhdr->mac4 );
+}
+
+
+int OWaveLanPacket::subType() const
+{
+ return FC_SUBTYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
+}
+
+
+int OWaveLanPacket::type() const
+{
+ return FC_TYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
+}
+
+
+int OWaveLanPacket::version() const
+{
+ return FC_VERSION( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
+}
+
+
+bool OWaveLanPacket::fromDS() const
+{
+ return FC_FROM_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
+}
+
+
+bool OWaveLanPacket::toDS() const
+{
+ return FC_TO_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
+}
+
+
+bool OWaveLanPacket::usesPowerManagement() const
+{
+ return FC_POWER_MGMT( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
+}
+
+
+bool OWaveLanPacket::usesWep() const
+{
+ return FC_WEP( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
+}
+
+
+/*======================================================================================
+ * OWaveLanManagementPacket
+ *======================================================================================*/
+
+OWaveLanManagementPacket::OWaveLanManagementPacket( const struct ieee_802_11_mgmt_header* data, OWaveLanPacket* parent )
+ :QObject( parent, "802.11 Management" ), _header( data ),
+ _body( (const struct ieee_802_11_mgmt_body*) (data+1) )
+{
+ qDebug( "OWaveLanManagementPacket::OWaveLanManagementPacket(): decoding frame..." );
+
+ switch ( ((OWaveLanPacket*) this->parent() )->subType() )
+ {
+ case ST_BEACON:
+ {
+ qDebug( "TYPE: BEACON FRAME" );
+ qDebug( "ESSID: %s", (const char*) SSID() );
+ break;
+ }
+ }
+}
+
+
+OWaveLanManagementPacket::~OWaveLanManagementPacket()
+{
+}
+
+
+QString OWaveLanManagementPacket::SSID() const
+{
+ int length = _body->ssid.length;
+ if ( length > 32 ) length = 32;
+ char essid[length+1];
+ memcpy( &essid, _body->ssid.ssid, length );
+ essid[length] = 0x0;
+ return essid;
+}
+
+
+/*======================================================================================
+ * OWaveLanDataPacket
+ *======================================================================================*/
+
+OWaveLanDataPacket::OWaveLanDataPacket( const struct ieee_802_11_data_header* data, OWaveLanPacket* parent )
+ :QObject( parent, "802.11 Data" ), _header( data )
+{
+ //qDebug( "size of header = %d", sizeof( struct ieee_802_11_data_header ) );
+ //qDebug( "header: %0x", data );
+ const unsigned char* payload = (const unsigned char*) data + sizeof( struct ieee_802_11_data_header );
+ //qDebug( "payload: %0x", payload );
+
+ if (!( ( (OWaveLanPacket*) this->parent())->duration() )) payload -= 6; // compensation for missing last address
+
+ new OLLCPacket( (const struct ieee_802_11_802_2_header*) payload, this );
+}
+
+
+OWaveLanDataPacket::~OWaveLanDataPacket()
+{
+}
+
+
+/*======================================================================================
+ * OLLCPacket
+ *======================================================================================*/
+
+OLLCPacket::OLLCPacket( const struct ieee_802_11_802_2_header* data, QObject* parent )
+ :QObject( parent, "802.11 802_2" ), _header( data )
+{
+ qDebug( "OLLCPacket::OLLCPacket(): decoding frame..." );
+
+ if ( !(_header->oui[0] || _header->oui[1] || _header->oui[2]) )
+ {
+ qDebug( "OLLCPacket::OLLCPacket(): contains an encapsulated Ethernet frame (type=%04X)", EXTRACT_16BITS( &_header->type ) );
+
+ switch ( EXTRACT_16BITS( &_header->type ) ) // defined in linux/if_ether.h
+ {
+ case ETH_P_IP: new OIPPacket( (const struct iphdr*) (data+1), this ); break;
+ default: qDebug( "OLLCPacket::OLLCPacket(): Unknown Encapsulation Type" );
+ }
+
+ }
+}
+
+
+OLLCPacket::~OLLCPacket()
+{
+}
+
+/*======================================================================================
+ * OPacketCapturer
+ *======================================================================================*/
+
+OPacketCapturer::OPacketCapturer( QObject* parent, const char* name )
+ :QObject( parent, name ), _name( QString::null ), _open( false ),
+ _pch( 0 )
+{
+}
+
+
+OPacketCapturer::~OPacketCapturer()
+{
+ if ( _open )
+ {
+ qDebug( "OPacketCapturer::~OPacketCapturer(): pcap still open, autoclosing." );
+ close();
+ }
+}
+
+
+void OPacketCapturer::setBlocking( bool b )
+{
+ if ( pcap_setnonblock( _pch, 1-b, _errbuf ) != -1 )
+ {
+ qDebug( "OPacketCapturer::setBlocking(): blocking mode changed successfully." );
+ }
+ else
+ {
+ qDebug( "OPacketCapturer::setBlocking(): can't change blocking mode: %s", _errbuf );
+ }
+}
+
+
+bool OPacketCapturer::blocking() const
+{
+ int b = pcap_getnonblock( _pch, _errbuf );
+ if ( b == -1 )
+ {
+ qDebug( "OPacketCapturer::blocking(): can't get blocking mode: %s", _errbuf );
+ return -1;
+ }
+ return !b;
+}
+
+
+void OPacketCapturer::close()
+{
+ if ( _open )
+ {
+ pcap_close( _pch );
+ _open = false;
+ }
+}
+
+
+int OPacketCapturer::dataLink() const
+{
+ return pcap_datalink( _pch );
+}
+
+
+int OPacketCapturer::fileno() const
+{
+ if ( _open )
+ {
+ return pcap_fileno( _pch );
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+
+OPacket* OPacketCapturer::next()
+{
+ packetheaderstruct header;
+ const unsigned char* pdata = pcap_next( _pch, &header );
+ if ( header.len )
+ return new OPacket( header, pdata, this );
+ else
+ return 0;
+}
+
+
+bool OPacketCapturer::open( const QString& name )
+{
+ if ( _open )
+ {
+ if ( name == _name ) // ignore opening an already openend device
+ {
+ return true;
+ }
+ else // close the last opened device
+ {
+ close();
+ }
+ }
+
+ _name = name;
+
+ pcap_t* handle = pcap_open_live( const_cast<char*>( (const char*) name ), 1024, 0, 0, &_errbuf[0] );
+
+ if ( handle )
+ {
+ qDebug( "OPacketCapturer::open(): libpcap opened successfully." );
+ _pch = handle;
+ _open = true;
+
+ // in case we have a qapp, create a socket notifier
+ if ( qApp )
+ {
+ QSocketNotifier* sn = new QSocketNotifier( fileno(), QSocketNotifier::Read, this );
+ connect( sn, SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) );
+ }
+
+ return true;
+ }
+ else
+ {
+ qDebug( "OPacketCapturer::open(): can't open libpcap: %s", _errbuf );
+ return false;
+ }
+
+}
+
+
+bool OPacketCapturer::isOpen() const
+{
+ return _open;
+}
+
+
+void OPacketCapturer::readyToReceive()
+{
+ qDebug( "OPacketCapturer::readyToReceive(): about to emit 'receivePacket(...)'" );
+ emit receivedPacket( next() );
+}
+
diff --git a/libopie2/opienet/opcap.h b/libopie2/opienet/opcap.h
new file mode 100644
index 0000000..65c550c
--- a/dev/null
+++ b/libopie2/opienet/opcap.h
@@ -0,0 +1,294 @@
+/*
+                 This file is part of the Opie Project
+              Copyright (C) 2003 by the Wellenreiter team:
+ Martin J. Muench <mjm@remote-exploit.org>
+ Max Moser <mmo@remote-exploit.org
+ Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OPCAP_H
+#define OPCAP_H
+
+/* LINUX */
+extern "C" // work around a bpf/pcap conflict in recent headers
+{
+ #include <pcap.h>
+}
+#include <netinet/ether.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <time.h>
+
+/* QT */
+#include <qhostaddress.h>
+#include <qobject.h>
+#include <qstring.h>
+
+/* OPIE */
+#include <opie2/onetutils.h>
+#include "802_11_user.h"
+
+/* TYPEDEFS */
+typedef struct timeval timevalstruct;
+typedef struct pcap_pkthdr packetheaderstruct;
+
+/* FORWARDS */
+class OPacketCapturer;
+
+/*======================================================================================
+ * OPacket - A frame on the wire
+ *======================================================================================*/
+
+class OPacket : public QObject
+{
+ Q_OBJECT
+
+ public:
+ OPacket( packetheaderstruct, const unsigned char*, QObject* parent );
+ virtual ~OPacket();
+
+ timevalstruct timeval() const;
+
+ OPacketCapturer* packetCapturer() const;
+
+ int caplen() const;
+ int len() const;
+ void dump() const;
+
+ private:
+ const packetheaderstruct _hdr; // pcap packet header
+ const unsigned char* _data; // pcap packet data
+};
+
+/*======================================================================================
+ * OEthernetPacket - DLT_EN10MB frame
+ *======================================================================================*/
+
+class OEthernetPacket : public QObject
+{
+ Q_OBJECT
+
+ public:
+ OEthernetPacket( const struct ether_header*, QObject* parent = 0 );
+ virtual ~OEthernetPacket();
+
+ OMacAddress sourceAddress() const;
+ OMacAddress destinationAddress() const;
+ int type() const;
+
+ private:
+ const struct ether_header* _ether;
+};
+
+
+/*======================================================================================
+ * OWaveLanPacket - DLT_IEEE802_11 frame
+ *======================================================================================*/
+
+class OWaveLanPacket : public QObject
+{
+ Q_OBJECT
+
+ public:
+ OWaveLanPacket( const struct ieee_802_11_header*, QObject* parent = 0 );
+ virtual ~OWaveLanPacket();
+
+ int duration() const;
+ bool fromDS() const;
+ bool toDS() const;
+ virtual OMacAddress macAddress1() const;
+ virtual OMacAddress macAddress2() const;
+ virtual OMacAddress macAddress3() const;
+ virtual OMacAddress macAddress4() const;
+ bool usesPowerManagement() const;
+ int type() const;
+ int subType() const;
+ int version() const;
+ bool usesWep() const;
+
+ private:
+ const struct ieee_802_11_header* _wlanhdr;
+};
+
+
+/*======================================================================================
+ * OWaveLanManagementPacket - type: management (T_MGMT)
+ *======================================================================================*/
+
+class OWaveLanManagementPacket : public QObject
+{
+ Q_OBJECT
+
+ public:
+ OWaveLanManagementPacket( const struct ieee_802_11_mgmt_header*, OWaveLanPacket* parent = 0 );
+ virtual ~OWaveLanManagementPacket();
+
+ QString SSID() const;
+
+ private:
+ const struct ieee_802_11_mgmt_header* _header;
+ const struct ieee_802_11_mgmt_body* _body;
+};
+
+
+/*======================================================================================
+ * OWaveLanDataPacket - type: data (T_DATA)
+ *======================================================================================*/
+
+class OWaveLanDataPacket : public QObject
+{
+ Q_OBJECT
+
+ public:
+ OWaveLanDataPacket( const struct ieee_802_11_data_header*, OWaveLanPacket* parent = 0 );
+ virtual ~OWaveLanDataPacket();
+
+ private:
+ const struct ieee_802_11_data_header* _header;
+};
+
+/*======================================================================================
+ * OLLCPacket - IEEE 802.2 Link Level Control
+ *======================================================================================*/
+
+class OLLCPacket : public QObject
+{
+ Q_OBJECT
+
+ public:
+ OLLCPacket( const struct ieee_802_11_802_2_header* data, QObject* parent = 0 );
+ virtual ~OLLCPacket();
+
+ private:
+ const struct ieee_802_11_802_2_header* _header;
+};
+
+/*======================================================================================
+ * OIPPacket
+ *======================================================================================*/
+
+class OIPPacket : public QObject
+{
+ Q_OBJECT
+
+ public:
+ OIPPacket( const struct iphdr*, QObject* parent = 0 );
+ virtual ~OIPPacket();
+
+ QHostAddress fromIPAddress() const;
+ QHostAddress toIPAddress() const;
+
+ int tos() const;
+ int len() const;
+ int id() const;
+ int offset() const;
+ int ttl() const;
+ int protocol() const;
+ int checksum() const;
+
+ private:
+ const struct iphdr* _iphdr;
+};
+
+/*======================================================================================
+ * OUDPPacket
+ *======================================================================================*/
+
+class OUDPPacket : public QObject
+{
+ Q_OBJECT
+
+ public:
+ OUDPPacket( const struct udphdr*, QObject* parent = 0 );
+ virtual ~OUDPPacket();
+
+ int fromPort() const;
+ int toPort() const;
+
+ private:
+ const struct udphdr* _udphdr;
+};
+
+/*======================================================================================
+ * OTCPPacket
+ *======================================================================================*/
+
+class OTCPPacket : public QObject
+{
+ Q_OBJECT
+
+ public:
+ OTCPPacket( const struct tcphdr*, QObject* parent = 0 );
+ virtual ~OTCPPacket();
+
+ int fromPort() const;
+ int toPort() const;
+
+ private:
+ const struct tcphdr* _tcphdr;
+};
+
+
+/*======================================================================================
+ * OPacketCapturer
+ *======================================================================================*/
+
+class OPacketCapturer : public QObject
+{
+ Q_OBJECT
+
+ public:
+ OPacketCapturer( QObject* parent = 0, const char* name = 0 );
+ ~OPacketCapturer();
+
+ void setBlocking( bool );
+ bool blocking() const;
+
+ void close();
+ int dataLink() const;
+ int fileno() const;
+ OPacket* next();
+ bool open( const QString& name );
+ bool isOpen() const;
+
+ signals:
+ void receivedPacket( OPacket* );
+
+ protected slots:
+ void readyToReceive();
+
+ protected:
+ QString _name; // devicename
+ bool _open; // check this before doing pcap calls
+ pcap_t* _pch; // pcap library handle
+ mutable char _errbuf[PCAP_ERRBUF_SIZE];
+};
+
+#endif // OPCAP_H
+
diff --git a/libopie2/opienet/opienet.pro b/libopie2/opienet/opienet.pro
new file mode 100644
index 0000000..e73afbf
--- a/dev/null
+++ b/libopie2/opienet/opienet.pro
@@ -0,0 +1,18 @@
+TEMPLATE = lib
+CONFIG += qt warn_on debug
+DESTDIR = $(OPIEDIR)/lib
+HEADERS = onetutils.cpp onetwork.h opcap.h
+
+SOURCES = onetutils.cpp onetwork.cpp opcap.cpp
+INTERFACES =
+TARGET = opienet2
+VERSION = 1.8.1
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+LIBS += -lpcap
+
+MOC_DIR = moc
+OBJECTS_DIR = obj
+
+include ( $(OPIEDIR)/include.pro )
+
diff --git a/libopie2/opiepim/.cvsignore b/libopie2/opiepim/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/opiepim/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/opiepim/config.in b/libopie2/opiepim/config.in
new file mode 100644
index 0000000..79b8f46
--- a/dev/null
+++ b/libopie2/opiepim/config.in
@@ -0,0 +1,7 @@
+ config LIBOPIE2PIM
+ boolean "libopie2pim (pim related classes)"
+ default "n"
+ depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE
+ comment "libopie2pim needs a libqpe and libopie2core"
+ depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE)
+
diff --git a/libopie2/opiepim/opiepim.pro b/libopie2/opiepim/opiepim.pro
new file mode 100644
index 0000000..7fc7bb7
--- a/dev/null
+++ b/libopie2/opiepim/opiepim.pro
@@ -0,0 +1,17 @@
+TEMPLATE = lib
+CONFIG += qt warn_on debug
+DESTDIR = $(OPIEDIR)/lib
+HEADERS =
+
+SOURCES =
+INTERFACES =
+TARGET = opiepim2
+VERSION = 1.8.1
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+
+MOC_DIR = moc
+OBJECTS_DIR = obj
+
+include ( $(OPIEDIR)/include.pro )
+
diff --git a/libopie2/opieui/.cvsignore b/libopie2/opieui/.cvsignore
new file mode 100644
index 0000000..8f7300c
--- a/dev/null
+++ b/libopie2/opieui/.cvsignore
@@ -0,0 +1,6 @@
+Makefile*
+moc*
+*moc
+*.o
+~*
+
diff --git a/libopie2/opieui/config.in b/libopie2/opieui/config.in
new file mode 100644
index 0000000..d40b5d9
--- a/dev/null
+++ b/libopie2/opieui/config.in
@@ -0,0 +1,7 @@
+ config LIBOPIE2UI
+ boolean "libopie2ui (user interface related classes)"
+ default "n"
+ depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE
+ comment "libopie2ui needs a libqpe and libopie2core"
+ depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE)
+
diff --git a/libopie2/opieui/odialog.cpp b/libopie2/opieui/odialog.cpp
new file mode 100644
index 0000000..00a7a7e
--- a/dev/null
+++ b/libopie2/opieui/odialog.cpp
@@ -0,0 +1,53 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include <opie2/odialog.h>
+
+int ODialog::mMarginSize = 5; // 11 like in KDialog is probably too much for PDA
+int ODialog::mSpacingSize = 2; // 6 like in KDialog is probably too much for PDA
+
+ODialog::ODialog(QWidget *parent, const char *name, bool modal, WFlags f)
+ : QDialog(parent, name, modal, f)
+{
+}
+
+int ODialog::marginHint()
+{
+ return( mMarginSize );
+}
+
+
+int ODialog::spacingHint()
+{
+ return( mSpacingSize );
+}
+
+// Placeholder for even more sophisticed things
diff --git a/libopie2/opieui/odialog.h b/libopie2/opieui/odialog.h
new file mode 100644
index 0000000..38f25e8
--- a/dev/null
+++ b/libopie2/opieui/odialog.h
@@ -0,0 +1,89 @@
+/*
+                 This file is part of the Opie Project
+
+              (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef ODIALOG_H
+#define ODIALOG_H
+
+class QLayoutItem;
+
+#include <qdialog.h>
+
+/**
+ * Dialog with extended nonmodal support and methods for OPIE standard
+ * compliance.
+ *
+ * The @ref marginHint() and @ref spacingHint() sizes shall be used
+ * whenever you layout the interior of a dialog. One special note. If
+ * you make your own action buttons (OK, Cancel etc), the space
+ * beteween the buttons shall be @ref spacingHint(), whereas the space
+ * above, below, to the right and to the left shall be @ref marginHint().
+ * If you add a separator line above the buttons, there shall be a
+ * @ref marginHint() between the buttons and the separator and a
+ * @ref marginHint() above the separator as well.
+ *
+ * @author Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ */
+
+class ODialog : public QDialog
+{
+ Q_OBJECT
+
+ public:
+
+ /**
+ * Constructor.
+ *
+ * Takes the same arguments as @ref QDialog.
+ */
+ ODialog(QWidget *parent = 0, const char *name = 0,
+ bool modal = false, WFlags f = 0);
+
+ /**
+ * Return the number of pixels you shall use between a
+ * dialog edge and the outermost widget(s) according to the KDE standard.
+ **/
+ static int marginHint();
+
+ /**
+ * Return the number of pixels you shall use between
+ * widgets inside a dialog according to the KDE standard.
+ */
+ static int spacingHint();
+
+ private:
+ static int mMarginSize;
+ static int mSpacingSize;
+
+ //class ODialogPrivate;
+ //ODialogPrivate *d;
+
+};
+#endif // ODIALOG_H
diff --git a/libopie2/opieui/oimageeffect.cpp b/libopie2/opieui/oimageeffect.cpp
new file mode 100644
index 0000000..3c28bbe
--- a/dev/null
+++ b/libopie2/opieui/oimageeffect.cpp
@@ -0,0 +1,3794 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998, 1999, 2001, 2002 Daniel M. Duley <mosfet@kde.org>
+ (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
+ (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
+ (C) 2000 Josef Weidendorfer <weidendo@in.tum.de>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+// $Id$
+
+#include <math.h>
+
+#include <qimage.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include "oimageeffect.h"
+
+#define MaxRGB 255L
+#define DegreesToRadians(x) ((x)*M_PI/180.0)
+
+using namespace std;
+
+inline unsigned int intensityValue(unsigned int color)
+{
+ return((unsigned int)((0.299*qRed(color) +
+ 0.587*qGreen(color) +
+ 0.1140000000000001*qBlue(color))));
+}
+
+//======================================================================
+//
+// Gradient effects
+//
+//======================================================================
+
+QImage OImageEffect::gradient(const QSize &size, const QColor &ca,
+ const QColor &cb, GradientType eff, int ncols)
+{
+ int rDiff, gDiff, bDiff;
+ int rca, gca, bca, rcb, gcb, bcb;
+
+ QImage image(size, 32);
+
+ if (size.width() == 0 || size.height() == 0) {
+#ifndef NDEBUG
+ cerr << "WARNING: OImageEffect::gradient: invalid image" << endl;
+#endif
+ return image;
+ }
+
+ register int x, y;
+
+ rDiff = (rcb = cb.red()) - (rca = ca.red());
+ gDiff = (gcb = cb.green()) - (gca = ca.green());
+ bDiff = (bcb = cb.blue()) - (bca = ca.blue());
+
+ if( eff == VerticalGradient || eff == HorizontalGradient ){
+
+ uint *p;
+ uint rgb;
+
+ register int rl = rca << 16;
+ register int gl = gca << 16;
+ register int bl = bca << 16;
+
+ if( eff == VerticalGradient ) {
+
+ int rcdelta = ((1<<16) / size.height()) * rDiff;
+ int gcdelta = ((1<<16) / size.height()) * gDiff;
+ int bcdelta = ((1<<16) / size.height()) * bDiff;
+
+ for ( y = 0; y < size.height(); y++ ) {
+ p = (uint *) image.scanLine(y);
+
+ rl += rcdelta;
+ gl += gcdelta;
+ bl += bcdelta;
+
+ rgb = qRgb( (rl>>16), (gl>>16), (bl>>16) );
+
+ for( x = 0; x < size.width(); x++ ) {
+ *p = rgb;
+ p++;
+ }
+ }
+
+ }
+ else { // must be HorizontalGradient
+
+ unsigned int *o_src = (unsigned int *)image.scanLine(0);
+ unsigned int *src = o_src;
+
+ int rcdelta = ((1<<16) / size.width()) * rDiff;
+ int gcdelta = ((1<<16) / size.width()) * gDiff;
+ int bcdelta = ((1<<16) / size.width()) * bDiff;
+
+ for( x = 0; x < size.width(); x++) {
+
+ rl += rcdelta;
+ gl += gcdelta;
+ bl += bcdelta;
+
+ *src++ = qRgb( (rl>>16), (gl>>16), (bl>>16));
+ }
+
+ src = o_src;
+
+ // Believe it or not, manually copying in a for loop is faster
+ // than calling memcpy for each scanline (on the order of ms...).
+ // I think this is due to the function call overhead (mosfet).
+
+ for (y = 1; y < size.height(); ++y) {
+
+ p = (unsigned int *)image.scanLine(y);
+ src = o_src;
+ for(x=0; x < size.width(); ++x)
+ *p++ = *src++;
+ }
+ }
+ }
+
+ else {
+
+ float rfd, gfd, bfd;
+ float rd = rca, gd = gca, bd = bca;
+
+ unsigned char *xtable[3];
+ unsigned char *ytable[3];
+
+ unsigned int w = size.width(), h = size.height();
+ xtable[0] = new unsigned char[w];
+ xtable[1] = new unsigned char[w];
+ xtable[2] = new unsigned char[w];
+ ytable[0] = new unsigned char[h];
+ ytable[1] = new unsigned char[h];
+ ytable[2] = new unsigned char[h];
+ w*=2, h*=2;
+
+ if ( eff == DiagonalGradient || eff == CrossDiagonalGradient) {
+ // Diagonal dgradient code inspired by BlackBox (mosfet)
+ // BlackBox dgradient is (C) Brad Hughes, <bhughes@tcac.net> and
+ // Mike Cole <mike@mydot.com>.
+
+ rfd = (float)rDiff/w;
+ gfd = (float)gDiff/w;
+ bfd = (float)bDiff/w;
+
+ int dir;
+ for (x = 0; x < size.width(); x++, rd+=rfd, gd+=gfd, bd+=bfd) {
+ dir = eff == DiagonalGradient? x : size.width() - x - 1;
+ xtable[0][dir] = (unsigned char) rd;
+ xtable[1][dir] = (unsigned char) gd;
+ xtable[2][dir] = (unsigned char) bd;
+ }
+ rfd = (float)rDiff/h;
+ gfd = (float)gDiff/h;
+ bfd = (float)bDiff/h;
+ rd = gd = bd = 0;
+ for (y = 0; y < size.height(); y++, rd+=rfd, gd+=gfd, bd+=bfd) {
+ ytable[0][y] = (unsigned char) rd;
+ ytable[1][y] = (unsigned char) gd;
+ ytable[2][y] = (unsigned char) bd;
+ }
+
+ for (y = 0; y < size.height(); y++) {
+ unsigned int *scanline = (unsigned int *)image.scanLine(y);
+ for (x = 0; x < size.width(); x++) {
+ scanline[x] = qRgb(xtable[0][x] + ytable[0][y],
+ xtable[1][x] + ytable[1][y],
+ xtable[2][x] + ytable[2][y]);
+ }
+ }
+ }
+
+ else if (eff == RectangleGradient ||
+ eff == PyramidGradient ||
+ eff == PipeCrossGradient ||
+ eff == EllipticGradient)
+ {
+ int rSign = rDiff>0? 1: -1;
+ int gSign = gDiff>0? 1: -1;
+ int bSign = bDiff>0? 1: -1;
+
+ rfd = (float)rDiff / size.width();
+ gfd = (float)gDiff / size.width();
+ bfd = (float)bDiff / size.width();
+
+ rd = (float)rDiff/2;
+ gd = (float)gDiff/2;
+ bd = (float)bDiff/2;
+
+ for (x = 0; x < size.width(); x++, rd-=rfd, gd-=gfd, bd-=bfd)
+ {
+ xtable[0][x] = (unsigned char) abs((int)rd);
+ xtable[1][x] = (unsigned char) abs((int)gd);
+ xtable[2][x] = (unsigned char) abs((int)bd);
+ }
+
+ rfd = (float)rDiff/size.height();
+ gfd = (float)gDiff/size.height();
+ bfd = (float)bDiff/size.height();
+
+ rd = (float)rDiff/2;
+ gd = (float)gDiff/2;
+ bd = (float)bDiff/2;
+
+ for (y = 0; y < size.height(); y++, rd-=rfd, gd-=gfd, bd-=bfd)
+ {
+ ytable[0][y] = (unsigned char) abs((int)rd);
+ ytable[1][y] = (unsigned char) abs((int)gd);
+ ytable[2][y] = (unsigned char) abs((int)bd);
+ }
+ unsigned int rgb;
+ int h = (size.height()+1)>>1;
+ for (y = 0; y < h; y++) {
+ unsigned int *sl1 = (unsigned int *)image.scanLine(y);
+ unsigned int *sl2 = (unsigned int *)image.scanLine(QMAX(size.height()-y-1, y));
+
+ int w = (size.width()+1)>>1;
+ int x2 = size.width()-1;
+
+ for (x = 0; x < w; x++, x2--) {
+ rgb = 0;
+ if (eff == PyramidGradient) {
+ rgb = qRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]),
+ gcb-gSign*(xtable[1][x]+ytable[1][y]),
+ bcb-bSign*(xtable[2][x]+ytable[2][y]));
+ }
+ if (eff == RectangleGradient) {
+ rgb = qRgb(rcb - rSign *
+ QMAX(xtable[0][x], ytable[0][y]) * 2,
+ gcb - gSign *
+ QMAX(xtable[1][x], ytable[1][y]) * 2,
+ bcb - bSign *
+ QMAX(xtable[2][x], ytable[2][y]) * 2);
+ }
+ if (eff == PipeCrossGradient) {
+ rgb = qRgb(rcb - rSign *
+ QMIN(xtable[0][x], ytable[0][y]) * 2,
+ gcb - gSign *
+ QMIN(xtable[1][x], ytable[1][y]) * 2,
+ bcb - bSign *
+ QMIN(xtable[2][x], ytable[2][y]) * 2);
+ }
+ if (eff == EllipticGradient) {
+ rgb = qRgb(rcb - rSign *
+ (int)sqrt((xtable[0][x]*xtable[0][x] +
+ ytable[0][y]*ytable[0][y])*2.0),
+ gcb - gSign *
+ (int)sqrt((xtable[1][x]*xtable[1][x] +
+ ytable[1][y]*ytable[1][y])*2.0),
+ bcb - bSign *
+ (int)sqrt((xtable[2][x]*xtable[2][x] +
+ ytable[2][y]*ytable[2][y])*2.0));
+ }
+
+ sl1[x] = sl2[x] = rgb;
+ sl1[x2] = sl2[x2] = rgb;
+ }
+ }
+ }
+
+ delete [] xtable[0];
+ delete [] xtable[1];
+ delete [] xtable[2];
+ delete [] ytable[0];
+ delete [] ytable[1];
+ delete [] ytable[2];
+ }
+
+ // dither if necessary
+ if (ncols && (QPixmap::defaultDepth() < 15 )) {
+ if ( ncols < 2 || ncols > 256 )
+ ncols = 3;
+ QColor *dPal = new QColor[ncols];
+ for (int i=0; i<ncols; i++) {
+ dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ),
+ gca + gDiff * i / ( ncols - 1 ),
+ bca + bDiff * i / ( ncols - 1 ) );
+ }
+ dither(image, dPal, ncols);
+ delete [] dPal;
+ }
+
+ return image;
+}
+
+
+// -----------------------------------------------------------------------------
+
+//CT this was (before Dirk A. Mueller's speedup changes)
+// merely the same code as in the above method, but it's supposedly
+// way less performant since it introduces a lot of supplementary tests
+// and simple math operations for the calculus of the balance.
+// (surprizingly, it isn't less performant, in the contrary :-)
+// Yes, I could have merged them, but then the excellent performance of
+// the balanced code would suffer with no other gain than a mere
+// source code and byte code size economy.
+
+QImage OImageEffect::unbalancedGradient(const QSize &size, const QColor &ca,
+ const QColor &cb, GradientType eff, int xfactor, int yfactor,
+ int ncols)
+{
+ int dir; // general parameter used for direction switches
+
+ bool _xanti = false , _yanti = false;
+
+ if (xfactor < 0) _xanti = true; // negative on X direction
+ if (yfactor < 0) _yanti = true; // negative on Y direction
+
+ xfactor = abs(xfactor);
+ yfactor = abs(yfactor);
+
+ if (!xfactor) xfactor = 1;
+ if (!yfactor) yfactor = 1;
+
+ if (xfactor > 200 ) xfactor = 200;
+ if (yfactor > 200 ) yfactor = 200;
+
+
+ // float xbal = xfactor/5000.;
+ // float ybal = yfactor/5000.;
+ float xbal = xfactor/30./size.width();
+ float ybal = yfactor/30./size.height();
+ float rat;
+
+ int rDiff, gDiff, bDiff;
+ int rca, gca, bca, rcb, gcb, bcb;
+
+ QImage image(size, 32);
+
+ if (size.width() == 0 || size.height() == 0) {
+#ifndef NDEBUG
+ cerr << "WARNING: OImageEffect::unbalancedGradient : invalid image\n";
+#endif
+ return image;
+ }
+
+ register int x, y;
+ unsigned int *scanline;
+
+ rDiff = (rcb = cb.red()) - (rca = ca.red());
+ gDiff = (gcb = cb.green()) - (gca = ca.green());
+ bDiff = (bcb = cb.blue()) - (bca = ca.blue());
+
+ if( eff == VerticalGradient || eff == HorizontalGradient){
+ QColor cRow;
+
+ uint *p;
+ uint rgbRow;
+
+ if( eff == VerticalGradient) {
+ for ( y = 0; y < size.height(); y++ ) {
+ dir = _yanti ? y : size.height() - 1 - y;
+ p = (uint *) image.scanLine(dir);
+ rat = 1 - exp( - (float)y * ybal );
+
+ cRow.setRgb( rcb - (int) ( rDiff * rat ),
+ gcb - (int) ( gDiff * rat ),
+ bcb - (int) ( bDiff * rat ) );
+
+ rgbRow = cRow.rgb();
+
+ for( x = 0; x < size.width(); x++ ) {
+ *p = rgbRow;
+ p++;
+ }
+ }
+ }
+ else {
+
+ unsigned int *src = (unsigned int *)image.scanLine(0);
+ for(x = 0; x < size.width(); x++ )
+ {
+ dir = _xanti ? x : size.width() - 1 - x;
+ rat = 1 - exp( - (float)x * xbal );
+
+ src[dir] = qRgb(rcb - (int) ( rDiff * rat ),
+ gcb - (int) ( gDiff * rat ),
+ bcb - (int) ( bDiff * rat ));
+ }
+
+ // Believe it or not, manually copying in a for loop is faster
+ // than calling memcpy for each scanline (on the order of ms...).
+ // I think this is due to the function call overhead (mosfet).
+
+ for(y = 1; y < size.height(); ++y)
+ {
+ scanline = (unsigned int *)image.scanLine(y);
+ for(x=0; x < size.width(); ++x)
+ scanline[x] = src[x];
+ }
+ }
+ }
+
+ else {
+ int w=size.width(), h=size.height();
+
+ unsigned char *xtable[3];
+ unsigned char *ytable[3];
+ xtable[0] = new unsigned char[w];
+ xtable[1] = new unsigned char[w];
+ xtable[2] = new unsigned char[w];
+ ytable[0] = new unsigned char[h];
+ ytable[1] = new unsigned char[h];
+ ytable[2] = new unsigned char[h];
+
+ if ( eff == DiagonalGradient || eff == CrossDiagonalGradient)
+ {
+ for (x = 0; x < w; x++) {
+ dir = _xanti ? x : w - 1 - x;
+ rat = 1 - exp( - (float)x * xbal );
+
+ xtable[0][dir] = (unsigned char) ( rDiff/2 * rat );
+ xtable[1][dir] = (unsigned char) ( gDiff/2 * rat );
+ xtable[2][dir] = (unsigned char) ( bDiff/2 * rat );
+ }
+
+ for (y = 0; y < h; y++) {
+ dir = _yanti ? y : h - 1 - y;
+ rat = 1 - exp( - (float)y * ybal );
+
+ ytable[0][dir] = (unsigned char) ( rDiff/2 * rat );
+ ytable[1][dir] = (unsigned char) ( gDiff/2 * rat );
+ ytable[2][dir] = (unsigned char) ( bDiff/2 * rat );
+ }
+
+ for (y = 0; y < h; y++) {
+ unsigned int *scanline = (unsigned int *)image.scanLine(y);
+ for (x = 0; x < w; x++) {
+ scanline[x] = qRgb(rcb - (xtable[0][x] + ytable[0][y]),
+ gcb - (xtable[1][x] + ytable[1][y]),
+ bcb - (xtable[2][x] + ytable[2][y]));
+ }
+ }
+ }
+
+ else if (eff == RectangleGradient ||
+ eff == PyramidGradient ||
+ eff == PipeCrossGradient ||
+ eff == EllipticGradient)
+ {
+ int rSign = rDiff>0? 1: -1;
+ int gSign = gDiff>0? 1: -1;
+ int bSign = bDiff>0? 1: -1;
+
+ for (x = 0; x < w; x++)
+ {
+ dir = _xanti ? x : w - 1 - x;
+ rat = 1 - exp( - (float)x * xbal );
+
+ xtable[0][dir] = (unsigned char) abs((int)(rDiff*(0.5-rat)));
+ xtable[1][dir] = (unsigned char) abs((int)(gDiff*(0.5-rat)));
+ xtable[2][dir] = (unsigned char) abs((int)(bDiff*(0.5-rat)));
+ }
+
+ for (y = 0; y < h; y++)
+ {
+ dir = _yanti ? y : h - 1 - y;
+
+ rat = 1 - exp( - (float)y * ybal );
+
+ ytable[0][dir] = (unsigned char) abs((int)(rDiff*(0.5-rat)));
+ ytable[1][dir] = (unsigned char) abs((int)(gDiff*(0.5-rat)));
+ ytable[2][dir] = (unsigned char) abs((int)(bDiff*(0.5-rat)));
+ }
+
+ for (y = 0; y < h; y++) {
+ unsigned int *scanline = (unsigned int *)image.scanLine(y);
+ for (x = 0; x < w; x++) {
+ if (eff == PyramidGradient)
+ {
+ scanline[x] = qRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]),
+ gcb-gSign*(xtable[1][x]+ytable[1][y]),
+ bcb-bSign*(xtable[2][x]+ytable[2][y]));
+ }
+ if (eff == RectangleGradient)
+ {
+ scanline[x] = qRgb(rcb - rSign *
+ QMAX(xtable[0][x], ytable[0][y]) * 2,
+ gcb - gSign *
+ QMAX(xtable[1][x], ytable[1][y]) * 2,
+ bcb - bSign *
+ QMAX(xtable[2][x], ytable[2][y]) * 2);
+ }
+ if (eff == PipeCrossGradient)
+ {
+ scanline[x] = qRgb(rcb - rSign *
+ QMIN(xtable[0][x], ytable[0][y]) * 2,
+ gcb - gSign *
+ QMIN(xtable[1][x], ytable[1][y]) * 2,
+ bcb - bSign *
+ QMIN(xtable[2][x], ytable[2][y]) * 2);
+ }
+ if (eff == EllipticGradient)
+ {
+ scanline[x] = qRgb(rcb - rSign *
+ (int)sqrt((xtable[0][x]*xtable[0][x] +
+ ytable[0][y]*ytable[0][y])*2.0),
+ gcb - gSign *
+ (int)sqrt((xtable[1][x]*xtable[1][x] +
+ ytable[1][y]*ytable[1][y])*2.0),
+ bcb - bSign *
+ (int)sqrt((xtable[2][x]*xtable[2][x] +
+ ytable[2][y]*ytable[2][y])*2.0));
+ }
+ }
+ }
+ }
+
+ if (ncols && (QPixmap::defaultDepth() < 15 )) {
+ if ( ncols < 2 || ncols > 256 )
+ ncols = 3;
+ QColor *dPal = new QColor[ncols];
+ for (int i=0; i<ncols; i++) {
+ dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ),
+ gca + gDiff * i / ( ncols - 1 ),
+ bca + bDiff * i / ( ncols - 1 ) );
+ }
+ dither(image, dPal, ncols);
+ delete [] dPal;
+ }
+
+ delete [] xtable[0];
+ delete [] xtable[1];
+ delete [] xtable[2];
+ delete [] ytable[0];
+ delete [] ytable[1];
+ delete [] ytable[2];
+
+ }
+
+ return image;
+}
+
+
+//======================================================================
+//
+// Intensity effects
+//
+//======================================================================
+
+
+/* This builds a 256 byte unsigned char lookup table with all
+ * the possible percent values prior to applying the effect, then uses
+ * integer math for the pixels. For any image larger than 9x9 this will be
+ * less expensive than doing a float operation on the 3 color components of
+ * each pixel. (mosfet)
+ */
+
+QImage& OImageEffect::intensity(QImage &image, float percent)
+{
+ if (image.width() == 0 || image.height() == 0) {
+#ifndef NDEBUG
+ cerr << "WARNING: OImageEffect::intensity : invalid image\n";
+#endif
+ return image;
+ }
+
+ int segColors = image.depth() > 8 ? 256 : image.numColors();
+ unsigned char *segTbl = new unsigned char[segColors];
+ int pixels = image.depth() > 8 ? image.width()*image.height() :
+ image.numColors();
+ unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
+ (unsigned int *)image.colorTable();
+
+ bool brighten = (percent >= 0);
+ if(percent < 0)
+ percent = -percent;
+
+ if(brighten){ // keep overflow check out of loops
+ for(int i=0; i < segColors; ++i){
+ int tmp = (int)(i*percent);
+ if(tmp > 255)
+ tmp = 255;
+ segTbl[i] = tmp;
+ }
+ }
+ else{
+ for(int i=0; i < segColors; ++i){
+ int tmp = (int)(i*percent);
+ if(tmp < 0)
+ tmp = 0;
+ segTbl[i] = tmp;
+ }
+ }
+
+ if(brighten){ // same here
+ for(int i=0; i < pixels; ++i){
+ int r = qRed(data[i]);
+ int g = qGreen(data[i]);
+ int b = qBlue(data[i]);
+ int a = qAlpha(data[i]);
+ r = r + segTbl[r] > 255 ? 255 : r + segTbl[r];
+ g = g + segTbl[g] > 255 ? 255 : g + segTbl[g];
+ b = b + segTbl[b] > 255 ? 255 : b + segTbl[b];
+ data[i] = qRgba(r, g, b,a);
+ }
+ }
+ else{
+ for(int i=0; i < pixels; ++i){
+ int r = qRed(data[i]);
+ int g = qGreen(data[i]);
+ int b = qBlue(data[i]);
+ int a = qAlpha(data[i]);
+ r = r - segTbl[r] < 0 ? 0 : r - segTbl[r];
+ g = g - segTbl[g] < 0 ? 0 : g - segTbl[g];
+ b = b - segTbl[b] < 0 ? 0 : b - segTbl[b];
+ data[i] = qRgba(r, g, b, a);
+ }
+ }
+ delete [] segTbl;
+
+ return image;
+}
+
+QImage& OImageEffect::channelIntensity(QImage &image, float percent,
+ RGBComponent channel)
+{
+ if (image.width() == 0 || image.height() == 0) {
+#ifndef NDEBUG
+ cerr << "WARNING: OImageEffect::channelIntensity : invalid image\n";
+#endif
+ return image;
+ }
+
+ int segColors = image.depth() > 8 ? 256 : image.numColors();
+ unsigned char *segTbl = new unsigned char[segColors];
+ int pixels = image.depth() > 8 ? image.width()*image.height() :
+ image.numColors();
+ unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
+ (unsigned int *)image.colorTable();
+ bool brighten = (percent >= 0);
+ if(percent < 0)
+ percent = -percent;
+
+ if(brighten){ // keep overflow check out of loops
+ for(int i=0; i < segColors; ++i){
+ int tmp = (int)(i*percent);
+ if(tmp > 255)
+ tmp = 255;
+ segTbl[i] = tmp;
+ }
+ }
+ else{
+ for(int i=0; i < segColors; ++i){
+ int tmp = (int)(i*percent);
+ if(tmp < 0)
+ tmp = 0;
+ segTbl[i] = tmp;
+ }
+ }
+
+ if(brighten){ // same here
+ if(channel == Red){ // and here ;-)
+ for(int i=0; i < pixels; ++i){
+ int c = qRed(data[i]);
+ c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
+ data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i]));
+ }
+ }
+ if(channel == Green){
+ for(int i=0; i < pixels; ++i){
+ int c = qGreen(data[i]);
+ c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
+ data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i]));
+ }
+ }
+ else{
+ for(int i=0; i < pixels; ++i){
+ int c = qBlue(data[i]);
+ c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
+ data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i]));
+ }
+ }
+
+ }
+ else{
+ if(channel == Red){
+ for(int i=0; i < pixels; ++i){
+ int c = qRed(data[i]);
+ c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
+ data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i]));
+ }
+ }
+ if(channel == Green){
+ for(int i=0; i < pixels; ++i){
+ int c = qGreen(data[i]);
+ c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
+ data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i]));
+ }
+ }
+ else{
+ for(int i=0; i < pixels; ++i){
+ int c = qBlue(data[i]);
+ c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
+ data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i]));
+ }
+ }
+ }
+ delete [] segTbl;
+
+ return image;
+}
+
+// Modulate an image with an RBG channel of another image
+//
+QImage& OImageEffect::modulate(QImage &image, QImage &modImage, bool reverse,
+ ModulationType type, int factor, RGBComponent channel)
+{
+ if (image.width() == 0 || image.height() == 0 ||
+ modImage.width() == 0 || modImage.height() == 0) {
+#ifndef NDEBUG
+ cerr << "WARNING: OImageEffect::modulate : invalid image\n";
+#endif
+ return image;
+ }
+
+ int r, g, b, h, s, v, a;
+ QColor clr;
+ int mod=0;
+ unsigned int x1, x2, y1, y2;
+ register int x, y;
+
+ // for image, we handle only depth 32
+ if (image.depth()<32) image = image.convertDepth(32);
+
+ // for modImage, we handle depth 8 and 32
+ if (modImage.depth()<8) modImage = modImage.convertDepth(8);
+
+ unsigned int *colorTable2 = (modImage.depth()==8) ?
+ modImage.colorTable():0;
+ unsigned int *data1, *data2;
+ unsigned char *data2b;
+ unsigned int color1, color2;
+
+ x1 = image.width(); y1 = image.height();
+ x2 = modImage.width(); y2 = modImage.height();
+
+ for (y = 0; y < (int)y1; y++) {
+ data1 = (unsigned int *) image.scanLine(y);
+ data2 = (unsigned int *) modImage.scanLine( y%y2 );
+ data2b = (unsigned char *) modImage.scanLine( y%y2 );
+
+ x=0;
+ while(x < (int)x1) {
+ color2 = (colorTable2) ? colorTable2[*data2b] : *data2;
+ if (reverse) {
+ color1 = color2;
+ color2 = *data1;
+ }
+ else
+ color1 = *data1;
+
+ if (type == Intensity || type == Contrast) {
+ r = qRed(color1);
+ g = qGreen(color1);
+ b = qBlue(color1);
+ if (channel != All) {
+ mod = (channel == Red) ? qRed(color2) :
+ (channel == Green) ? qGreen(color2) :
+ (channel == Blue) ? qBlue(color2) :
+ (channel == Gray) ? qGray(color2) : 0;
+ mod = mod*factor/50;
+ }
+
+ if (type == Intensity) {
+ if (channel == All) {
+ r += r * factor/50 * qRed(color2)/256;
+ g += g * factor/50 * qGreen(color2)/256;
+ b += b * factor/50 * qBlue(color2)/256;
+ }
+ else {
+ r += r * mod/256;
+ g += g * mod/256;
+ b += b * mod/256;
+ }
+ }
+ else { // Contrast
+ if (channel == All) {
+ r += (r-128) * factor/50 * qRed(color2)/128;
+ g += (g-128) * factor/50 * qGreen(color2)/128;
+ b += (b-128) * factor/50 * qBlue(color2)/128;
+ }
+ else {
+ r += (r-128) * mod/128;
+ g += (g-128) * mod/128;
+ b += (b-128) * mod/128;
+ }
+ }
+
+ if (r<0) r=0; if (r>255) r=255;
+ if (g<0) g=0; if (g>255) g=255;
+ if (b<0) b=0; if (b>255) b=255;
+ a = qAlpha(*data1);
+ *data1 = qRgba(r, g, b, a);
+ }
+ else if (type == Saturation || type == HueShift) {
+ clr.setRgb(color1);
+ clr.hsv(&h, &s, &v);
+ mod = (channel == Red) ? qRed(color2) :
+ (channel == Green) ? qGreen(color2) :
+ (channel == Blue) ? qBlue(color2) :
+ (channel == Gray) ? qGray(color2) : 0;
+ mod = mod*factor/50;
+
+ if (type == Saturation) {
+ s -= s * mod/256;
+ if (s<0) s=0; if (s>255) s=255;
+ }
+ else { // HueShift
+ h += mod;
+ while(h<0) h+=360;
+ h %= 360;
+ }
+
+ clr.setHsv(h, s, v);
+ a = qAlpha(*data1);
+ *data1 = clr.rgb() | ((uint)(a & 0xff) << 24);
+ }
+ data1++; data2++; data2b++; x++;
+ if ( (x%x2) ==0) { data2 -= x2; data2b -= x2; }
+ }
+ }
+ return image;
+}
+
+
+
+//======================================================================
+//
+// Blend effects
+//
+//======================================================================
+
+
+// Nice and fast direct pixel manipulation
+QImage& OImageEffect::blend(const QColor& clr, QImage& dst, float opacity)
+{
+ if (dst.width() <= 0 || dst.height() <= 0)
+ return dst;
+
+ if (opacity < 0.0 || opacity > 1.0) {
+#ifndef NDEBUG
+ cerr << "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1]\n";
+#endif
+ return dst;
+ }
+
+ int depth = dst.depth();
+ if (depth != 32)
+ dst = dst.convertDepth(32);
+
+ int pixels = dst.width() * dst.height();
+ int rcol, gcol, bcol;
+ clr.rgb(&rcol, &gcol, &bcol);
+
+#ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
+ register unsigned char *data = (unsigned char *)dst.bits() + 1;
+#else // BGRA
+ register unsigned char *data = (unsigned char *)dst.bits();
+#endif
+
+ for (register int i=0; i<pixels; i++)
+ {
+#ifdef WORDS_BIGENDIAN
+ *(data++) += (unsigned char)((rcol - *data) * opacity);
+ *(data++) += (unsigned char)((gcol - *data) * opacity);
+ *(data++) += (unsigned char)((bcol - *data) * opacity);
+#else
+ *(data++) += (unsigned char)((bcol - *data) * opacity);
+ *(data++) += (unsigned char)((gcol - *data) * opacity);
+ *(data++) += (unsigned char)((rcol - *data) * opacity);
+#endif
+ data++; // skip alpha
+ }
+ return dst;
+}
+
+// Nice and fast direct pixel manipulation
+QImage& OImageEffect::blend(QImage& src, QImage& dst, float opacity)
+{
+ if (src.width() <= 0 || src.height() <= 0)
+ return dst;
+ if (dst.width() <= 0 || dst.height() <= 0)
+ return dst;
+
+ if (src.width() != dst.width() || src.height() != dst.height()) {
+#ifndef NDEBUG
+ cerr << "WARNING: OImageEffect::blend : src and destination images are not the same size\n";
+#endif
+ return dst;
+ }
+
+ if (opacity < 0.0 || opacity > 1.0) {
+#ifndef NDEBUG
+ cerr << "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1]\n";
+#endif
+ return dst;
+ }
+
+ if (src.depth() != 32) src = src.convertDepth(32);
+ if (dst.depth() != 32) dst = dst.convertDepth(32);
+
+ int pixels = src.width() * src.height();
+#ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
+ register unsigned char *data1 = (unsigned char *)dst.bits() + 1;
+ register unsigned char *data2 = (unsigned char *)src.bits() + 1;
+#else // BGRA
+ register unsigned char *data1 = (unsigned char *)dst.bits();
+ register unsigned char *data2 = (unsigned char *)src.bits();
+#endif
+
+ for (register int i=0; i<pixels; i++)
+ {
+#ifdef WORDS_BIGENDIAN
+ *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
+ *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
+ *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
+#else
+ *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
+ *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
+ *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
+#endif
+ data1++; // skip alpha
+ data2++;
+ }
+
+ return dst;
+}
+
+
+QImage& OImageEffect::blend(QImage &image, float initial_intensity,
+ const QColor &bgnd, GradientType eff,
+ bool anti_dir)
+{
+ if (image.width() == 0 || image.height() == 0 || image.depth()!=32 ) {
+#ifndef NDEBUG
+ cerr << "WARNING: OImageEffect::blend : invalid image\n";
+#endif
+ return image;
+ }
+
+ int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue();
+ int r, g, b;
+ int ind;
+
+ unsigned int xi, xf, yi, yf;
+ unsigned int a;
+
+ // check the boundaries of the initial intesity param
+ float unaffected = 1;
+ if (initial_intensity > 1) initial_intensity = 1;
+ if (initial_intensity < -1) initial_intensity = -1;
+ if (initial_intensity < 0) {
+ unaffected = 1. + initial_intensity;
+ initial_intensity = 0;
+ }
+
+
+ float intensity = initial_intensity;
+ float var = 1. - initial_intensity;
+
+ if (anti_dir) {
+ initial_intensity = intensity = 1.;
+ var = -var;
+ }
+
+ register int x, y;
+
+ unsigned int *data = (unsigned int *)image.bits();
+
+ int image_width = image.width(); //Those can't change
+ int image_height = image.height();
+
+
+ if( eff == VerticalGradient || eff == HorizontalGradient ) {
+
+ // set the image domain to apply the effect to
+ xi = 0, xf = image_width;
+ yi = 0, yf = image_height;
+ if (eff == VerticalGradient) {
+ if (anti_dir) yf = (int)(image_height * unaffected);
+ else yi = (int)(image_height * (1 - unaffected));
+ }
+ else {
+ if (anti_dir) xf = (int)(image_width * unaffected);
+ else xi = (int)(image_height * (1 - unaffected));
+ }
+
+ var /= (eff == VerticalGradient?yf-yi:xf-xi);
+
+ int ind_base;
+ for (y = yi; y < (int)yf; y++) {
+ intensity = eff == VerticalGradient? intensity + var :
+ initial_intensity;
+ ind_base = image_width * y ;
+ for (x = xi; x < (int)xf ; x++) {
+ if (eff == HorizontalGradient) intensity += var;
+ ind = x + ind_base;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+ }
+ }
+ }
+ else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) {
+ float xvar = var / 2 / image_width; // / unaffected;
+ float yvar = var / 2 / image_height; // / unaffected;
+ float tmp;
+
+ for (x = 0; x < image_width ; x++) {
+ tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1);
+ ind = x;
+ for (y = 0; y < image_height ; y++) {
+ intensity = initial_intensity + tmp + yvar * y;
+
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+
+ ind += image_width;
+ }
+ }
+ }
+
+ else if (eff == RectangleGradient || eff == EllipticGradient) {
+ float xvar;
+ float yvar;
+
+ for (x = 0; x < image_width / 2 + image_width % 2; x++) {
+ xvar = var / image_width * (image_width - x*2/unaffected-1);
+ for (y = 0; y < image_height / 2 + image_height % 2; y++) {
+ yvar = var / image_height * (image_height - y*2/unaffected -1);
+
+ if (eff == RectangleGradient)
+ intensity = initial_intensity + QMAX(xvar, yvar);
+ else
+ intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
+ if (intensity > 1) intensity = 1;
+ if (intensity < 0) intensity = 0;
+
+ //NW
+ ind = x + image_width * y ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+
+ //NE
+ ind = image_width - x - 1 + image_width * y ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+ }
+ }
+
+ //CT loop is doubled because of stupid central row/column issue.
+ // other solution?
+ for (x = 0; x < image_width / 2; x++) {
+ xvar = var / image_width * (image_width - x*2/unaffected-1);
+ for (y = 0; y < image_height / 2; y++) {
+ yvar = var / image_height * (image_height - y*2/unaffected -1);
+
+ if (eff == RectangleGradient)
+ intensity = initial_intensity + QMAX(xvar, yvar);
+ else
+ intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
+ if (intensity > 1) intensity = 1;
+ if (intensity < 0) intensity = 0;
+
+ //SW
+ ind = x + image_width * (image_height - y -1) ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+
+ //SE
+ ind = image_width-x-1 + image_width * (image_height - y - 1) ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+ }
+ }
+ }
+#ifndef NDEBUG
+ else cerr << "OImageEffect::blend effect not implemented" << endl;
+#endif
+ return image;
+}
+
+// Not very efficient as we create a third big image...
+//
+QImage& OImageEffect::blend(QImage &image1, QImage &image2,
+ GradientType gt, int xf, int yf)
+{
+ if (image1.width() == 0 || image1.height() == 0 ||
+ image2.width() == 0 || image2.height() == 0)
+ return image1;
+
+ QImage image3;
+
+ image3 = OImageEffect::unbalancedGradient(image1.size(),
+ QColor(0,0,0), QColor(255,255,255),
+ gt, xf, yf, 0);
+
+ return blend(image1,image2,image3, Red); // Channel to use is arbitrary
+}
+
+// Blend image2 into image1, using an RBG channel of blendImage
+//
+QImage& OImageEffect::blend(QImage &image1, QImage &image2,
+ QImage &blendImage, RGBComponent channel)
+{
+ if (image1.width() == 0 || image1.height() == 0 ||
+ image2.width() == 0 || image2.height() == 0 ||
+ blendImage.width() == 0 || blendImage.height() == 0) {
+#ifndef NDEBUG
+ cerr << "OImageEffect::blend effect invalid image" << endl;
+#endif
+ return image1;
+ }
+
+ int r, g, b;
+ int ind1, ind2, ind3;
+
+ unsigned int x1, x2, x3, y1, y2, y3;
+ unsigned int a;
+
+ register int x, y;
+
+ // for image1 and image2, we only handle depth 32
+ if (image1.depth()<32) image1 = image1.convertDepth(32);
+ if (image2.depth()<32) image2 = image2.convertDepth(32);
+
+ // for blendImage, we handle depth 8 and 32
+ if (blendImage.depth()<8) blendImage = blendImage.convertDepth(8);
+
+ unsigned int *colorTable3 = (blendImage.depth()==8) ?
+ blendImage.colorTable():0;
+
+ unsigned int *data1 = (unsigned int *)image1.bits();
+ unsigned int *data2 = (unsigned int *)image2.bits();
+ unsigned int *data3 = (unsigned int *)blendImage.bits();
+ unsigned char *data3b = (unsigned char *)blendImage.bits();
+ unsigned int color3;
+
+ x1 = image1.width(); y1 = image1.height();
+ x2 = image2.width(); y2 = image2.height();
+ x3 = blendImage.width(); y3 = blendImage.height();
+
+ for (y = 0; y < (int)y1; y++) {
+ ind1 = x1*y;
+ ind2 = x2*(y%y2);
+ ind3 = x3*(y%y3);
+
+ x=0;
+ while(x < (int)x1) {
+ color3 = (colorTable3) ? colorTable3[data3b[ind3]] : data3[ind3];
+
+ a = (channel == Red) ? qRed(color3) :
+ (channel == Green) ? qGreen(color3) :
+ (channel == Blue) ? qBlue(color3) : qGray(color3);
+
+ r = (a*qRed(data1[ind1]) + (256-a)*qRed(data2[ind2]))/256;
+ g = (a*qGreen(data1[ind1]) + (256-a)*qGreen(data2[ind2]))/256;
+ b = (a*qBlue(data1[ind1]) + (256-a)*qBlue(data2[ind2]))/256;
+
+ a = qAlpha(data1[ind1]);
+ data1[ind1] = qRgba(r, g, b, a);
+
+ ind1++; ind2++; ind3++; x++;
+ if ( (x%x2) ==0) ind2 -= x2;
+ if ( (x%x3) ==0) ind3 -= x3;
+ }
+ }
+ return image1;
+}
+
+
+//======================================================================
+//
+// Hash effects
+//
+//======================================================================
+
+unsigned int OImageEffect::lHash(unsigned int c)
+{
+ unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c);
+ unsigned char nr, ng, nb;
+ nr =(r >> 1) + (r >> 2); nr = nr > r ? 0 : nr;
+ ng =(g >> 1) + (g >> 2); ng = ng > g ? 0 : ng;
+ nb =(b >> 1) + (b >> 2); nb = nb > b ? 0 : nb;
+
+ return qRgba(nr, ng, nb, a);
+}
+
+
+// -----------------------------------------------------------------------------
+
+unsigned int OImageEffect::uHash(unsigned int c)
+{
+ unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c);
+ unsigned char nr, ng, nb;
+ nr = r + (r >> 3); nr = nr < r ? ~0 : nr;
+ ng = g + (g >> 3); ng = ng < g ? ~0 : ng;
+ nb = b + (b >> 3); nb = nb < b ? ~0 : nb;
+
+ return qRgba(nr, ng, nb, a);
+}
+
+
+// -----------------------------------------------------------------------------
+
+QImage& OImageEffect::hash(QImage &image, Lighting lite, unsigned int spacing)
+{
+ if (image.width() == 0 || image.height() == 0) {
+#ifndef NDEBUG
+ cerr << "OImageEffect::hash effect invalid image" << endl;
+#endif
+ return image;
+ }
+
+ register int x, y;
+ unsigned int *data = (unsigned int *)image.bits();
+ unsigned int ind;
+
+ //CT no need to do it if not enough space
+ if ((lite == NorthLite ||
+ lite == SouthLite)&&
+ (unsigned)image.height() < 2+spacing) return image;
+ if ((lite == EastLite ||
+ lite == WestLite)&&
+ (unsigned)image.height() < 2+spacing) return image;
+
+ if (lite == NorthLite || lite == SouthLite) {
+ for (y = 0 ; y < image.height(); y = y + 2 + spacing) {
+ for (x = 0; x < image.width(); x++) {
+ ind = x + image.width() * y;
+ data[ind] = lite==NorthLite?uHash(data[ind]):lHash(data[ind]);
+
+ ind = ind + image.width();
+ data[ind] = lite==NorthLite?lHash(data[ind]):uHash(data[ind]);
+ }
+ }
+ }
+
+ else if (lite == EastLite || lite == WestLite) {
+ for (y = 0 ; y < image.height(); y++) {
+ for (x = 0; x < image.width(); x = x + 2 + spacing) {
+ ind = x + image.width() * y;
+ data[ind] = lite==EastLite?uHash(data[ind]):lHash(data[ind]);
+
+ ind++;
+ data[ind] = lite==EastLite?lHash(data[ind]):uHash(data[ind]);
+ }
+ }
+ }
+
+ else if (lite == NWLite || lite == SELite) {
+ for (y = 0 ; y < image.height(); y++) {
+ for (x = 0;
+ x < (int)(image.width() - ((y & 1)? 1 : 0) * spacing);
+ x = x + 2 + spacing) {
+ ind = x + image.width() * y + ((y & 1)? 1 : 0);
+ data[ind] = lite==NWLite?uHash(data[ind]):lHash(data[ind]);
+
+ ind++;
+ data[ind] = lite==NWLite?lHash(data[ind]):uHash(data[ind]);
+ }
+ }
+ }
+
+ else if (lite == SWLite || lite == NELite) {
+ for (y = 0 ; y < image.height(); y++) {
+ for (x = 0 + ((y & 1)? 1 : 0); x < image.width(); x = x + 2 + spacing) {
+ ind = x + image.width() * y - ((y & 1)? 1 : 0);
+ data[ind] = lite==SWLite?uHash(data[ind]):lHash(data[ind]);
+
+ ind++;
+ data[ind] = lite==SWLite?lHash(data[ind]):uHash(data[ind]);
+ }
+ }
+ }
+
+ return image;
+}
+
+
+//======================================================================
+//
+// Flatten effects
+//
+//======================================================================
+
+QImage& OImageEffect::flatten(QImage &img, const QColor &ca,
+ const QColor &cb, int ncols)
+{
+ if (img.width() == 0 || img.height() == 0)
+ return img;
+
+ // a bitmap is easy...
+ if (img.depth() == 1) {
+ img.setColor(0, ca.rgb());
+ img.setColor(1, cb.rgb());
+ return img;
+ }
+
+ int r1 = ca.red(); int r2 = cb.red();
+ int g1 = ca.green(); int g2 = cb.green();
+ int b1 = ca.blue(); int b2 = cb.blue();
+ int min = 0, max = 255;
+
+ QRgb col;
+
+ // Get minimum and maximum greylevel.
+ if (img.numColors()) {
+ // pseudocolor
+ for (int i = 0; i < img.numColors(); i++) {
+ col = img.color(i);
+ int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
+ min = QMIN(min, mean);
+ max = QMAX(max, mean);
+ }
+ } else {
+ // truecolor
+ for (int y=0; y < img.height(); y++)
+ for (int x=0; x < img.width(); x++) {
+ col = img.pixel(x, y);
+ int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
+ min = QMIN(min, mean);
+ max = QMAX(max, mean);
+ }
+ }
+
+ // Conversion factors
+ float sr = ((float) r2 - r1) / (max - min);
+ float sg = ((float) g2 - g1) / (max - min);
+ float sb = ((float) b2 - b1) / (max - min);
+
+
+ // Repaint the image
+ if (img.numColors()) {
+ for (int i=0; i < img.numColors(); i++) {
+ col = img.color(i);
+ int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
+ int r = (int) (sr * (mean - min) + r1 + 0.5);
+ int g = (int) (sg * (mean - min) + g1 + 0.5);
+ int b = (int) (sb * (mean - min) + b1 + 0.5);
+ img.setColor(i, qRgba(r, g, b, qAlpha(col)));
+ }
+ } else {
+ for (int y=0; y < img.height(); y++)
+ for (int x=0; x < img.width(); x++) {
+ col = img.pixel(x, y);
+ int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
+ int r = (int) (sr * (mean - min) + r1 + 0.5);
+ int g = (int) (sg * (mean - min) + g1 + 0.5);
+ int b = (int) (sb * (mean - min) + b1 + 0.5);
+ img.setPixel(x, y, qRgba(r, g, b, qAlpha(col)));
+ }
+ }
+
+
+ // Dither if necessary
+ if ( (ncols <= 0) || ((img.numColors() != 0) && (img.numColors() <= ncols)))
+ return img;
+
+ if (ncols == 1) ncols++;
+ if (ncols > 256) ncols = 256;
+
+ QColor *pal = new QColor[ncols];
+ sr = ((float) r2 - r1) / (ncols - 1);
+ sg = ((float) g2 - g1) / (ncols - 1);
+ sb = ((float) b2 - b1) / (ncols - 1);
+
+ for (int i=0; i<ncols; i++)
+ pal[i] = QColor(r1 + int(sr*i), g1 + int(sg*i), b1 + int(sb*i));
+
+ dither(img, pal, ncols);
+
+ delete[] pal;
+ return img;
+}
+
+
+//======================================================================
+//
+// Fade effects
+//
+//======================================================================
+
+QImage& OImageEffect::fade(QImage &img, float val, const QColor &color)
+{
+ if (img.width() == 0 || img.height() == 0)
+ return img;
+
+ // We don't handle bitmaps
+ if (img.depth() == 1)
+ return img;
+
+ unsigned char tbl[256];
+ for (int i=0; i<256; i++)
+ tbl[i] = (int) (val * i + 0.5);
+
+ int red = color.red();
+ int green = color.green();
+ int blue = color.blue();
+
+ QRgb col;
+ int r, g, b, cr, cg, cb;
+
+ if (img.depth() <= 8) {
+ // pseudo color
+ for (int i=0; i<img.numColors(); i++) {
+ col = img.color(i);
+ cr = qRed(col); cg = qGreen(col); cb = qBlue(col);
+ if (cr > red)
+ r = cr - tbl[cr - red];
+ else
+ r = cr + tbl[red - cr];
+ if (cg > green)
+ g = cg - tbl[cg - green];
+ else
+ g = cg + tbl[green - cg];
+ if (cb > blue)
+ b = cb - tbl[cb - blue];
+ else
+ b = cb + tbl[blue - cb];
+ img.setColor(i, qRgba(r, g, b, qAlpha(col)));
+ }
+
+ } else {
+ // truecolor
+ for (int y=0; y<img.height(); y++) {
+ QRgb *data = (QRgb *) img.scanLine(y);
+ for (int x=0; x<img.width(); x++) {
+ col = *data;
+ cr = qRed(col); cg = qGreen(col); cb = qBlue(col);
+ if (cr > red)
+ r = cr - tbl[cr - red];
+ else
+ r = cr + tbl[red - cr];
+ if (cg > green)
+ g = cg - tbl[cg - green];
+ else
+ g = cg + tbl[green - cg];
+ if (cb > blue)
+ b = cb - tbl[cb - blue];
+ else
+ b = cb + tbl[blue - cb];
+ *data++ = qRgba(r, g, b, qAlpha(col));
+ }
+ }
+ }
+
+ return img;
+}
+
+//======================================================================
+//
+// Color effects
+//
+//======================================================================
+
+// This code is adapted from code (C) Rik Hemsley <rik@kde.org>
+//
+// The formula used (r + b + g) /3 is different from the qGray formula
+// used by Qt. This is because our formula is much much faster. If,
+// however, it turns out that this is producing sub-optimal images,
+// then it will have to change (kurt)
+//
+// It does produce lower quality grayscale ;-) Use fast == true for the fast
+// algorithm, false for the higher quality one (mosfet).
+QImage& OImageEffect::toGray(QImage &img, bool fast)
+{
+ if (img.width() == 0 || img.height() == 0)
+ return img;
+
+ if(fast){
+ if (img.depth() == 32) {
+ register uchar * r(img.bits());
+ register uchar * g(img.bits() + 1);
+ register uchar * b(img.bits() + 2);
+
+ uchar * end(img.bits() + img.numBytes());
+
+ while (r != end) {
+
+ *r = *g = *b = (((*r + *g) >> 1) + *b) >> 1; // (r + b + g) / 3
+
+ r += 4;
+ g += 4;
+ b += 4;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < img.numColors(); i++)
+ {
+ register uint r = qRed(img.color(i));
+ register uint g = qGreen(img.color(i));
+ register uint b = qBlue(img.color(i));
+
+ register uint gray = (((r + g) >> 1) + b) >> 1;
+ img.setColor(i, qRgba(gray, gray, gray, qAlpha(img.color(i))));
+ }
+ }
+ }
+ else{
+ int pixels = img.depth() > 8 ? img.width()*img.height() :
+ img.numColors();
+ unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
+ (unsigned int *)img.colorTable();
+ int val, i;
+ for(i=0; i < pixels; ++i){
+ val = qGray(data[i]);
+ data[i] = qRgba(val, val, val, qAlpha(data[i]));
+ }
+ }
+ return img;
+}
+
+// CT 29Jan2000 - desaturation algorithms
+QImage& OImageEffect::desaturate(QImage &img, float desat)
+{
+ if (img.width() == 0 || img.height() == 0)
+ return img;
+
+ if (desat < 0) desat = 0.;
+ if (desat > 1) desat = 1.;
+ int pixels = img.depth() > 8 ? img.width()*img.height() :
+ img.numColors();
+ unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
+ (unsigned int *)img.colorTable();
+ int h, s, v, i;
+ QColor clr; // keep constructor out of loop (mosfet)
+ for(i=0; i < pixels; ++i){
+ clr.setRgb(data[i]);
+ clr.hsv(&h, &s, &v);
+ clr.setHsv(h, (int)(s * (1. - desat)), v);
+ data[i] = clr.rgb();
+ }
+ return img;
+}
+
+// Contrast stuff (mosfet)
+QImage& OImageEffect::contrast(QImage &img, int c)
+{
+ if (img.width() == 0 || img.height() == 0)
+ return img;
+
+ if(c > 255)
+ c = 255;
+ if(c < -255)
+ c = -255;
+ int pixels = img.depth() > 8 ? img.width()*img.height() :
+ img.numColors();
+ unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
+ (unsigned int *)img.colorTable();
+ int i, r, g, b;
+ for(i=0; i < pixels; ++i){
+ r = qRed(data[i]);
+ g = qGreen(data[i]);
+ b = qBlue(data[i]);
+ if(qGray(data[i]) <= 127){
+ if(r - c <= 255)
+ r -= c;
+ if(g - c <= 255)
+ g -= c;
+ if(b - c <= 255)
+ b -= c;
+ }
+ else{
+ if(r + c <= 255)
+ r += c;
+ if(g + c <= 255)
+ g += c;
+ if(b + c <= 255)
+ b += c;
+ }
+ data[i] = qRgba(r, g, b, qAlpha(data[i]));
+ }
+ return(img);
+}
+
+//======================================================================
+//
+// Dithering effects
+//
+//======================================================================
+
+// adapted from kFSDither (C) 1997 Martin Jones (mjones@kde.org)
+//
+// Floyd-Steinberg dithering
+// Ref: Bitmapped Graphics Programming in C++
+// Marv Luse, Addison-Wesley Publishing, 1993.
+QImage& OImageEffect::dither(QImage &img, const QColor *palette, int size)
+{
+ if (img.width() == 0 || img.height() == 0 ||
+ palette == 0 || img.depth() <= 8)
+ return img;
+
+ QImage dImage( img.width(), img.height(), 8, size );
+ int i;
+
+ dImage.setNumColors( size );
+ for ( i = 0; i < size; i++ )
+ dImage.setColor( i, palette[ i ].rgb() );
+
+ int *rerr1 = new int [ img.width() * 2 ];
+ int *gerr1 = new int [ img.width() * 2 ];
+ int *berr1 = new int [ img.width() * 2 ];
+
+ memset( rerr1, 0, sizeof( int ) * img.width() * 2 );
+ memset( gerr1, 0, sizeof( int ) * img.width() * 2 );
+ memset( berr1, 0, sizeof( int ) * img.width() * 2 );
+
+ int *rerr2 = rerr1 + img.width();
+ int *gerr2 = gerr1 + img.width();
+ int *berr2 = berr1 + img.width();
+
+ for ( int j = 0; j < img.height(); j++ )
+ {
+ uint *ip = (uint * )img.scanLine( j );
+ uchar *dp = dImage.scanLine( j );
+
+ for ( i = 0; i < img.width(); i++ )
+ {
+ rerr1[i] = rerr2[i] + qRed( *ip );
+ rerr2[i] = 0;
+ gerr1[i] = gerr2[i] + qGreen( *ip );
+ gerr2[i] = 0;
+ berr1[i] = berr2[i] + qBlue( *ip );
+ berr2[i] = 0;
+ ip++;
+ }
+
+ *dp++ = nearestColor( rerr1[0], gerr1[0], berr1[0], palette, size );
+
+ for ( i = 1; i < img.width()-1; i++ )
+ {
+ int indx = nearestColor( rerr1[i], gerr1[i], berr1[i], palette, size );
+ *dp = indx;
+
+ int rerr = rerr1[i];
+ rerr -= palette[indx].red();
+ int gerr = gerr1[i];
+ gerr -= palette[indx].green();
+ int berr = berr1[i];
+ berr -= palette[indx].blue();
+
+ // diffuse red error
+ rerr1[ i+1 ] += ( rerr * 7 ) >> 4;
+ rerr2[ i-1 ] += ( rerr * 3 ) >> 4;
+ rerr2[ i ] += ( rerr * 5 ) >> 4;
+ rerr2[ i+1 ] += ( rerr ) >> 4;
+
+ // diffuse green error
+ gerr1[ i+1 ] += ( gerr * 7 ) >> 4;
+ gerr2[ i-1 ] += ( gerr * 3 ) >> 4;
+ gerr2[ i ] += ( gerr * 5 ) >> 4;
+ gerr2[ i+1 ] += ( gerr ) >> 4;
+
+ // diffuse red error
+ berr1[ i+1 ] += ( berr * 7 ) >> 4;
+ berr2[ i-1 ] += ( berr * 3 ) >> 4;
+ berr2[ i ] += ( berr * 5 ) >> 4;
+ berr2[ i+1 ] += ( berr ) >> 4;
+
+ dp++;
+ }
+
+ *dp = nearestColor( rerr1[i], gerr1[i], berr1[i], palette, size );
+ }
+
+ delete [] rerr1;
+ delete [] gerr1;
+ delete [] berr1;
+
+ img = dImage;
+ return img;
+}
+
+int OImageEffect::nearestColor( int r, int g, int b, const QColor *palette, int size )
+{
+ if (palette == 0)
+ return 0;
+
+ int dr = palette[0].red() - r;
+ int dg = palette[0].green() - g;
+ int db = palette[0].blue() - b;
+
+ int minDist = dr*dr + dg*dg + db*db;
+ int nearest = 0;
+
+ for (int i = 1; i < size; i++ )
+ {
+ dr = palette[i].red() - r;
+ dg = palette[i].green() - g;
+ db = palette[i].blue() - b;
+
+ int dist = dr*dr + dg*dg + db*db;
+
+ if ( dist < minDist )
+ {
+ minDist = dist;
+ nearest = i;
+ }
+ }
+
+ return nearest;
+}
+
+bool OImageEffect::blend(
+ const QImage & upper,
+ const QImage & lower,
+ QImage & output
+)
+{
+ if (
+ upper.width() > lower.width() ||
+ upper.height() > lower.height() ||
+ upper.depth() != 32 ||
+ lower.depth() != 32
+ )
+ {
+#ifndef NDEBUG
+ cerr << "OImageEffect::blend : Sizes not correct\n" ;
+#endif
+ return false;
+ }
+
+ output = lower.copy();
+
+ register uchar *i, *o;
+ register int a;
+ register int col;
+ register int w = upper.width();
+ int row(upper.height() - 1);
+
+ do {
+
+ i = upper.scanLine(row);
+ o = output.scanLine(row);
+
+ col = w << 2;
+ --col;
+
+ do {
+
+ while (!(a = i[col]) && (col != 3)) {
+ --col; --col; --col; --col;
+ }
+
+ --col;
+ o[col] += ((i[col] - o[col]) * a) >> 8;
+
+ --col;
+ o[col] += ((i[col] - o[col]) * a) >> 8;
+
+ --col;
+ o[col] += ((i[col] - o[col]) * a) >> 8;
+
+ } while (col--);
+
+ } while (row--);
+
+ return true;
+}
+
+#if 0
+// Not yet...
+bool OImageEffect::blend(
+ const QImage & upper,
+ const QImage & lower,
+ QImage & output,
+ const QRect & destRect
+)
+{
+ output = lower.copy();
+ return output;
+}
+
+#endif
+
+bool OImageEffect::blend(
+ int &x, int &y,
+ const QImage & upper,
+ const QImage & lower,
+ QImage & output
+)
+{
+ int cx=0, cy=0, cw=upper.width(), ch=upper.height();
+
+ if ( upper.width() + x > lower.width() ||
+ upper.height() + y > lower.height() ||
+ x < 0 || y < 0 ||
+ upper.depth() != 32 || lower.depth() != 32 )
+ {
+ if ( x > lower.width() || y > lower.height() ) return false;
+ if ( upper.width()<=0 || upper.height() <= 0 ) return false;
+ if ( lower.width()<=0 || lower.height() <= 0 ) return false;
+
+ if (x<0) {cx=-x; cw+=x; x=0; };
+ if (cw + x > lower.width()) { cw=lower.width()-x; };
+ if (y<0) {cy=-y; ch+=y; y=0; };
+ if (ch + y > lower.height()) { ch=lower.height()-y; };
+
+ if ( cx >= upper.width() || cy >= upper.height() ) return true;
+ if ( cw <= 0 || ch <= 0 ) return true;
+ }
+
+ output.create(cw,ch,32);
+// output.setAlphaBuffer(true); // I should do some benchmarks to see if
+ // this is worth the effort
+
+ register QRgb *i, *o, *b;
+
+ register int a;
+ register int j,k;
+ for (j=0; j<ch; j++)
+ {
+ b=reinterpret_cast<QRgb *>(&lower.scanLine(y+j) [ (x+cw) << 2 ]);
+ i=reinterpret_cast<QRgb *>(&upper.scanLine(cy+j)[ (cx+cw) << 2 ]);
+ o=reinterpret_cast<QRgb *>(&output.scanLine(j) [ cw << 2 ]);
+
+ k=cw-1;
+ --b; --i; --o;
+ do
+ {
+ while ( !(a=qAlpha(*i)) && k>0 )
+ {
+ i--;
+// *o=0;
+ *o=*b;
+ --o; --b;
+ k--;
+ };
+// *o=0xFF;
+ *o = qRgb(qRed(*b) + (((qRed(*i) - qRed(*b)) * a) >> 8),
+ qGreen(*b) + (((qGreen(*i) - qGreen(*b)) * a) >> 8),
+ qBlue(*b) + (((qBlue(*i) - qBlue(*b)) * a) >> 8));
+ --i; --o; --b;
+ } while (k--);
+ }
+
+ return true;
+}
+
+bool OImageEffect::blendOnLower(
+ int x, int y,
+ const QImage & upper,
+ const QImage & lower
+)
+{
+ int cx=0, cy=0, cw=upper.width(), ch=upper.height();
+
+ if ( upper.depth() != 32 || lower.depth() != 32 ) return false;
+ if ( x + cw > lower.width() ||
+ y + ch > lower.height() ||
+ x < 0 || y < 0 )
+ {
+ if ( x > lower.width() || y > lower.height() ) return true;
+ if ( upper.width()<=0 || upper.height() <= 0 ) return true;
+ if ( lower.width()<=0 || lower.height() <= 0 ) return true;
+
+ if (x<0) {cx=-x; cw+=x; x=0; };
+ if (cw + x > lower.width()) { cw=lower.width()-x; };
+ if (y<0) {cy=-y; ch+=y; y=0; };
+ if (ch + y > lower.height()) { ch=lower.height()-y; };
+
+ if ( cx >= upper.width() || cy >= upper.height() ) return true;
+ if ( cw <= 0 || ch <= 0 ) return true;
+ }
+
+ register uchar *i, *b;
+ register int a;
+ register int k;
+
+ for (int j=0; j<ch; j++)
+ {
+ b=&lower.scanLine(y+j) [ (x+cw) << 2 ];
+ i=&upper.scanLine(cy+j)[ (cx+cw) << 2 ];
+
+ k=cw-1;
+ --b; --i;
+ do
+ {
+#ifndef WORDS_BIGENDIAN
+ while ( !(a=*i) && k>0 )
+#else
+ while ( !(a=*(i-3)) && k>0 )
+#endif
+ {
+ i-=4; b-=4; k--;
+ };
+
+#ifndef WORDS_BIGENDIAN
+ --i; --b;
+ *b += ( ((*i - *b) * a) >> 8 );
+ --i; --b;
+ *b += ( ((*i - *b) * a) >> 8 );
+ --i; --b;
+ *b += ( ((*i - *b) * a) >> 8 );
+ --i; --b;
+#else
+ *b += ( ((*i - *b) * a) >> 8 );
+ --i; --b;
+ *b += ( ((*i - *b) * a) >> 8 );
+ --i; --b;
+ *b += ( ((*i - *b) * a) >> 8 );
+ i -= 2; b -= 2;
+#endif
+ } while (k--);
+ }
+
+ return true;
+}
+
+// For selected icons
+QImage& OImageEffect::selectedImage( QImage &img, const QColor &col )
+{
+ return blend( col, img, 0.5);
+}
+
+//
+// ===================================================================
+// Effects originally ported from ImageMagick for PixiePlus, plus a few
+// new ones. (mosfet 12/29/01)
+// ===================================================================
+//
+
+void OImageEffect::normalize(QImage &img)
+{
+ int *histogram, threshold_intensity, intense;
+ int x, y, i;
+
+ unsigned int gray_value;
+ unsigned int *normalize_map;
+ unsigned int high, low;
+
+ // allocate histogram and normalize map
+ histogram = (int *)calloc(MaxRGB+1, sizeof(int));
+ normalize_map = (unsigned int *)malloc((MaxRGB+1)*sizeof(unsigned int));
+ if(!normalize_map || !histogram){
+ qWarning("Unable to allocate normalize histogram and map");
+ free(normalize_map);
+ free(histogram);
+ return;
+ }
+
+ // form histogram
+ if(img.depth() > 8){ // DirectClass
+ unsigned int *data;
+ for(y=0; y < img.height(); ++y){
+ data = (unsigned int *)img.scanLine(y);
+ for(x=0; x < img.width(); ++x){
+ gray_value = intensityValue(data[x]);
+ histogram[gray_value]++;
+ }
+ }
+ }
+ else{ // PsudeoClass
+ unsigned char *data;
+ unsigned int *cTable = img.colorTable();
+ for(y=0; y < img.height(); ++y){
+ data = (unsigned char *)img.scanLine(y);
+ for(x=0; x < img.width(); ++x){
+ gray_value = intensityValue(*(cTable+data[x]));
+ histogram[gray_value]++;
+ }
+ }
+ }
+
+ // find histogram boundaries by locating the 1 percent levels
+ threshold_intensity = (img.width()*img.height())/100;
+ intense = 0;
+ for(low=0; low < MaxRGB; ++low){
+ intense+=histogram[low];
+ if(intense > threshold_intensity)
+ break;
+ }
+ intense=0;
+ for(high=MaxRGB; high != 0; --high){
+ intense+=histogram[high];
+ if(intense > threshold_intensity)
+ break;
+ }
+
+ if (low == high){
+ // Unreasonable contrast; use zero threshold to determine boundaries.
+ threshold_intensity=0;
+ intense=0;
+ for(low=0; low < MaxRGB; ++low){
+ intense+=histogram[low];
+ if(intense > threshold_intensity)
+ break;
+ }
+ intense=0;
+ for(high=MaxRGB; high != 0; --high)
+ {
+ intense+=histogram[high];
+ if(intense > threshold_intensity)
+ break;
+ }
+ if(low == high)
+ return; // zero span bound
+ }
+
+ // Stretch the histogram to create the normalized image mapping.
+ for(i=0; i <= MaxRGB; i++){
+ if (i < (int) low)
+ normalize_map[i]=0;
+ else{
+ if(i > (int) high)
+ normalize_map[i]=MaxRGB;
+ else
+ normalize_map[i]=(MaxRGB-1)*(i-low)/(high-low);
+ }
+ }
+ // Normalize
+ if(img.depth() > 8){ // DirectClass
+ unsigned int *data;
+ for(y=0; y < img.height(); ++y){
+ data = (unsigned int *)img.scanLine(y);
+ for(x=0; x < img.width(); ++x){
+ data[x] = qRgba(normalize_map[qRed(data[x])],
+ normalize_map[qGreen(data[x])],
+ normalize_map[qBlue(data[x])],
+ qAlpha(data[x]));
+ }
+ }
+ }
+ else{ // PsudeoClass
+ int colors = img.numColors();
+ unsigned int *cTable = img.colorTable();
+ for(i=0; i < colors; ++i){
+ cTable[i] = qRgba(normalize_map[qRed(cTable[i])],
+ normalize_map[qGreen(cTable[i])],
+ normalize_map[qBlue(cTable[i])],
+ qAlpha(cTable[i]));
+ }
+ }
+ free(histogram);
+ free(normalize_map);
+}
+
+
+void OImageEffect::equalize(QImage &img)
+{
+ int *histogram, *map, *equalize_map;
+ int x, y, i, j;
+
+ unsigned int high, low;
+
+ // allocate histogram and maps
+ histogram = (int *)calloc(MaxRGB+1, sizeof(int));
+ map = (int *)malloc((MaxRGB+1)*sizeof(unsigned int));
+ equalize_map = (int *)malloc((MaxRGB+1)*sizeof(unsigned int));
+
+ if(!histogram || !map || !equalize_map){
+ qWarning("Unable to allocate equalize histogram and maps");
+ free(histogram);
+ free(map);
+ free(equalize_map);
+ return;
+ }
+ // form histogram
+ if(img.depth() > 8){ // DirectClass
+ unsigned int *data;
+ for(y=0; y < img.height(); ++y){
+ data = (unsigned int *)img.scanLine(y);
+ for(x=0; x < img.width(); ++x){
+ histogram[intensityValue(data[x])]++;
+ }
+ }
+ }
+ else{ // PsudeoClass
+ unsigned char *data;
+ unsigned int *cTable = img.colorTable();
+ for(y=0; y < img.height(); ++y){
+ data = (unsigned char *)img.scanLine(y);
+ for(x=0; x < img.width(); ++x){
+ histogram[intensityValue(*(cTable+data[x]))]++;
+ }
+ }
+ }
+
+ // integrate the histogram to get the equalization map.
+ j=0;
+ for(i=0; i <= MaxRGB; i++){
+ j+=histogram[i];
+ map[i]=j;
+ }
+ free(histogram);
+ if(map[MaxRGB] == 0){
+ free(equalize_map);
+ free(map);
+ return;
+ }
+ // equalize
+ low=map[0];
+ high=map[MaxRGB];
+ for(i=0; i <= MaxRGB; i++)
+ equalize_map[i]=(unsigned int)
+ ((((double) (map[i]-low))*MaxRGB)/QMAX(high-low,1));
+ free(map);
+ // stretch the histogram
+ if(img.depth() > 8){ // DirectClass
+ unsigned int *data;
+ for(y=0; y < img.height(); ++y){
+ data = (unsigned int *)img.scanLine(y);
+ for(x=0; x < img.width(); ++x){
+ data[x] = qRgba(equalize_map[qRed(data[x])],
+ equalize_map[qGreen(data[x])],
+ equalize_map[qBlue(data[x])],
+ qAlpha(data[x]));
+ }
+ }
+ }
+ else{ // PsudeoClass
+ int colors = img.numColors();
+ unsigned int *cTable = img.colorTable();
+ for(i=0; i < colors; ++i){
+ cTable[i] = qRgba(equalize_map[qRed(cTable[i])],
+ equalize_map[qGreen(cTable[i])],
+ equalize_map[qBlue(cTable[i])],
+ qAlpha(cTable[i]));
+ }
+ }
+ free(equalize_map);
+}
+
+QImage OImageEffect::sample(QImage &src, int w, int h)
+{
+ if(w == src.width() && h == src.height())
+ return(src);
+
+ double *x_offset, *y_offset;
+ int j, k, y;
+ register int x;
+ QImage dest(w, h, src.depth());
+
+ x_offset = (double *)malloc(w*sizeof(double));
+ y_offset = (double *)malloc(h*sizeof(double));
+ if(!x_offset || !y_offset){
+ qWarning("Unable to allocate pixels buffer");
+ free(x_offset);
+ free(y_offset);
+ return(src);
+ }
+
+ // init pixel offsets
+ for(x=0; x < w; ++x)
+ x_offset[x] = x*src.width()/((double)w);
+ for(y=0; y < h; ++y)
+ y_offset[y] = y*src.height()/((double)h);
+
+ // sample each row
+ if(src.depth() > 8){ // DirectClass source image
+ unsigned int *srcData, *destData;
+ unsigned int *pixels;
+ pixels = (unsigned int *)malloc(src.width()*sizeof(unsigned int));
+ if(!pixels){
+ qWarning("Unable to allocate pixels buffer");
+ free(pixels);
+ free(x_offset);
+ free(y_offset);
+ return(src);
+ }
+ j = (-1);
+ for(y=0; y < h; ++y){
+ destData = (unsigned int *)dest.scanLine(y);
+ if(j != y_offset[y]){
+ // read a scan line
+ j = (int)(y_offset[y]);
+ srcData = (unsigned int *)src.scanLine(j);
+ (void)memcpy(pixels, srcData, src.width()*sizeof(unsigned int));
+ }
+ // sample each column
+ for(x=0; x < w; ++x){
+ k = (int)(x_offset[x]);
+ destData[x] = pixels[k];
+ }
+ }
+ free(pixels);
+ }
+ else{ // PsudeoClass source image
+ unsigned char *srcData, *destData;
+ unsigned char *pixels;
+ pixels = (unsigned char *)malloc(src.width()*sizeof(unsigned char));
+ if(!pixels){
+ qWarning("Unable to allocate pixels buffer");
+ free(pixels);
+ free(x_offset);
+ free(y_offset);
+ return(src);
+ }
+ // copy colortable
+ dest.setNumColors(src.numColors());
+ (void)memcpy(dest.colorTable(), src.colorTable(),
+ src.numColors()*sizeof(unsigned int));
+
+ // sample image
+ j = (-1);
+ for(y=0; y < h; ++y){
+ destData = (unsigned char *)dest.scanLine(y);
+ if(j != y_offset[y]){
+ // read a scan line
+ j = (int)(y_offset[y]);
+ srcData = (unsigned char *)src.scanLine(j);
+ (void)memcpy(pixels, srcData, src.width()*sizeof(unsigned char));
+ }
+ // sample each column
+ for(x=0; x < w; ++x){
+ k = (int)(x_offset[x]);
+ destData[x] = pixels[k];
+ }
+ }
+ free(pixels);
+ }
+ free(x_offset);
+ free(y_offset);
+ return(dest);
+}
+
+void OImageEffect::threshold(QImage &img, unsigned int threshold)
+{
+ int i, count;
+ unsigned int *data;
+ if(img.depth() > 8){ // DirectClass
+ count = img.width()*img.height();
+ data = (unsigned int *)img.bits();
+ }
+ else{ // PsudeoClass
+ count = img.numColors();
+ data = (unsigned int *)img.colorTable();
+ }
+ for(i=0; i < count; ++i)
+ data[i] = intensityValue(data[i]) < threshold ? Qt::black.rgb() : Qt::white.rgb();
+}
+
+QImage OImageEffect::charcoal(QImage &src, double factor)
+{
+ QImage dest(src);
+ dest.detach();
+ toGray(dest);
+ dest = edge(dest, factor);
+ dest = blur(dest, factor);
+ normalize(dest);
+ dest.invertPixels(false);
+ return(dest);
+}
+
+void OImageEffect::hull(const int x_offset, const int y_offset,
+ const int polarity, const int columns,
+ const int rows,
+ unsigned int *f, unsigned int *g)
+{
+ int x, y;
+
+ unsigned int *p, *q, *r, *s;
+ unsigned int v;
+ if(f == NULL || g == NULL)
+ return;
+ p=f+(columns+2);
+ q=g+(columns+2);
+ r=p+(y_offset*(columns+2)+x_offset);
+ for (y=0; y < rows; y++){
+ p++;
+ q++;
+ r++;
+ if(polarity > 0)
+ for (x=0; x < columns; x++){
+ v=(*p);
+ if (*r > v)
+ v++;
+ *q=v;
+ p++;
+ q++;
+ r++;
+ }
+ else
+ for(x=0; x < columns; x++){
+ v=(*p);
+ if (v > (unsigned int) (*r+1))
+ v--;
+ *q=v;
+ p++;
+ q++;
+ r++;
+ }
+ p++;
+ q++;
+ r++;
+ }
+ p=f+(columns+2);
+ q=g+(columns+2);
+ r=q+(y_offset*(columns+2)+x_offset);
+ s=q-(y_offset*(columns+2)+x_offset);
+ for(y=0; y < rows; y++){
+ p++;
+ q++;
+ r++;
+ s++;
+ if(polarity > 0)
+ for(x=0; x < (int) columns; x++){
+ v=(*q);
+ if (((unsigned int) (*s+1) > v) && (*r > v))
+ v++;
+ *p=v;
+ p++;
+ q++;
+ r++;
+ s++;
+ }
+ else
+ for (x=0; x < columns; x++){
+ v=(*q);
+ if (((unsigned int) (*s+1) < v) && (*r < v))
+ v--;
+ *p=v;
+ p++;
+ q++;
+ r++;
+ s++;
+ }
+ p++;
+ q++;
+ r++;
+ s++;
+ }
+}
+
+QImage OImageEffect::despeckle(QImage &src)
+{
+ int i, j, x, y;
+ unsigned int *blue_channel, *red_channel, *green_channel, *buffer,
+ *alpha_channel;
+ int packets;
+ static const int
+ X[4]= {0, 1, 1,-1},
+ Y[4]= {1, 0, 1, 1};
+
+ unsigned int *destData;
+ QImage dest(src.width(), src.height(), 32);
+
+ packets = (src.width()+2)*(src.height()+2);
+ red_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
+ green_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
+ blue_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
+ alpha_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
+ buffer = (unsigned int *)calloc(packets, sizeof(unsigned int));
+ if(!red_channel || ! green_channel || ! blue_channel || ! alpha_channel ||
+ !buffer){
+ free(red_channel);
+ free(green_channel);
+ free(blue_channel);
+ free(alpha_channel);
+ free(buffer);
+ return(src);
+ }
+
+ // copy image pixels to color component buffers
+ j = src.width()+2;
+ if(src.depth() > 8){ // DirectClass source image
+ unsigned int *srcData;
+ for(y=0; y < src.height(); ++y){
+ srcData = (unsigned int *)src.scanLine(y);
+ ++j;
+ for(x=0; x < src.width(); ++x){
+ red_channel[j] = qRed(srcData[x]);
+ green_channel[j] = qGreen(srcData[x]);
+ blue_channel[j] = qBlue(srcData[x]);
+ alpha_channel[j] = qAlpha(srcData[x]);
+ ++j;
+ }
+ ++j;
+ }
+ }
+ else{ // PsudeoClass source image
+ unsigned char *srcData;
+ unsigned int *cTable = src.colorTable();
+ unsigned int pixel;
+ for(y=0; y < src.height(); ++y){
+ srcData = (unsigned char *)src.scanLine(y);
+ ++j;
+ for(x=0; x < src.width(); ++x){
+ pixel = *(cTable+srcData[x]);
+ red_channel[j] = qRed(pixel);
+ green_channel[j] = qGreen(pixel);
+ blue_channel[j] = qBlue(pixel);
+ alpha_channel[j] = qAlpha(pixel);
+ ++j;
+ }
+ ++j;
+ }
+ }
+ // reduce speckle in red channel
+ for(i=0; i < 4; i++){
+ hull(X[i],Y[i],1,src.width(),src.height(),red_channel,buffer);
+ hull(-X[i],-Y[i],1,src.width(),src.height(),red_channel,buffer);
+ hull(-X[i],-Y[i],-1,src.width(),src.height(),red_channel,buffer);
+ hull(X[i],Y[i],-1,src.width(),src.height(),red_channel,buffer);
+ }
+ // reduce speckle in green channel
+ for (i=0; i < packets; i++)
+ buffer[i]=0;
+ for (i=0; i < 4; i++){
+ hull(X[i],Y[i],1,src.width(),src.height(),green_channel,buffer);
+ hull(-X[i],-Y[i],1,src.width(),src.height(),green_channel,buffer);
+ hull(-X[i],-Y[i],-1,src.width(),src.height(),green_channel,buffer);
+ hull(X[i],Y[i],-1,src.width(),src.height(),green_channel,buffer);
+ }
+ // reduce speckle in blue channel
+ for (i=0; i < packets; i++)
+ buffer[i]=0;
+ for (i=0; i < 4; i++){
+ hull(X[i],Y[i],1,src.width(),src.height(),blue_channel,buffer);
+ hull(-X[i],-Y[i],1,src.width(),src.height(),blue_channel,buffer);
+ hull(-X[i],-Y[i],-1,src.width(),src.height(),blue_channel,buffer);
+ hull(X[i],Y[i],-1,src.width(),src.height(),blue_channel,buffer);
+ }
+ // copy color component buffers to despeckled image
+ j = dest.width()+2;
+ for(y=0; y < dest.height(); ++y)
+ {
+ destData = (unsigned int *)dest.scanLine(y);
+ ++j;
+ for (x=0; x < dest.width(); ++x)
+ {
+ destData[x] = qRgba(red_channel[j], green_channel[j],
+ blue_channel[j], alpha_channel[j]);
+ ++j;
+ }
+ ++j;
+ }
+ free(buffer);
+ free(red_channel);
+ free(green_channel);
+ free(blue_channel);
+ free(alpha_channel);
+ return(dest);
+}
+
+unsigned int OImageEffect::generateNoise(unsigned int pixel,
+ NoiseType noise_type)
+{
+#define NoiseEpsilon 1.0e-5
+#define NoiseMask 0x7fff
+#define SigmaUniform 4.0
+#define SigmaGaussian 4.0
+#define SigmaImpulse 0.10
+#define SigmaLaplacian 10.0
+#define SigmaMultiplicativeGaussian 0.5
+#define SigmaPoisson 0.05
+#define TauGaussian 20.0
+
+ double alpha, beta, sigma, value;
+ alpha=(double) (rand() & NoiseMask)/NoiseMask;
+ if (alpha == 0.0)
+ alpha=1.0;
+ switch(noise_type){
+ case UniformNoise:
+ default:
+ {
+ value=(double) pixel+SigmaUniform*(alpha-0.5);
+ break;
+ }
+ case GaussianNoise:
+ {
+ double tau;
+
+ beta=(double) (rand() & NoiseMask)/NoiseMask;
+ sigma=sqrt(-2.0*log(alpha))*cos(2.0*M_PI*beta);
+ tau=sqrt(-2.0*log(alpha))*sin(2.0*M_PI*beta);
+ value=(double) pixel+
+ (sqrt((double) pixel)*SigmaGaussian*sigma)+(TauGaussian*tau);
+ break;
+ }
+ case MultiplicativeGaussianNoise:
+ {
+ if (alpha <= NoiseEpsilon)
+ sigma=MaxRGB;
+ else
+ sigma=sqrt(-2.0*log(alpha));
+ beta=(rand() & NoiseMask)/NoiseMask;
+ value=(double) pixel+
+ pixel*SigmaMultiplicativeGaussian*sigma*cos(2.0*M_PI*beta);
+ break;
+ }
+ case ImpulseNoise:
+ {
+ if (alpha < (SigmaImpulse/2.0))
+ value=0;
+ else
+ if (alpha >= (1.0-(SigmaImpulse/2.0)))
+ value=MaxRGB;
+ else
+ value=pixel;
+ break;
+ }
+ case LaplacianNoise:
+ {
+ if (alpha <= 0.5)
+ {
+ if (alpha <= NoiseEpsilon)
+ value=(double) pixel-MaxRGB;
+ else
+ value=(double) pixel+SigmaLaplacian*log(2.0*alpha);
+ break;
+ }
+ beta=1.0-alpha;
+ if (beta <= (0.5*NoiseEpsilon))
+ value=(double) pixel+MaxRGB;
+ else
+ value=(double) pixel-SigmaLaplacian*log(2.0*beta);
+ break;
+ }
+ case PoissonNoise:
+ {
+ register int
+ i;
+
+ for (i=0; alpha > exp(-SigmaPoisson*pixel); i++)
+ {
+ beta=(double) (rand() & NoiseMask)/NoiseMask;
+ alpha=alpha*beta;
+ }
+ value=i/SigmaPoisson;
+ break;
+ }
+ }
+ if(value < 0.0)
+ return(0);
+ if(value > MaxRGB)
+ return(MaxRGB);
+ return((unsigned int) (value+0.5));
+}
+
+QImage OImageEffect::addNoise(QImage &src, NoiseType noise_type)
+{
+ int x, y;
+ QImage dest(src.width(), src.height(), 32);
+ unsigned int *destData;
+
+ if(src.depth() > 8){ // DirectClass source image
+ unsigned int *srcData;
+ for(y=0; y < src.height(); ++y){
+ srcData = (unsigned int *)src.scanLine(y);
+ destData = (unsigned int *)dest.scanLine(y);
+ for(x=0; x < src.width(); ++x){
+ destData[x] = qRgba(generateNoise(qRed(srcData[x]), noise_type),
+ generateNoise(qGreen(srcData[x]), noise_type),
+ generateNoise(qBlue(srcData[x]), noise_type),
+ qAlpha(srcData[x]));
+ }
+ }
+ }
+ else{ // PsudeoClass source image
+ unsigned char *srcData;
+ unsigned int *cTable = src.colorTable();
+ unsigned int pixel;
+ for(y=0; y < src.height(); ++y){
+ srcData = (unsigned char *)src.scanLine(y);
+ destData = (unsigned int *)dest.scanLine(y);
+ for(x=0; x < src.width(); ++x){
+ pixel = *(cTable+srcData[x]);
+ destData[x] = qRgba(generateNoise(qRed(pixel), noise_type),
+ generateNoise(qGreen(pixel), noise_type),
+ generateNoise(qBlue(pixel), noise_type),
+ qAlpha(pixel));
+ }
+ }
+
+ }
+ return(dest);
+}
+
+unsigned int OImageEffect::interpolateColor(QImage *image, double x_offset,
+ double y_offset,
+ unsigned int background)
+{
+ double alpha, beta;
+ unsigned int p, q, r, s;
+ int x, y;
+
+ x = (int)x_offset;
+ y = (int)y_offset;
+ if((x < -1) || (x >= image->width()) || (y < -1) || (y >= image->height()))
+ return(background);
+ if(image->depth() > 8){
+ if((x >= 0) && (y >= 0) && (x < (image->width()-1)) && (y < (image->height()-1))) {
+ unsigned int *t = (unsigned int *)image->scanLine(y);
+ p = t[x];
+ q = t[x+1];
+ r = t[x+image->width()];
+ s = t[x+image->width()+1];
+ }
+ else{
+ unsigned int *t = (unsigned int *)image->scanLine(y);
+ p = background;
+ if((x >= 0) && (y >= 0)){
+ p = t[x];
+ }
+ q = background;
+ if(((x+1) < image->width()) && (y >= 0)){
+ q = t[x+1];
+ }
+ r = background;
+ if((x >= 0) && ((y+1) < image->height())){
+ t = (unsigned int *)image->scanLine(y+1);
+ r = t[x+image->width()];
+ }
+ s = background;
+ if(((x+1) < image->width()) && ((y+1) < image->height())){
+ t = (unsigned int *)image->scanLine(y+1);
+ s = t[x+image->width()+1];
+ }
+
+ }
+ }
+ else{
+ unsigned int *colorTable = (unsigned int *)image->colorTable();
+ if((x >= 0) && (y >= 0) && (x < (image->width()-1)) && (y < (image->height()-1))) {
+ unsigned char *t;
+ t = (unsigned char *)image->scanLine(y);
+ p = *(colorTable+t[x]);
+ q = *(colorTable+t[x+1]);
+ t = (unsigned char *)image->scanLine(y+1);
+ r = *(colorTable+t[x]);
+ s = *(colorTable+t[x+1]);
+ }
+ else{
+ unsigned char *t;
+ p = background;
+ if((x >= 0) && (y >= 0)){
+ t = (unsigned char *)image->scanLine(y);
+ p = *(colorTable+t[x]);
+ }
+ q = background;
+ if(((x+1) < image->width()) && (y >= 0)){
+ t = (unsigned char *)image->scanLine(y);
+ q = *(colorTable+t[x+1]);
+ }
+ r = background;
+ if((x >= 0) && ((y+1) < image->height())){
+ t = (unsigned char *)image->scanLine(y+1);
+ r = *(colorTable+t[x]);
+ }
+ s = background;
+ if(((x+1) < image->width()) && ((y+1) < image->height())){
+ t = (unsigned char *)image->scanLine(y+1);
+ s = *(colorTable+t[x+1]);
+ }
+
+ }
+
+ }
+ x_offset -= floor(x_offset);
+ y_offset -= floor(y_offset);
+ alpha = 1.0-x_offset;
+ beta = 1.0-y_offset;
+
+ return(qRgba((unsigned char)(beta*(alpha*qRed(p)+x_offset*qRed(q))+y_offset*(alpha*qRed(r)+x_offset*qRed(s))),
+ (unsigned char)(beta*(alpha*qGreen(p)+x_offset*qGreen(q))+y_offset*(alpha*qGreen(r)+x_offset*qGreen(s))),
+ (unsigned char)(beta*(alpha*qBlue(p)+x_offset*qBlue(q))+y_offset*(alpha*qBlue(r)+x_offset*qBlue(s))),
+ (unsigned char)(beta*(alpha*qAlpha(p)+x_offset*qAlpha(q))+y_offset*(alpha*qAlpha(r)+x_offset*qAlpha(s)))));
+}
+
+QImage OImageEffect::implode(QImage &src, double factor,
+ unsigned int background)
+{
+ double amount, distance, radius;
+ double x_center, x_distance, x_scale;
+ double y_center, y_distance, y_scale;
+ unsigned int *destData;
+ int x, y;
+
+ QImage dest(src.width(), src.height(), 32);
+
+ // compute scaling factor
+ x_scale = 1.0;
+ y_scale = 1.0;
+ x_center = (double)0.5*src.width();
+ y_center = (double)0.5*src.height();
+ radius=x_center;
+ if(src.width() > src.height())
+ y_scale = (double)src.width()/src.height();
+ else if(src.width() < src.height()){
+ x_scale = (double) src.height()/src.width();
+ radius = y_center;
+ }
+ amount=factor/10.0;
+ if(amount >= 0)
+ amount/=10.0;
+ if(src.depth() > 8){ // DirectClass source image
+ unsigned int *srcData;
+ for(y=0; y < src.height(); ++y){
+ srcData = (unsigned int *)src.scanLine(y);
+ destData = (unsigned int *)dest.scanLine(y);
+ y_distance=y_scale*(y-y_center);
+ for(x=0; x < src.width(); ++x){
+ destData[x] = srcData[x];
+ x_distance = x_scale*(x-x_center);
+ distance= x_distance*x_distance+y_distance*y_distance;
+ if(distance < (radius*radius)){
+ double factor;
+ // Implode the pixel.
+ factor=1.0;
+ if(distance > 0.0)
+ factor=
+ pow(sin(0.5000000000000001*M_PI*sqrt(distance)/radius),-amount);
+ destData[x] = interpolateColor(&src, factor*x_distance/x_scale+x_center,
+ factor*y_distance/y_scale+y_center,
+ background);
+ }
+ }
+ }
+ }
+ else{ // PsudeoClass source image
+ unsigned char *srcData;
+ unsigned char idx;
+ unsigned int *cTable = src.colorTable();
+ for(y=0; y < src.height(); ++y){
+ srcData = (unsigned char *)src.scanLine(y);
+ destData = (unsigned int *)dest.scanLine(y);
+ y_distance=y_scale*(y-y_center);
+ for(x=0; x < src.width(); ++x){
+ idx = srcData[x];
+ destData[x] = cTable[idx];
+ x_distance = x_scale*(x-x_center);
+ distance= x_distance*x_distance+y_distance*y_distance;
+ if(distance < (radius*radius)){
+ double factor;
+ // Implode the pixel.
+ factor=1.0;
+ if(distance > 0.0)
+ factor=
+ pow(sin(0.5000000000000001*M_PI*sqrt(distance)/radius),-amount);
+ destData[x] = interpolateColor(&src, factor*x_distance/x_scale+x_center,
+ factor*y_distance/y_scale+y_center,
+ background);
+ }
+ }
+ }
+
+ }
+ return(dest);
+}
+
+QImage OImageEffect::rotate(QImage &img, RotateDirection r)
+{
+ QImage dest;
+ int x, y;
+ if(img.depth() > 8){
+ unsigned int *srcData, *destData;
+ switch(r){
+ case Rotate90:
+ dest.create(img.height(), img.width(), img.depth());
+ for(y=0; y < img.height(); ++y){
+ srcData = (unsigned int *)img.scanLine(y);
+ for(x=0; x < img.width(); ++x){
+ destData = (unsigned int *)dest.scanLine(x);
+ destData[img.height()-y-1] = srcData[x];
+ }
+ }
+ break;
+ case Rotate180:
+ dest.create(img.width(), img.height(), img.depth());
+ for(y=0; y < img.height(); ++y){
+ srcData = (unsigned int *)img.scanLine(y);
+ destData = (unsigned int *)dest.scanLine(img.height()-y-1);
+ for(x=0; x < img.width(); ++x)
+ destData[img.width()-x-1] = srcData[x];
+ }
+ break;
+ case Rotate270:
+ dest.create(img.height(), img.width(), img.depth());
+ for(y=0; y < img.height(); ++y){
+ srcData = (unsigned int *)img.scanLine(y);
+ for(x=0; x < img.width(); ++x){
+ destData = (unsigned int *)dest.scanLine(img.width()-x-1);
+ destData[y] = srcData[x];
+ }
+ }
+ break;
+ default:
+ dest = img;
+ break;
+ }
+ }
+ else{
+ unsigned char *srcData, *destData;
+ unsigned int *srcTable, *destTable;
+ switch(r){
+ case Rotate90:
+ dest.create(img.height(), img.width(), img.depth());
+ dest.setNumColors(img.numColors());
+ srcTable = (unsigned int *)img.colorTable();
+ destTable = (unsigned int *)dest.colorTable();
+ for(x=0; x < img.numColors(); ++x)
+ destTable[x] = srcTable[x];
+ for(y=0; y < img.height(); ++y){
+ srcData = (unsigned char *)img.scanLine(y);
+ for(x=0; x < img.width(); ++x){
+ destData = (unsigned char *)dest.scanLine(x);
+ destData[img.height()-y-1] = srcData[x];
+ }
+ }
+ break;
+ case Rotate180:
+ dest.create(img.width(), img.height(), img.depth());
+ dest.setNumColors(img.numColors());
+ srcTable = (unsigned int *)img.colorTable();
+ destTable = (unsigned int *)dest.colorTable();
+ for(x=0; x < img.numColors(); ++x)
+ destTable[x] = srcTable[x];
+ for(y=0; y < img.height(); ++y){
+ srcData = (unsigned char *)img.scanLine(y);
+ destData = (unsigned char *)dest.scanLine(img.height()-y-1);
+ for(x=0; x < img.width(); ++x)
+ destData[img.width()-x-1] = srcData[x];
+ }
+ break;
+ case Rotate270:
+ dest.create(img.height(), img.width(), img.depth());
+ dest.setNumColors(img.numColors());
+ srcTable = (unsigned int *)img.colorTable();
+ destTable = (unsigned int *)dest.colorTable();
+ for(x=0; x < img.numColors(); ++x)
+ destTable[x] = srcTable[x];
+ for(y=0; y < img.height(); ++y){
+ srcData = (unsigned char *)img.scanLine(y);
+ for(x=0; x < img.width(); ++x){
+ destData = (unsigned char *)dest.scanLine(img.width()-x-1);
+ destData[y] = srcData[x];
+ }
+ }
+ break;
+ default:
+ dest = img;
+ break;
+ }
+
+ }
+ return(dest);
+}
+
+void OImageEffect::solarize(QImage &img, double factor)
+{
+ int i, count;
+ int threshold;
+ unsigned int *data;
+
+ threshold = (int)(factor*(MaxRGB+1)/100.0);
+ if(img.depth() < 32){
+ data = (unsigned int *)img.colorTable();
+ count = img.numColors();
+ }
+ else{
+ data = (unsigned int *)img.bits();
+ count = img.width()*img.height();
+ }
+ for(i=0; i < count; ++i){
+ data[i] = qRgba(qRed(data[i]) > threshold ? MaxRGB-qRed(data[i]) : qRed(data[i]),
+ qGreen(data[i]) > threshold ? MaxRGB-qGreen(data[i]) : qGreen(data[i]),
+ qBlue(data[i]) > threshold ? MaxRGB-qBlue(data[i]) : qBlue(data[i]),
+ qAlpha(data[i]));
+ }
+}
+
+QImage OImageEffect::spread(QImage &src, unsigned int amount)
+{
+ int quantum, x, y;
+ int x_distance, y_distance;
+ if(src.width() < 3 || src.height() < 3)
+ return(src);
+ QImage dest(src);
+ dest.detach();
+ quantum=(amount+1) >> 1;
+ if(src.depth() > 8){ // DirectClass source image
+ unsigned int *p, *q;
+ for(y=0; y < src.height(); y++){
+ q = (unsigned int *)dest.scanLine(y);
+ for(x=0; x < src.width(); x++){
+ x_distance = x + ((rand() & (amount+1))-quantum);
+ y_distance = y + ((rand() & (amount+1))-quantum);
+ x_distance = QMIN(x_distance, src.width()-1);
+ y_distance = QMIN(y_distance, src.height()-1);
+ if(x_distance < 0)
+ x_distance = 0;
+ if(y_distance < 0)
+ y_distance = 0;
+ p = (unsigned int *)src.scanLine(y_distance);
+ p += x_distance;
+ *q++=(*p);
+ }
+ }
+ }
+ else{ // PsudeoClass source image
+ // just do colortable values
+ unsigned char *p, *q;
+ for(y=0; y < src.height(); y++){
+ q = (unsigned char *)dest.scanLine(y);
+ for(x=0; x < src.width(); x++){
+ x_distance = x + ((rand() & (amount+1))-quantum);
+ y_distance = y + ((rand() & (amount+1))-quantum);
+ x_distance = QMIN(x_distance, src.width()-1);
+ y_distance = QMIN(y_distance, src.height()-1);
+ if(x_distance < 0)
+ x_distance = 0;
+ if(y_distance < 0)
+ y_distance = 0;
+ p = (unsigned char *)src.scanLine(y_distance);
+ p += x_distance;
+ *q++=(*p);
+ }
+ }
+ }
+ return(dest);
+}
+
+QImage OImageEffect::swirl(QImage &src, double degrees,
+ unsigned int background)
+{
+ double cosine, distance, factor, radius, sine, x_center, x_distance,
+ x_scale, y_center, y_distance, y_scale;
+ int x, y;
+ unsigned int *q;
+ QImage dest(src.width(), src.height(), 32);
+
+ // compute scaling factor
+ x_center = src.width()/2.0;
+ y_center = src.height()/2.0;
+ radius = QMAX(x_center,y_center);
+ x_scale=1.0;
+ y_scale=1.0;
+ if(src.width() > src.height())
+ y_scale=(double)src.width()/src.height();
+ else if(src.width() < src.height())
+ x_scale=(double)src.height()/src.width();
+ degrees=DegreesToRadians(degrees);
+ // swirl each row
+ if(src.depth() > 8){ // DirectClass source image
+ unsigned int *p;
+ for(y=0; y < src.height(); y++){
+ p = (unsigned int *)src.scanLine(y);
+ q = (unsigned int *)dest.scanLine(y);
+ y_distance = y_scale*(y-y_center);
+ for(x=0; x < src.width(); x++){
+ // determine if the pixel is within an ellipse
+ *q=(*p);
+ x_distance = x_scale*(x-x_center);
+ distance = x_distance*x_distance+y_distance*y_distance;
+ if (distance < (radius*radius)){
+ // swirl
+ factor = 1.0-sqrt(distance)/radius;
+ sine = sin(degrees*factor*factor);
+ cosine = cos(degrees*factor*factor);
+ *q = interpolateColor(&src,
+ (cosine*x_distance-sine*y_distance)/x_scale+x_center,
+ (sine*x_distance+cosine*y_distance)/y_scale+y_center,
+ background);
+ }
+ p++;
+ q++;
+ }
+ }
+ }
+ else{ // PsudeoClass source image
+ unsigned char *p;
+ unsigned int *cTable = (unsigned int *)src.colorTable();
+ for(y=0; y < src.height(); y++){
+ p = (unsigned char *)src.scanLine(y);
+ q = (unsigned int *)dest.scanLine(y);
+ y_distance = y_scale*(y-y_center);
+ for(x=0; x < src.width(); x++){
+ // determine if the pixel is within an ellipse
+ *q = *(cTable+(*p));
+ x_distance = x_scale*(x-x_center);
+ distance = x_distance*x_distance+y_distance*y_distance;
+ if (distance < (radius*radius)){
+ // swirl
+ factor = 1.0-sqrt(distance)/radius;
+ sine = sin(degrees*factor*factor);
+ cosine = cos(degrees*factor*factor);
+ *q = interpolateColor(&src,
+ (cosine*x_distance-sine*y_distance)/x_scale+x_center,
+ (sine*x_distance+cosine*y_distance)/y_scale+y_center,
+ background);
+ }
+ p++;
+ q++;
+ }
+ }
+
+ }
+ return(dest);
+}
+
+QImage OImageEffect::wave(QImage &src, double amplitude, double wavelength,
+ unsigned int background)
+{
+ double *sine_map;
+ int x, y;
+ unsigned int *q;
+
+ QImage dest(src.width(), src.height() + (int)(2*fabs(amplitude)), 32);
+ // allocate sine map
+ sine_map = (double *)malloc(dest.width()*sizeof(double));
+ if(!sine_map)
+ return(src);
+ for(x=0; x < dest.width(); ++x)
+ sine_map[x]=fabs(amplitude)+amplitude*sin((2*M_PI*x)/wavelength);
+ // wave image
+ for(y=0; y < dest.height(); ++y){
+ q = (unsigned int *)dest.scanLine(y);
+ for (x=0; x < dest.width(); x++){
+ *q=interpolateColor(&src, x, (int)(y-sine_map[x]), background);
+ ++q;
+ }
+ }
+ free(sine_map);
+ return(dest);
+}
+
+QImage OImageEffect::oilPaint(QImage &src, int radius)
+{
+ // TODO 8bpp src!
+ if(src.depth() < 32){
+ qWarning("Oil Paint source image < 32bpp. Convert before using!");
+ return(src);
+ }
+ int j, k, i, x, y;
+ unsigned int *histogram;
+ unsigned int *s;
+ unsigned int count;
+
+ unsigned int *srcData, *destData;
+
+ QImage dest(src);
+ dest.detach();
+ histogram = (unsigned int *) malloc((MaxRGB+1)*sizeof(unsigned int));
+ if(!histogram)
+ return(src);
+ // paint each row
+ k=0;
+ for(y = radius; y < src.height(); ++y){
+ srcData = (unsigned int *)src.scanLine(y-radius);
+ destData = (unsigned int *)dest.scanLine(y);
+ srcData += radius*src.width()+radius;
+ destData += radius;
+ for(x=radius; x < src.width()-radius; ++x){
+ // determine most frequent color
+ count = 0;
+ for(i=0; i < MaxRGB+1; ++i)
+ histogram[i] = 0;
+ for(i=0; i < radius; ++i){
+ s = srcData-(radius-1)*src.width()-i-1;
+ for(j =0; j < (2*i+1); ++j){
+ k = intensityValue(*s);
+ histogram[k]++;
+ if(histogram[k] > count){
+ *destData = *s;
+ count = histogram[k];
+ }
+ ++s;
+ }
+ s = srcData+(radius-i)*src.width()-i-1;
+ for(j =0; j < (2*i+1); ++j){
+ k = intensityValue(*s);
+ histogram[k]++;
+ if(histogram[k] > count){
+ *destData = *s;
+ count = histogram[k];
+ }
+ ++s;
+ }
+ }
+ s = srcData-radius;
+ for(j =0; j < (2*i+1); ++j){
+ k = intensityValue(*s);
+ histogram[k]++;
+ if(histogram[k] > count){
+ *destData = *s;
+ count = histogram[k];
+ }
+ ++s;
+ }
+ ++srcData;
+ ++destData;
+ }
+ }
+ free(histogram);
+ return(dest);
+}
+
+//
+// The following methods work by computing a value from neighboring pixels
+// (mosfet 12/28/01)
+//
+
+QImage OImageEffect::edge(QImage &src, double factor)
+{
+#define Edge(weight) \
+ total_red+=(weight)*qRed(*s); \
+ total_green+=(weight)*qGreen(*s); \
+ total_blue+=(weight)*qBlue(*s); \
+ total_opacity+=(weight)*qAlpha(*s); \
+ s++;
+
+#define Edge256(weight) \
+ total_red+=(weight)*qRed(*(cTable+(*s))); \
+ total_green+=(weight)*qGreen(*(cTable+(*s))); \
+ total_blue+=(weight)*qBlue(*(cTable+(*s))); \
+ total_opacity+=(weight)*qAlpha(*(cTable+(*s))); \
+ s++;
+
+ if(src.width() < 3 || src.height() < 3)
+ return(src);
+
+ double total_blue, total_green, total_opacity, total_red, weight;
+
+ int x, y;
+
+ unsigned int *q;
+
+ QImage dest(src.width(), src.height(), 32);
+ weight=factor/8.0;
+ if(src.depth() > 8){ // DirectClass source image
+ unsigned int *p, *s;
+ for(y=0; y < src.height(); ++y){
+ p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
+ q = (unsigned int *)dest.scanLine(y);
+ // edge detect this row of pixels.
+ *q++=(*(p+src.width()));
+ for(x=1; x < src.width()-1; ++x){
+ // compute weighted average of target pixel color components.
+ total_red=0.0;
+ total_green=0.0;
+ total_blue=0.0;
+ total_opacity=0.0;
+ s=p;
+ Edge(-weight/8); Edge(-weight/8) Edge(-weight/8);
+ s=p+src.width();
+ Edge(-weight/8); Edge(weight); Edge(-weight/8);
+ s=p+2*src.width();
+ Edge(-weight/8); Edge(-weight/8); Edge(-weight/8);
+ *q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
+ (unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
+ (unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
+ (unsigned char)((total_opacity < 0) ? 0 : (total_opacity > MaxRGB) ? MaxRGB : total_opacity));
+ p++;
+ q++;
+ }
+ p++;
+ *q++=(*p);
+ }
+ }
+ else{ // PsudeoClass source image
+ unsigned char *p, *p2, *p3, *s;
+ unsigned int *cTable = src.colorTable();
+ int scanLineIdx;
+ for(y=0; y < src.height(); ++y){
+ scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
+ p = (unsigned char *)src.scanLine(scanLineIdx);
+ p2 = (unsigned char *)src.scanLine(scanLineIdx+1);
+ p3 = (unsigned char *)src.scanLine(scanLineIdx+2);
+ q = (unsigned int *)dest.scanLine(y);
+ // edge detect this row of pixels.
+ *q++=(*(cTable+(*p2)));
+ for(x=1; x < src.width()-1; ++x){
+ // compute weighted average of target pixel color components.
+ total_red=0.0;
+ total_green=0.0;
+ total_blue=0.0;
+ total_opacity=0.0;
+ s=p;
+ Edge256(-weight/8); Edge256(-weight/8) Edge256(-weight/8);
+ s=p2;
+ Edge256(-weight/8); Edge256(weight); Edge256(-weight/8);
+ s=p3;
+ Edge256(-weight/8); Edge256(-weight/8); Edge256(-weight/8);
+ *q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
+ (unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
+ (unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
+ (unsigned char)((total_opacity < 0) ? 0 : (total_opacity > MaxRGB) ? MaxRGB : total_opacity));
+ p++;
+ p2++;
+ p3++;
+ q++;
+ }
+ p++;
+ *q++=(*(cTable+(*p)));
+ }
+ }
+ return(dest);
+}
+
+QImage OImageEffect::sharpen(QImage &src, double factor)
+{
+#define Sharpen(weight) \
+ total_red+=(weight)*qRed(*s); \
+ total_green+=(weight)*qGreen(*s); \
+ total_blue+=(weight)*qBlue(*s); \
+ total_opacity+=(weight)*qAlpha(*s); \
+ s++;
+
+#define Sharpen256(weight) \
+ total_red+=(weight)*qRed(*(cTable+(*s))); \
+ total_green+=(weight)*qGreen(*(cTable+(*s))); \
+ total_blue+=(weight)*qBlue(*(cTable+(*s))); \
+ total_opacity+=(weight)*qAlpha(*(cTable+(*s))); \
+ s++;
+
+ if(src.width() < 3 || src.height() < 3)
+ return(src);
+
+ double total_blue, total_green, total_opacity, total_red;
+ double quantum, weight;
+ unsigned char r, g, b, a;
+
+ int x, y;
+ unsigned int *q;
+
+ QImage dest(src.width(), src.height(), 32);
+ weight = ((100.0-factor)/2.0+13.0);
+ quantum = QMAX(weight-12.0, 1.0);
+ if(src.depth() > 8){ // DirectClass source image
+ unsigned int *p, *s;
+ for(y=0; y < src.height(); ++y){
+ p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
+ q = (unsigned int *)dest.scanLine(y);
+ // sharpen this row of pixels.
+ *q++=(*(p+src.width()));
+ for(x=1; x < src.width()-1; ++x){
+ // compute weighted average of target pixel color components.
+ total_red=0.0;
+ total_green=0.0;
+ total_blue=0.0;
+ total_opacity=0.0;
+ s=p;
+ Sharpen(-1); Sharpen(-2); Sharpen(-1);
+ s=p+src.width();
+ Sharpen(-2); Sharpen(weight); Sharpen(-2);
+ s=p+2*src.width();
+ Sharpen(-1); Sharpen(-2); Sharpen(-1);
+ if(total_red < 0)
+ r=0;
+ else if(total_red > (int)(MaxRGB*quantum))
+ r = (unsigned char)MaxRGB;
+ else
+ r = (unsigned char)((total_red+(quantum/2.0))/quantum);
+
+ if(total_green < 0)
+ g = 0;
+ else if(total_green > (int)(MaxRGB*quantum))
+ g = (unsigned char)MaxRGB;
+ else
+ g = (unsigned char)((total_green+(quantum/2.0))/quantum);
+
+ if(total_blue < 0)
+ b = 0;
+ else if(total_blue > (int)(MaxRGB*quantum))
+ b = (unsigned char)MaxRGB;
+ else
+ b = (unsigned char)((total_blue+(quantum/2.0))/quantum);
+
+ if(total_opacity < 0)
+ a = 0;
+ else if(total_opacity > (int)(MaxRGB*quantum))
+ a = (unsigned char)MaxRGB;
+ else
+ a= (unsigned char)((total_opacity+(quantum/2.0))/quantum);
+
+ *q = qRgba(r, g, b, a);
+
+ p++;
+ q++;
+ }
+ p++;
+ *q++=(*p);
+ }
+ }
+ else{ // PsudeoClass source image
+ unsigned char *p, *p2, *p3, *s;
+ unsigned int *cTable = src.colorTable();
+ int scanLineIdx;
+ for(y=0; y < src.height(); ++y){
+ scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
+ p = (unsigned char *)src.scanLine(scanLineIdx);
+ p2 = (unsigned char *)src.scanLine(scanLineIdx+1);
+ p3 = (unsigned char *)src.scanLine(scanLineIdx+2);
+ q = (unsigned int *)dest.scanLine(y);
+ // sharpen this row of pixels.
+ *q++=(*(cTable+(*p2)));
+ for(x=1; x < src.width()-1; ++x){
+ // compute weighted average of target pixel color components.
+ total_red=0.0;
+ total_green=0.0;
+ total_blue=0.0;
+ total_opacity=0.0;
+ s=p;
+ Sharpen256(-1); Sharpen256(-2); Sharpen256(-1);
+ s=p2;
+ Sharpen256(-2); Sharpen256(weight); Sharpen256(-2);
+ s=p3;
+ Sharpen256(-1); Sharpen256(-2); Sharpen256(-1);
+ if(total_red < 0)
+ r=0;
+ else if(total_red > (int)(MaxRGB*quantum))
+ r = (unsigned char)MaxRGB;
+ else
+ r = (unsigned char)((total_red+(quantum/2.0))/quantum);
+
+ if(total_green < 0)
+ g = 0;
+ else if(total_green > (int)(MaxRGB*quantum))
+ g = (unsigned char)MaxRGB;
+ else
+ g = (unsigned char)((total_green+(quantum/2.0))/quantum);
+
+ if(total_blue < 0)
+ b = 0;
+ else if(total_blue > (int)(MaxRGB*quantum))
+ b = (unsigned char)MaxRGB;
+ else
+ b = (unsigned char)((total_blue+(quantum/2.0))/quantum);
+
+ if(total_opacity < 0)
+ a = 0;
+ else if(total_opacity > (int)(MaxRGB*quantum))
+ a = (unsigned char)MaxRGB;
+ else
+ a = (unsigned char)((total_opacity+(quantum/2.0))/quantum);
+
+ *q = qRgba(r, g, b, a);
+
+ p++;
+ p2++;
+ p3++;
+ q++;
+ }
+ p++;
+ *q++=(*(cTable+(*p)));
+ }
+ }
+ return(dest);
+}
+
+QImage OImageEffect::emboss(QImage &src)
+{
+#define Emboss(weight) \
+ total_red+=(weight)*qRed(*s); \
+ total_green+=(weight)*qGreen(*s); \
+ total_blue+=(weight)*qBlue(*s); \
+ s++;
+
+#define Emboss256(weight) \
+ total_red+=(weight)*qRed(*(cTable+(*s))); \
+ total_green+=(weight)*qGreen(*(cTable+(*s))); \
+ total_blue+=(weight)*qBlue(*(cTable+(*s))); \
+ s++;
+
+ if(src.width() < 3 || src.height() < 3)
+ return(src);
+
+ double total_blue, total_green, total_red;
+ int x, y;
+ unsigned int *q;
+
+ QImage dest(src.width(), src.height(), 32);
+ if(src.depth() > 8){ // DirectClass source image
+ unsigned int *p, *s;
+ for(y=0; y < src.height(); ++y){
+ p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
+ q = (unsigned int *)dest.scanLine(y);
+ // emboss this row of pixels.
+ *q++=(*(p+src.width()));
+ for(x=1; x < src.width()-1; ++x){
+ // compute weighted average of target pixel color components.
+ total_red=0.0;
+ total_green=0.0;
+ total_blue=0.0;
+ s=p;
+ Emboss(-1); Emboss(-2); Emboss( 0);
+ s=p+src.width();
+ Emboss(-2); Emboss( 0); Emboss( 2);
+ s=p+2*src.width();
+ Emboss( 0); Emboss( 2); Emboss( 1);
+ total_red += (MaxRGB+1)/2;
+ total_green += (MaxRGB+1)/2;
+ total_blue += (MaxRGB+1)/2;
+ *q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
+ (unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
+ (unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
+ 255);
+ p++;
+ q++;
+ }
+ p++;
+ *q++=(*p);
+ }
+ }
+ else{ // PsudeoClass source image
+ unsigned char *p, *p2, *p3, *s;
+ unsigned int *cTable = src.colorTable();
+ int scanLineIdx;
+ for(y=0; y < src.height(); ++y){
+ scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
+ p = (unsigned char *)src.scanLine(scanLineIdx);
+ p2 = (unsigned char *)src.scanLine(scanLineIdx+1);
+ p3 = (unsigned char *)src.scanLine(scanLineIdx+2);
+ q = (unsigned int *)dest.scanLine(y);
+ // emboss this row of pixels.
+ *q++=(*(cTable+(*p2)));
+ for(x=1; x < src.width()-1; ++x){
+ // compute weighted average of target pixel color components.
+ total_red=0.0;
+ total_green=0.0;
+ total_blue=0.0;
+ s=p;
+ Emboss256(-1); Emboss256(-2); Emboss256(0);
+ s=p2;
+ Emboss256(-2); Emboss256(0); Emboss256(2);
+ s=p3;
+ Emboss256(0); Emboss256(2); Emboss256(1);
+ total_red += (MaxRGB+1)/2;
+ total_green += (MaxRGB+1)/2;
+ total_blue += (MaxRGB+1)/2;
+ *q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
+ (unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
+ (unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
+ 255);
+ p++;
+ p2++;
+ p3++;
+ q++;
+ }
+ p++;
+ *q++=(*(cTable+(*p)));
+ }
+ }
+ toGray(dest);
+ normalize(dest);
+ return(dest);
+}
+
+QImage OImageEffect::shade(QImage &src, bool color_shading, double azimuth,
+ double elevation)
+{
+ struct PointInfo{
+ double x, y, z;
+ };
+
+ double distance, normal_distance, shade;
+ int x, y;
+
+ struct PointInfo light, normal;
+
+ unsigned int *q;
+
+ QImage dest(src.width(), src.height(), 32);
+
+ azimuth = DegreesToRadians(azimuth);
+ elevation = DegreesToRadians(elevation);
+ light.x = MaxRGB*cos(azimuth)*cos(elevation);
+ light.y = MaxRGB*sin(azimuth)*cos(elevation);
+ light.z = MaxRGB*sin(elevation);
+ normal.z= 2*MaxRGB; // constant Z of surface normal
+
+ if(src.depth() > 8){ // DirectClass source image
+ unsigned int *p, *s0, *s1, *s2;
+ for(y=0; y < src.height(); ++y){
+ p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
+ q = (unsigned int *)dest.scanLine(y);
+ // shade this row of pixels.
+ *q++=(*(p+src.width()));
+ p++;
+ s0 = p;
+ s1 = p + src.width();
+ s2 = p + 2*src.width();
+ for(x=1; x < src.width()-1; ++x){
+ // determine the surface normal and compute shading.
+ normal.x=intensityValue(*(s0-1))+intensityValue(*(s1-1))+intensityValue(*(s2-1))-
+ (double) intensityValue(*(s0+1))-(double) intensityValue(*(s1+1))-
+ (double) intensityValue(*(s2+1));
+ normal.y=intensityValue(*(s2-1))+intensityValue(*s2)+intensityValue(*(s2+1))-
+ (double) intensityValue(*(s0-1))-(double) intensityValue(*s0)-
+ (double) intensityValue(*(s0+1));
+ if((normal.x == 0) && (normal.y == 0))
+ shade=light.z;
+ else{
+ shade=0.0;
+ distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
+ if (distance > 0.0){
+ normal_distance=
+ normal.x*normal.x+normal.y*normal.y+normal.z*normal.z;
+ if(fabs(normal_distance) > 0.0000001)
+ shade=distance/sqrt(normal_distance);
+ }
+ }
+ if(!color_shading){
+ *q = qRgba((unsigned char)(shade),
+ (unsigned char)(shade),
+ (unsigned char)(shade),
+ qAlpha(*s1));
+ }
+ else{
+ *q = qRgba((unsigned char)((shade*qRed(*s1))/(MaxRGB+1)),
+ (unsigned char)((shade*qGreen(*s1))/(MaxRGB+1)),
+ (unsigned char)((shade*qBlue(*s1))/(MaxRGB+1)),
+ qAlpha(*s1));
+ }
+ ++s0;
+ ++s1;
+ ++s2;
+ q++;
+ }
+ *q++=(*s1);
+ }
+ }
+ else{ // PsudeoClass source image
+ unsigned char *p, *s0, *s1, *s2;
+ int scanLineIdx;
+ unsigned int *cTable = (unsigned int *)src.colorTable();
+ for(y=0; y < src.height(); ++y){
+ scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
+ p = (unsigned char *)src.scanLine(scanLineIdx);
+ q = (unsigned int *)dest.scanLine(y);
+ // shade this row of pixels.
+ s0 = p;
+ s1 = (unsigned char *) src.scanLine(scanLineIdx+1);
+ s2 = (unsigned char *) src.scanLine(scanLineIdx+2);
+ *q++=(*(cTable+(*s1)));
+ ++p;
+ ++s0;
+ ++s1;
+ ++s2;
+ for(x=1; x < src.width()-1; ++x){
+ // determine the surface normal and compute shading.
+ normal.x=intensityValue(*(cTable+(*(s0-1))))+intensityValue(*(cTable+(*(s1-1))))+intensityValue(*(cTable+(*(s2-1))))-
+ (double) intensityValue(*(cTable+(*(s0+1))))-(double) intensityValue(*(cTable+(*(s1+1))))-
+ (double) intensityValue(*(cTable+(*(s2+1))));
+ normal.y=intensityValue(*(cTable+(*(s2-1))))+intensityValue(*(cTable+(*s2)))+intensityValue(*(cTable+(*(s2+1))))-
+ (double) intensityValue(*(cTable+(*(s0-1))))-(double) intensityValue(*(cTable+(*s0)))-
+ (double) intensityValue(*(cTable+(*(s0+1))));
+ if((normal.x == 0) && (normal.y == 0))
+ shade=light.z;
+ else{
+ shade=0.0;
+ distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
+ if (distance > 0.0){
+ normal_distance=
+ normal.x*normal.x+normal.y*normal.y+normal.z*normal.z;
+ if(fabs(normal_distance) > 0.0000001)
+ shade=distance/sqrt(normal_distance);
+ }
+ }
+ if(!color_shading){
+ *q = qRgba((unsigned char)(shade),
+ (unsigned char)(shade),
+ (unsigned char)(shade),
+ qAlpha(*(cTable+(*s1))));
+ }
+ else{
+ *q = qRgba((unsigned char)((shade*qRed(*(cTable+(*s1))))/(MaxRGB+1)),
+ (unsigned char)((shade*qGreen(*(cTable+(*s1))))/(MaxRGB+1)),
+ (unsigned char)((shade*qBlue(*(cTable+(*s1))))/(MaxRGB+1)),
+ qAlpha(*s1));
+ }
+ ++s0;
+ ++s1;
+ ++s2;
+ q++;
+ }
+ *q++=(*(cTable+(*s1)));
+ }
+ }
+ return(dest);
+}
+
+QImage OImageEffect::blur(QImage &src, double factor)
+{
+
+#define Blur(weight) \
+ total_red+=(weight)*qRed(*s); \
+ total_green+=(weight)*qGreen(*s); \
+ total_blue+=(weight)*qBlue(*s); \
+ total_opacity+=(weight)*qAlpha(*s); \
+ s++;
+
+#define Blur256(weight) \
+ total_red+=(weight)*qRed(*(cTable+(*s))); \
+ total_green+=(weight)*qGreen(*(cTable+(*s))); \
+ total_blue+=(weight)*qBlue(*(cTable+(*s))); \
+ total_opacity+=(weight)*qAlpha(*(cTable+(*s))); \
+ s++;
+
+ if(src.width() < 3 || src.height() < 3)
+ return(src);
+
+ double quantum, total_blue, total_green, total_opacity, total_red, weight;
+
+ int x, y;
+ unsigned int *q;
+
+ QImage dest(src.width(), src.height(), 32);
+ weight=((100.0-factor)/2)+1;
+ quantum = QMAX(weight+12.0, 1.0);
+ if(src.depth() > 8){ // DirectClass source image
+ unsigned int *p, *s;
+ for(y=0; y < src.height(); ++y){
+ p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
+ q = (unsigned int *)dest.scanLine(y);
+ // blur this row of pixels.
+ *q++=(*(p+src.width()));
+ for(x=1; x < src.width()-1; ++x){
+ // compute weighted average of target pixel color components.
+ total_red=0.0;
+ total_green=0.0;
+ total_blue=0.0;
+ total_opacity=0.0;
+ s=p;
+ Blur(1); Blur(2); Blur(1);
+ s=p+src.width();
+ Blur(2); Blur(weight); Blur(2);
+ s=p+2*src.width();
+ Blur(1); Blur(2); Blur(1);
+ *q = qRgba((unsigned char)((total_red+(quantum/2))/quantum),
+ (unsigned char)((total_green+(quantum/2))/quantum),
+ (unsigned char)((total_blue+(quantum/2))/quantum),
+ (unsigned char)((total_opacity+(quantum/2))/quantum));
+ p++;
+ q++;
+ }
+ p++;
+ *q++=(*p);
+ }
+ }
+ else{ // PsudeoClass source image
+ unsigned char *p, *p2, *p3, *s;
+ unsigned int *cTable = src.colorTable();
+ int scanLineIdx;
+ for(y=0; y < src.height(); ++y){
+ scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
+ p = (unsigned char *)src.scanLine(scanLineIdx);
+ p2 = (unsigned char *)src.scanLine(scanLineIdx+1);
+ p3 = (unsigned char *)src.scanLine(scanLineIdx+2);
+ q = (unsigned int *)dest.scanLine(y);
+ // blur this row of pixels.
+ *q++=(*(cTable+(*p2)));
+ for(x=1; x < src.width()-1; ++x){
+ // compute weighted average of target pixel color components.
+ total_red=0.0;
+ total_green=0.0;
+ total_blue=0.0;
+ total_opacity=0.0;
+ s=p;
+ Blur256(1); Blur256(2); Blur256(1);
+ s=p2;
+ Blur256(2); Blur256(weight); Blur256(2);
+ s=p3;
+ Blur256(1); Blur256(2); Blur256(1);
+ *q = qRgba((unsigned char)((total_red+(quantum/2))/quantum),
+ (unsigned char)((total_green+(quantum/2))/quantum),
+ (unsigned char)((total_blue+(quantum/2))/quantum),
+ (unsigned char)((total_opacity+(quantum/2))/quantum));
+ p++;
+ p2++;
+ p3++;
+ q++;
+ }
+ p++;
+ *q++=(*(cTable+(*p)));
+ }
+ }
+ return(dest);
+}
+
+// High quality, expensive HSV contrast. You can do a faster one by just
+// taking a grayscale threshold (ie: 128) and incrementing RGB color
+// channels above it and decrementing those below it, but this gives much
+// better results. (mosfet 12/28/01)
+void OImageEffect::contrastHSV(QImage &img, bool sharpen)
+{
+ int i, sign;
+ unsigned int *data;
+ int count;
+ double brightness, scale, theta;
+ QColor c;
+ int h, s, v;
+
+ sign = sharpen ? 1 : -1;
+ scale=0.5000000000000001;
+ if(img.depth() > 8){
+ count = img.width()*img.height();
+ data = (unsigned int *)img.bits();
+ }
+ else{
+ count = img.numColors();
+ data = (unsigned int *)img.colorTable();
+ }
+ for(i=0; i < count; ++i){
+ c.setRgb(data[i]);
+ c.hsv(&h, &s, &v);
+ brightness = v/255.0;
+ theta=(brightness-0.5)*M_PI;
+ brightness+=scale*(((scale*((sin(theta)+1.0)))-brightness)*sign);
+ if (brightness > 1.0)
+ brightness=1.0;
+ else
+ if (brightness < 0)
+ brightness=0.0;
+ v = (int)(brightness*255);
+ c.setHsv(h, s, v);
+ data[i] = qRgba(c.red(), c.green(), c.blue(), qAlpha(data[i]));
+ }
+}
+
+
+
+
diff --git a/libopie2/opieui/oimageeffect.h b/libopie2/opieui/oimageeffect.h
new file mode 100644
index 0000000..313ea50
--- a/dev/null
+++ b/libopie2/opieui/oimageeffect.h
@@ -0,0 +1,558 @@
+//FIXME: Revise for Opie - do we really need such fancy stuff on PDA's?
+//FIXME: Maybe not on SL5xxx, but surely on C700 :))
+
+/* This file is part of the KDE libraries
+ Copyright (C) 1998, 1999, 2001, 2002 Daniel M. Duley <mosfet@interaccess.com>
+ (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
+ (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+// $Id$
+
+#ifndef OIMAGEEFFECT_H
+#define OIMAGEEFFECT_H
+
+class QImage;
+class QSize;
+class QColor;
+
+/**
+ * This class includes various @ref QImage based graphical effects.
+ *
+ * Everything is
+ * static, so there is no need to create an instance of this class. You can
+ * just call the static methods. They are encapsulated here merely to provide
+ * a common namespace.
+ */
+
+class OImageEffect
+{
+public:
+ enum GradientType { VerticalGradient, HorizontalGradient,
+ DiagonalGradient, CrossDiagonalGradient,
+ PyramidGradient, RectangleGradient,
+ PipeCrossGradient, EllipticGradient };
+ enum RGBComponent { Red, Green, Blue, Gray, All };
+
+ enum Lighting {NorthLite, NWLite, WestLite, SWLite,
+ SouthLite, SELite, EastLite, NELite};
+
+ enum ModulationType { Intensity, Saturation, HueShift, Contrast };
+
+ enum NoiseType { UniformNoise=0, GaussianNoise, MultiplicativeGaussianNoise,
+ ImpulseNoise, LaplacianNoise, PoissonNoise};
+
+ enum RotateDirection{ Rotate90, Rotate180, Rotate270 };
+
+ /**
+ * Create a gradient from color a to color b of the specified type.
+ *
+ * @param size The desired size of the gradient.
+ * @param ca Color a
+ * @param cb Color b
+ * @param type The type of gradient.
+ * @param ncols The number of colors to use when not running on a
+ * truecolor display. The gradient will be dithered to this number of
+ * colors. Pass 0 to prevent dithering.
+ */
+ static QImage gradient(const QSize &size, const QColor &ca,
+ const QColor &cb, GradientType type, int ncols=3);
+
+ /**
+ * Create an unbalanced gradient.
+
+ * An unbalanced gradient is a gradient where the transition from
+ * color a to color b is not linear, but in this case, exponential.
+ *
+ * @param size The desired size of the gradient.
+ * @param ca Color a
+ * @param cb Color b
+ * @param type The type of gradient.
+ * @param xfactor The x decay length. Use a value between -200 and 200.
+ * @param yfactor The y decay length.
+ * @param ncols The number of colors. See OPixmapEffect:gradient.
+ */
+ static QImage unbalancedGradient(const QSize &size, const QColor &ca,
+ const QColor &cb, GradientType type, int xfactor = 100,
+ int yfactor = 100, int ncols = 3);
+
+ /**
+ * Blends a color into the destination image, using an opacity
+ * value for blending one into another. Very fast direct pixel
+ * manipulation is used.
+ *
+ * @author Karol Szwed (gallium@kde.org)
+ * @param clr source color to be blended into the destination image.
+ * @param dst destination image in which the source will be blended into.
+ * @param opacity opacity (in percent) which determines how much the source
+ * color will be blended into the destination image.
+ * @return The destination image (dst) containing the result.
+ */
+ static QImage& blend(const QColor& clr, QImage& dst, float opacity);
+
+ /**
+ * Blend the src image into the destination image, using an opacity
+ * value for blending one into another. Very fast direct pixel
+ * manipulation is used.
+ *
+ * @author Karol Szwed (gallium@kde.org)
+ * @param src source image to be blended into the destination image.
+ * @param dst destination image in which the source will be blended into.
+ * @param opacity opacity (in percent) which determines how much the source
+ * image will be blended into the destination image.
+ * @return The destination image (dst) containing the result.
+ */
+ static QImage& blend(QImage& src, QImage& dst, float opacity);
+
+ /**
+ * Blend the provided image into a background of the indicated color.
+ *
+ * @param initial_intensity this parameter takes values from -1 to 1:
+ * a) if positive: how much to fade the image in its
+ * less affected spot
+ * b) if negative: roughly indicates how much of the image
+ * remains unaffected
+ * @param bgnd indicates the color of the background to blend in
+ * @param eff lets you choose what kind of blending you like
+ * @param anti_dir blend in the opposite direction (makes no much sense
+ * with concentric blending effects)
+ * @param image must be 32bpp
+ */
+ static QImage& blend(QImage &image, float initial_intensity,
+ const QColor &bgnd, GradientType eff,
+ bool anti_dir=false);
+
+ /**
+ * Blend an image into another one, using a gradient type
+ * for blending from one to another.
+ *
+ * @param image1 source1 and result of blending
+ * @param image2 source2 of blending
+ * @param gt gradient type for blending between source1 and source2
+ * @param xf x decay length for unbalanced gradient tpye
+ * @param yf y decay length for unbalanced gradient tpye
+ */
+ static QImage& blend(QImage &image1,QImage &image2,
+ GradientType gt, int xf=100, int yf=100);
+
+ /**
+ * Blend an image into another one, using a color channel of a
+ * third image for the decision of blending from one to another.
+ *
+ * @param image1 Source 1 and result of blending
+ * @param image2 Source 2 of blending
+ * @param blendImage If the gray value of of pixel is 0, the result
+ * for this pixel is that of image1; for a gray value
+ * of 1, the pixel of image2 is used; for a value
+ * inbetween, a corresponding blending is used.
+ * @param channel The RBG channel to use for the blending decision.
+ */
+ static QImage& blend(QImage &image1, QImage &image2,
+ QImage &blendImage, RGBComponent channel);
+
+ /**
+ * Blend an image into another one, using alpha in the expected way.
+ * @author Rik Hemsley (rikkus) <rik@kde.org>
+ */
+ static bool blend(const QImage & upper, const QImage & lower, QImage & output);
+// Not yet... static bool blend(const QImage & image1, const QImage & image2, QImage & output, const QRect & destRect);
+
+ /**
+ * Blend an image into another one, using alpha in the expected way and
+ * over coordinates @p x and @p y with respect to the lower image.
+ * The output is a QImage which is the @p upper image already blended
+ * with the @p lower one, so its size will be (in general) the same than
+ * @p upper instead of the same size than @p lower like the method above.
+ * In fact, the size of @p output is like upper's one only when it can be
+ * painted on lower, if there has to be some clipping, output's size will
+ * be the clipped area and x and y will be set to the correct up-left corner
+ * where the clipped rectangle begins.
+ */
+ static bool blend(int &x, int &y, const QImage & upper, const QImage & lower, QImage & output);
+ /**
+ * Blend an image into another one, using alpha in the expected way and
+ * over coordinates @p x and @p y with respect to the lower image.
+ * The output is painted in the own @p lower image. This is an optimization
+ * of the blend method above provided by convenience.
+ */
+ static bool blendOnLower(int x, int y, const QImage & upper, const QImage & lower);
+
+ /**
+ * Modifies the intensity of a pixmap's RGB channel component.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param image The QImage to process.
+ * @param percent Percent value. Use a negative value to dim.
+ * @param channel Which channel(s) should be modified
+ * @return The @p image, provided for convenience.
+ */
+ static QImage& channelIntensity(QImage &image, float percent,
+ RGBComponent channel);
+
+ /**
+ * Fade an image to a certain background color.
+ *
+ * The number of colors will not be changed.
+ *
+ * @param image The QImage to process.
+ * @param val The strength of the effect. 0 <= val <= 1.
+ * @param color The background color.
+ * @return Returns the @ref image(), provided for convenience.
+ */
+ static QImage& fade(QImage &img, float val, const QColor &color);
+
+
+ /**
+ * This recolors a pixmap. The most dark color will become color a,
+ * the most bright one color b, and in between.
+ *
+ * @param image A QImage to process.
+ * @param ca Color a
+ * @param cb Color b
+ */
+ static QImage& flatten(QImage &image, const QColor &ca,
+ const QColor &cb, int ncols=0);
+
+ /**
+ * Build a hash on any given @ref QImage
+ *
+ * @param image The QImage to process
+ * @param lite The hash faces the indicated lighting (cardinal poles).
+ * @param spacing How many unmodified pixels inbetween hashes.
+ * @return Returns the @ref image(), provided for convenience.
+ */
+ static QImage& hash(QImage &image, Lighting lite=NorthLite,
+ unsigned int spacing=0);
+
+ /**
+ * Either brighten or dim the image by a specified percent.
+ * For example, .50 will modify the colors by 50%.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param image The QImage to process.
+ * @param percent The percent value. Use a negative value to dim.
+ * @return Returns The @ref image(), provided for convenience.
+ */
+ static QImage& intensity(QImage &image, float percent);
+
+ /**
+ * Modulate the image with a color channel of another image.
+ *
+ * @param image The QImage to modulate and result.
+ * @param modImage The QImage to use for modulation.
+ * @param reverse Invert the meaning of image/modImage; result is image!
+ * @param type The modulation Type to use.
+ * @param factor The modulation amplitude; with 0 no effect [-200;200].
+ * @param channel The RBG channel of image2 to use for modulation.
+ * @return Returns the @ref image(), provided for convenience.
+ */
+ static QImage& modulate(QImage &image, QImage &modImage, bool reverse,
+ ModulationType type, int factor, RGBComponent channel);
+
+ /**
+ * Convert an image to grayscale.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param image The @ref QImage to process.
+ * @param fast Set to @p true in order to use a faster but non-photographic
+ * quality algorithm. Appropriate for things such as toolbar icons.
+ * @return Returns the @ref image(), provided for convenience.
+ */
+ static QImage& toGray(QImage &image, bool fast = false);
+
+ /**
+ * Desaturate an image evenly.
+ *
+ * @param image The QImage to process.
+ * @param desat A value between 0 and 1 setting the degree of desaturation
+ * @return Returns the @ref image(), provided for convenience.
+ */
+ static QImage& desaturate(QImage &image, float desat = 0.3);
+
+ /**
+ * Fast, but low quality contrast of an image. Also see contrastHSV.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param image The QImage to process.
+ * @param c A contrast value between -255 to 255.
+ * @return The @ref image(), provided for convenience.
+ */
+ static QImage& contrast(QImage &image, int c);
+
+ /**
+ * Dither an image using Floyd-Steinberg dithering for low-color
+ * situations.
+ *
+ * @param image The QImage to process.
+ * @param palette The color palette to use
+ * @param size The size of the palette
+ * @return Returns the @ref image(), provided for convenience.
+ */
+ static QImage& dither(QImage &img, const QColor *palette, int size);
+
+ /**
+ * Calculate the image for a selected image, for instance a selected icon
+ * on the desktop.
+ * @param img the QImage to select
+ * @param col the selected color, usually from QColorGroup::highlight().
+ */
+ static QImage& selectedImage( QImage &img, const QColor &col );
+
+ /**
+ * High quality, expensive HSV contrast. You can do a faster one by just
+ * taking a intensity threshold (ie: 128) and incrementing RGB color
+ * channels above it and decrementing those below it, but this gives much
+ * better results.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param img The QImage to process.
+ * @param sharpen If true sharpness is increase, (spiffed). Otherwise
+ * it is decreased, (dulled).
+ */
+ static void contrastHSV(QImage &img, bool sharpen=true);
+
+ /**
+ * Normalizes the pixel values to span the full range of color values.
+ * This is a contrast enhancement technique.
+ * @author Daniel M. Duley (mosfet)
+ */
+ static void normalize(QImage &img);
+
+ /**
+ * Performs histogram equalization on the reference
+ * image.
+ * @author Daniel M. Duley (mosfet)
+ */
+ static void equalize(QImage &img);
+
+ /**
+ * Thresholds the reference image. You can also threshold images by using
+ * ThresholdDither in the various QPixmap/QImage convert methods, but this
+ * lets you specify a threshold value.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param img The QImage to process.
+ * @param value The threshold value.
+ */
+ static void threshold(QImage &img, unsigned int value=128);
+
+ /**
+ * Produces a 'solarization' effect seen when exposing a photographic
+ * film to light during the development process.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param img The QImage to process.
+ * @param factor The extent of the solarization (0-99.9)
+ */
+ static void solarize(QImage &img, double factor=50.0);
+
+ /**
+ * Embosses the source image. This involves highlighting the edges
+ * and applying various other enhancements in order to get a metal
+ * effect.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @return The embossed image. The original is not changed.
+ */
+ static QImage emboss(QImage &src);
+
+ /**
+ * Minimizes speckle noise in the source image using the 8 hull
+ * algorithm.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @return The despeckled image. The original is not changed.
+ */
+ static QImage despeckle(QImage &src);
+
+ /**
+ * Produces a neat little "charcoal" effect.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param factor The factor for detecting lines (0-99.0).
+ * @return The charcoal image. The original is not changed.
+ */
+ static QImage charcoal(QImage &src, double factor=50.0);
+
+ /**
+ * Rotates the image by the specified amount
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param r The rotate direction.
+ * @return The rotated image. The original is not changed.
+ */
+ static QImage rotate(QImage &src, RotateDirection r);
+
+ /**
+ * Scales an image using simple pixel sampling. This does not produce
+ * nearly as nice a result as QImage::smoothScale(), but has the
+ * advantage of being much faster - only a few milliseconds.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param w The new width.
+ * @param h The new height.
+ * @return The scaled image. The original is not changed.
+ */
+ static QImage sample(QImage &src, int w, int h);
+
+ /**
+ * Adds noise to an image.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param type The algorithm used to generate the noise.
+ * @return The image with noise added. The original is not changed.
+ */
+ static QImage addNoise(QImage &src, NoiseType type = GaussianNoise);
+
+ /**
+ * Blurs an image by convolving pixel neighborhoods.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param factor The percent weight to give to the center pixel.
+ * @return The blurred image. The original is not changed.
+ */
+ static QImage blur(QImage &src, double factor=50.0);
+
+ /**
+ * Detects edges in an image using pixel neighborhoods and an edge
+ * detection mask.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param factor The percent weight to give to the center pixel.
+ * @return The image with edges detected. The original is not changed.
+ */
+ static QImage edge(QImage &src, double factor=50.0);
+
+ /**
+ * Implodes an image by a specified percent.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param factor The extent of the implosion.
+ * @param background An RGBA value to use for the background. After the
+ * effect some pixels may be "empty". This value is used for those pixels.
+ * @return The imploded image. The original is not changed.
+ */
+ static QImage implode(QImage &src, double factor=30.0,
+ unsigned int background = 0xFFFFFFFF);
+ /**
+ * Produces an oil painting effect.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param radius The radius of the pixel neighborhood used in applying the
+ * effect.
+ * @return The new image. The original is not changed.
+ */
+ static QImage oilPaint(QImage &src, int radius=3);
+
+ /**
+ * Sharpens the pixels in the image using pixel neighborhoods.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param factor The percent weight to give to the center pixel.
+ * @return The sharpened image. The original is not changed.
+ */
+ static QImage sharpen(QImage &src, double factor=30.0);
+
+ /**
+ * Randomly displaces pixels.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param amount The vicinity for choosing a random pixel to swap.
+ * @return The image with pixels displaced. The original is not changed.
+ */
+ static QImage spread(QImage &src, unsigned int amount=3);
+
+ /**
+ * Shades the image using a distance light source.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param color_shading If true do color shading, otherwise do grayscale.
+ * @param azimuth Determines the light source and direction.
+ * @param elevation Determines the light source and direction.
+ * @return The shaded image. The original is not changed.
+ */
+ static QImage shade(QImage &src, bool color_shading=true, double azimuth=30.0,
+ double elevation=30.0);
+ /**
+ * Swirls the image by a specified amount
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param degrees The tightness of the swirl.
+ * @param background An RGBA value to use for the background. After the
+ * effect some pixels may be "empty". This value is used for those pixels.
+ * @return The swirled image. The original is not changed.
+ */
+ static QImage swirl(QImage &src, double degrees=50.0, unsigned int background =
+ 0xFFFFFFFF);
+
+ /**
+ * Modifies the pixels along a sine wave.
+ *
+ * @author Daniel M. Duley (mosfet)
+ * @param src The QImage to process.
+ * @param amplitude The amplitude of the sine wave.
+ * @param wavelength The frequency of the sine wave.
+ * @return The new image. The original is not changed.
+ */
+ static QImage wave(QImage &src, double amplitude=25.0, double frequency=150.0,
+ unsigned int background = 0xFFFFFFFF);
+
+private:
+
+ /**
+ * Helper function to fast calc some altered (lighten, shaded) colors
+ *
+ */
+ static unsigned int lHash(unsigned int c);
+ static unsigned int uHash(unsigned int c);
+
+ /**
+ * Helper function to find the nearest color to the RBG triplet
+ */
+ static int nearestColor( int r, int g, int b, const QColor *pal, int size );
+
+ static void hull(const int x_offset, const int y_offset, const int polarity,
+ const int width, const int height,
+ unsigned int *f, unsigned int *g);
+ static unsigned int generateNoise(unsigned int pixel, NoiseType type);
+ static unsigned int interpolateColor(QImage *image, double x, double y,
+ unsigned int background);
+};
+
+#endif
diff --git a/libopie2/opieui/olistview.cpp b/libopie2/opieui/olistview.cpp
new file mode 100644
index 0000000..2b2f09a
--- a/dev/null
+++ b/libopie2/opieui/olistview.cpp
@@ -0,0 +1,423 @@
+/*
+                 This file is part of the Opie Project
+
+ =. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* QT */
+
+#include <qcolor.h>
+#include <qheader.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+
+/* OPIE */
+
+#include <opie2/olistview.h>
+
+/*======================================================================================
+ * OListView
+ *======================================================================================*/
+
+OListView::OListView( QWidget *parent, const char *name )
+ :QListView( parent, name )
+{
+ //FIXME: get from global settings and calculate ==> see oglobalsettings.*
+
+ m_alternateBackground = QColor( 238, 246, 255 );
+ m_columnSeparator = QPen( QColor( 150, 160, 170 ), 0, DotLine );
+ m_fullWidth = true;
+}
+
+OListView::~OListView()
+{
+}
+
+void OListView::setFullWidth( bool fullWidth )
+{
+ m_fullWidth = m_fullWidth;
+ #if QT_VERSION > 290
+ header()->setStretchEnabled( fullWidth, columns()-1 );
+ #endif
+}
+
+bool OListView::fullWidth() const
+{
+ return m_fullWidth;
+}
+
+int OListView::addColumn( const QString& label, int width )
+{
+ int result = QListView::addColumn( label, width );
+ #if QT_VERSION > 290
+ if (m_fullWidth) {
+ header()->setStretchEnabled( false, columns()-2 );
+ header()->setStretchEnabled( true, columns()-1 );
+ }
+ #endif
+ return result;
+}
+
+int OListView::addColumn( const QIconSet& iconset, const QString& label, int width )
+{
+ int result = QListView::addColumn( iconset, label, width );
+ #if QT_VERSION > 290
+ if (m_fullWidth) {
+ header()->setStretchEnabled( false, columns()-2 );
+ header()->setStretchEnabled( true, columns()-1 );
+ }
+ #endif
+ return result;
+}
+
+void OListView::removeColumn( int index )
+{
+ QListView::removeColumn(index);
+ #if QT_VERSION > 290
+ if ( m_fullWidth && index == columns() )
+ {
+ header()->setStretchEnabled( true, columns()-1 );
+ }
+ #endif
+}
+
+const QColor& OListView::alternateBackground() const
+{
+ return m_alternateBackground;
+}
+
+void OListView::setAlternateBackground( const QColor &c )
+{
+ m_alternateBackground = c;
+ repaint();
+}
+
+const QPen& OListView::columnSeparator() const
+{
+ return m_columnSeparator;
+}
+
+void OListView::setColumnSeparator( const QPen& p )
+{
+ m_columnSeparator = p;
+ repaint();
+}
+
+OListViewItem* OListView::childFactory()
+{
+ return new OListViewItem( this );
+}
+
+#ifndef QT_NO_DATASTREAM
+void OListView::serializeTo( QDataStream& s ) const
+{
+ #warning Caution... the binary format is still under construction...
+ qDebug( "storing OListView..." );
+
+ // store number of columns and the labels
+ s << columns();
+ for ( int i = 0; i < columns(); ++i )
+ s << columnText( i );
+
+ // calculate the number of top-level items to serialize
+ int items = 0;
+ QListViewItem* item = firstChild();
+ while ( item )
+ {
+ item = item->nextSibling();
+ items++;
+ }
+
+ // store number of items and the items itself
+ s << items;
+ item = firstChild();
+ for ( int i = 0; i < items; ++i )
+ {
+ s << *static_cast<OListViewItem*>( item );
+ item = item->nextSibling();
+ }
+
+ qDebug( "OListview stored." );
+}
+
+void OListView::serializeFrom( QDataStream& s )
+{
+ #warning Caution... the binary format is still under construction...
+ qDebug( "loading OListView..." );
+
+ int cols;
+ s >> cols;
+ qDebug( "read number of columns = %d", cols );
+
+ while ( columns() < cols ) addColumn( QString::null );
+
+ for ( int i = 0; i < cols; ++i )
+ {
+ QString coltext;
+ s >> coltext;
+ qDebug( "read text '%s' for column %d", (const char*) coltext, i );
+ setColumnText( i, coltext );
+ }
+
+ int items;
+ s >> items;
+ qDebug( "read number of items = %d", items );
+
+ for ( int i = 0; i < items; ++i )
+ {
+ OListViewItem* item = childFactory();
+ s >> *item;
+ }
+
+ qDebug( "OListView loaded." );
+
+}
+
+QDataStream& operator<<( QDataStream& s, const OListView& lv )
+{
+ lv.serializeTo( s );
+}
+
+QDataStream& operator>>( QDataStream& s, OListView& lv )
+{
+ lv.serializeFrom( s );
+}
+#endif // QT_NO_DATASTREAM
+
+/*======================================================================================
+ * OListViewItem
+ *======================================================================================*/
+
+OListViewItem::OListViewItem(QListView *parent)
+ : QListViewItem(parent)
+{
+ init();
+}
+
+OListViewItem::OListViewItem(QListViewItem *parent)
+ : QListViewItem(parent)
+{
+ init();
+}
+
+OListViewItem::OListViewItem(QListView *parent, QListViewItem *after)
+ : QListViewItem(parent, after)
+{
+ init();
+}
+
+OListViewItem::OListViewItem(QListViewItem *parent, QListViewItem *after)
+ : QListViewItem(parent, after)
+{
+ init();
+}
+
+OListViewItem::OListViewItem(QListView *parent,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+OListViewItem::OListViewItem(QListViewItem *parent,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+OListViewItem::OListViewItem(QListView *parent, QListViewItem *after,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+OListViewItem::OListViewItem(QListViewItem *parent, QListViewItem *after,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+OListViewItem::~OListViewItem()
+{
+}
+
+void OListViewItem::init()
+{
+ m_known = false;
+}
+
+const QColor &OListViewItem::backgroundColor()
+{
+ return isAlternate() ? static_cast<OListView*>(listView())->alternateBackground() :
+ listView()->viewport()->colorGroup().base();
+}
+
+bool OListViewItem::isAlternate()
+{
+ OListView *lv = static_cast<OListView*>( listView() );
+
+ // check if the item above is an OListViewItem
+ OListViewItem *above = static_cast<OListViewItem*>( itemAbove() );
+ /*if (! itemAbove()->inherits( "OListViewItem" )) return false;*/
+
+ // check if we have a valid alternate background color
+ if (!(lv && lv->alternateBackground().isValid())) return false;
+
+ m_known = above ? above->m_known : true;
+ if (m_known)
+ {
+ m_odd = above ? !above->m_odd : false;
+ }
+ else
+ {
+ OListViewItem *item;
+ bool previous = true;
+ if (parent())
+ {
+ item = static_cast<OListViewItem *>(parent());
+ if ( item /*&& item->inherits( "OListViewItem" )*/ ) previous = item->m_odd;
+ item = static_cast<OListViewItem *>(parent()->firstChild());
+ /* if ( !item.inherits( "OListViewItem" ) item = 0; */
+ }
+ else
+ {
+ item = static_cast<OListViewItem *>(lv->firstChild());
+ }
+
+ while(item)
+ {
+ item->m_odd = previous = !previous;
+ item->m_known = true;
+ item = static_cast<OListViewItem *>(item->nextSibling());
+ /* if (!item.inherits( "OListViewItem" ) ) break; */
+ }
+ }
+ return m_odd;
+}
+
+void OListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment)
+{
+ QColorGroup _cg = cg;
+ const QPixmap *pm = listView()->viewport()->backgroundPixmap();
+ if (pm && !pm->isNull())
+ {
+ _cg.setBrush( QColorGroup::Base, QBrush(backgroundColor(), *pm) );
+ p->setBrushOrigin( -listView()->contentsX(), -listView()->contentsY() );
+ }
+ else if ( isAlternate() )
+ {
+ _cg.setColor( QColorGroup::Base, static_cast<OListView*>( listView() )->alternateBackground() );
+ }
+ QListViewItem::paintCell( p, _cg, column, width, alignment );
+
+ //FIXME: Use styling here!
+
+ const QPen& pen = static_cast<OListView*>( listView() )->columnSeparator();
+ p->setPen( pen );
+ p->drawLine( width-1, 0, width-1, height() );
+}
+
+OListViewItem* OListViewItem::childFactory()
+{
+ return new OListViewItem( this );
+}
+
+#ifndef QT_NO_DATASTREAM
+void OListViewItem::serializeTo( QDataStream& s ) const
+{
+ #warning Caution... the binary format is still under construction...
+ qDebug( "storing OListViewItem..." );
+
+ // store item text
+ for ( int i = 0; i < listView()->columns(); ++i )
+ {
+ s << text( i );
+ }
+
+ // calculate the number of children to serialize
+ int items = 0;
+ QListViewItem* item = firstChild();
+ while ( item )
+ {
+ item = item->nextSibling();
+ items++;
+ }
+
+ // store number of items and the items itself
+ s << items;
+ item = firstChild();
+ for ( int i = 0; i < items; ++i )
+ {
+ s << *static_cast<OListViewItem*>( item );
+ item = item->nextSibling();
+ }
+
+ qDebug( "OListviewItem stored." );
+}
+void OListViewItem::serializeFrom( QDataStream& s )
+{
+ #warning Caution... the binary format is still under construction...
+ qDebug( "loading OListViewItem..." );
+
+ for ( int i = 0; i < listView()->columns(); ++i )
+ {
+ QString coltext;
+ s >> coltext;
+ qDebug( "read text '%s' for column %d", (const char*) coltext, i );
+ setText( i, coltext );
+ }
+
+ int items;
+ s >> items;
+ qDebug( "read number of items = %d", items );
+
+ for ( int i = 0; i < items; ++i )
+ {
+ OListViewItem* item = childFactory();
+ s >> (*item);
+ }
+
+ qDebug( "OListViewItem loaded." );
+}
+
+QDataStream& operator<<( QDataStream& s, const OListViewItem& lvi )
+{
+ lvi.serializeTo( s );
+}
+
+QDataStream& operator>>( QDataStream& s, OListViewItem& lvi )
+{
+ lvi.serializeFrom( s );
+}
+#endif // QT_NO_DATASTREAM
diff --git a/libopie2/opieui/olistview.h b/libopie2/opieui/olistview.h
new file mode 100644
index 0000000..bafc67c
--- a/dev/null
+++ b/libopie2/opieui/olistview.h
@@ -0,0 +1,235 @@
+/*
+                 This file is part of the Opie Project
+
+ =. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OLISTVIEW_H
+#define OLISTVIEW_H
+
+#include <qcolor.h>
+#include <qlistview.h>
+#include <qpen.h>
+#include <qdatastream.h>
+
+class OListViewItem;
+
+/**
+ * A @ref QListView variant featuring visual and functional enhancements
+ * like an alternate background for odd rows, an autostretch mode
+ * for the width of the widget ( >= Qt 3 only ) and persistence capabilities.
+ *
+ * @author Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ * @short OListView list/tree widget.
+ */
+ class OListView: public QListView
+{
+ public:
+ /**
+ * Constructor.
+ *
+ * The parameters @p parent and @p name are handled by
+ * @ref QListView, as usual.
+ */
+ OListView ( QWidget *parent = 0, const char *name = 0 );
+
+ /**
+ * Destructor.
+ */
+ virtual ~OListView();
+
+ /**
+ * Let the last column fit exactly all the available width.
+ */
+ void setFullWidth( bool fullWidth );
+
+ /**
+ * Returns whether the last column is set to fit the available width.
+ */
+ bool fullWidth() const;
+
+ /**
+ * Reimplemented for full width support
+ */
+ virtual int addColumn( const QString& label, int width = -1 );
+
+ /**
+ * Reimplemented for full width support
+ */
+ virtual int addColumn( const QIconSet& iconset, const QString& label, int width = -1 );
+
+ /**
+ * Reimplemented for full width support
+ */
+ virtual void removeColumn(int index);
+
+ /**
+ * sets the alternate background background color.
+ * This only has an effect if the items are OListViewItems
+ *
+ * @param c the color to use for every other item. Set to an invalid
+ * color to disable alternate colors.
+ */
+ void setAlternateBackground( const QColor &c );
+
+ /**
+ * sets the column separator pen.
+ *
+ * @param p the pen used to draw the column separator.
+ */
+ void setColumnSeparator( const QPen &p );
+
+ /**
+ * @return the alternate background color
+ */
+ const QColor& alternateBackground() const;
+
+ /**
+ * @return the column separator pen
+ */
+ const QPen& columnSeparator() const;
+
+ /**
+ * create a list view item as child of this object
+ * @return the new object
+ */
+ virtual OListViewItem* childFactory();
+
+ #ifndef QT_NO_DATASTREAM
+ /**
+ * serialize this object to a @ref QDataStream
+ * @param s the stream used to serialize this object.
+ */
+ virtual void serializeTo( QDataStream& s ) const;
+
+ /**
+ * serialize this object from a @ref QDataStream
+ * @param s the stream used to serialize this object.
+ */
+ virtual void serializeFrom( QDataStream& s );
+ #endif
+
+ private:
+ QColor m_alternateBackground;
+ bool m_fullWidth;
+ QPen m_columnSeparator;
+};
+
+#ifndef QT_NO_DATASTREAM
+/**
+ * \relates QListView
+ * Writes a listview to the stream and returns a reference to the stream.
+ */
+QDataStream& operator<<( QDataStream& s, const OListView& lv );
+/**
+ * \relates QListView
+ * Reads a listview from the stream and returns a reference to the stream.
+ */
+QDataStream& operator>>( QDataStream& s, OListView& lv );
+#endif // QT_NO_DATASTREAM
+
+//****************************** OListViewItem ******************************************************************
+
+class OListViewItem: public QListViewItem
+{
+ public:
+ OListViewItem( QListView * parent );
+ OListViewItem( QListViewItem * parent );
+ OListViewItem( QListView * parent, QListViewItem * after );
+ OListViewItem( QListViewItem * parent, QListViewItem * after );
+
+ OListViewItem( QListView * parent,
+ QString, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null );
+
+ OListViewItem( QListViewItem * parent,
+ QString, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null );
+
+ OListViewItem( QListView * parent, QListViewItem * after,
+ QString, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null );
+
+ OListViewItem( QListViewItem * parent, QListViewItem * after,
+ QString, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null );
+
+ virtual ~OListViewItem();
+
+ const QColor& backgroundColor();
+ bool isAlternate();
+ void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment );
+ void init();
+
+ /**
+ * create a list view item as child of this object
+ * @return the new object
+ */
+ virtual OListViewItem* childFactory();
+
+ #ifndef QT_NO_DATASTREAM
+ /**
+ * serialize this object to or from a @ref QDataStream
+ * @param s the stream used to serialize this object.
+ */
+ virtual void serializeTo( QDataStream& s ) const;
+
+ /**
+ * serialize this object to or from a @ref QDataStream
+ * @param s the stream used to serialize this object.
+ */
+ virtual void serializeFrom( QDataStream& s );
+ #endif
+
+ private:
+ bool m_known;
+ bool m_odd;
+};
+
+#ifndef QT_NO_DATASTREAM
+/**
+ * \relates QListViewItem
+ * Writes a listview item and all subitems recursively to the stream
+ * and returns a reference to the stream.
+ */
+QDataStream& operator<<( QDataStream &s, const OListViewItem& lvi );
+/**
+ * \relates QListViewItem
+ * Reads a listview item from the stream and returns a reference to the stream.
+ */
+QDataStream& operator>>( QDataStream &s, OListViewItem& lvi );
+#endif // QT_NO_DATASTREAM
+
+#endif // OLISTVIEW_H
diff --git a/libopie2/opieui/opieui.pro b/libopie2/opieui/opieui.pro
new file mode 100644
index 0000000..dffbbde
--- a/dev/null
+++ b/libopie2/opieui/opieui.pro
@@ -0,0 +1,46 @@
+TEMPLATE = lib
+CONFIG += qt warn_on debug
+DESTDIR = $(QTDIR)/lib
+HEADERS = ocompletionbox.h \
+ ocombobox.h \
+ oeditlistbox.h \
+ olineedit.h \
+ olistview.h \
+ oimageeffect.h \
+ opixmapeffect.h \
+ opopupmenu.h \
+ opixmapprovider.h \
+ oselector.h \
+ oversatileview.h \
+ oversatileviewitem.h \
+ #ojanuswidget.h \
+ odialog.h \
+ oseparator.h
+
+SOURCES = ocompletionbox.cpp \
+ ocombobox.cpp \
+ oeditlistbox.cpp \
+ olineedit.cpp \
+ olistview.cpp \
+ oimageeffect.cpp \
+ opixmapeffect.cpp \
+ opopupmenu.cpp \
+ opixmapprovider.cpp \
+ oselector.cpp \
+ oversatileview.cpp \
+ oversatileviewitem.cpp \
+ #ojanuswidget.cpp \
+ odialog.cpp \
+ oseparator.cpp
+
+INTERFACES =
+TARGET = opieui2
+VERSION = 1.8.1
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+LIBS += -lopiecore2
+MOC_DIR = moc
+OBJECTS_DIR = obj
+
+include ( $(OPIEDIR)/include.pro )
+
diff --git a/libopie2/opieui/opixmapeffect.cpp b/libopie2/opieui/opixmapeffect.cpp
new file mode 100644
index 0000000..05f851d
--- a/dev/null
+++ b/libopie2/opieui/opixmapeffect.cpp
@@ -0,0 +1,328 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
+ (C) 1998, 1999 Daniel M. Duley <mosfet@kde.org>
+ (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
+
+*/
+
+// $Id$
+
+/* QT */
+
+#include <qimage.h>
+#include <qpainter.h>
+
+/* OPIE */
+
+#include <opie2/opixmapeffect.h>
+#include <opie2/oimageeffect.h>
+
+//======================================================================
+//
+// Gradient effects
+//
+//======================================================================
+
+
+OPixmap& OPixmapEffect::gradient(OPixmap &pixmap, const QColor &ca,
+ const QColor &cb, GradientType eff, int ncols)
+{
+ if(pixmap.depth() > 8 &&
+ (eff == VerticalGradient || eff == HorizontalGradient)) {
+
+ int rDiff, gDiff, bDiff;
+ int rca, gca, bca /*, rcb, gcb, bcb*/;
+
+ register int x, y;
+
+ rDiff = (/*rcb = */ cb.red()) - (rca = ca.red());
+ gDiff = (/*gcb = */ cb.green()) - (gca = ca.green());
+ bDiff = (/*bcb = */ cb.blue()) - (bca = ca.blue());
+
+ register int rl = rca << 16;
+ register int gl = gca << 16;
+ register int bl = bca << 16;
+
+ int rcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * rDiff;
+ int gcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * gDiff;
+ int bcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * bDiff;
+
+ QPainter p(&pixmap);
+
+ // these for-loops could be merged, but the if's in the inner loop
+ // would make it slow
+ switch(eff) {
+ case VerticalGradient:
+ for ( y = 0; y < pixmap.height(); y++ ) {
+ rl += rcdelta;
+ gl += gcdelta;
+ bl += bcdelta;
+
+ p.setPen(QColor(rl>>16, gl>>16, bl>>16));
+ p.drawLine(0, y, pixmap.width()-1, y);
+ }
+ break;
+ case HorizontalGradient:
+ for( x = 0; x < pixmap.width(); x++) {
+ rl += rcdelta;
+ gl += gcdelta;
+ bl += bcdelta;
+
+ p.setPen(QColor(rl>>16, gl>>16, bl>>16));
+ p.drawLine(x, 0, x, pixmap.height()-1);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ else {
+ QImage image = OImageEffect::gradient(pixmap.size(), ca, cb,
+ (OImageEffect::GradientType) eff, ncols);
+ pixmap.convertFromImage(image);
+ }
+
+ return pixmap;
+}
+
+
+// -----------------------------------------------------------------------------
+
+OPixmap& OPixmapEffect::unbalancedGradient(OPixmap &pixmap, const QColor &ca,
+ const QColor &cb, GradientType eff, int xfactor, int yfactor,
+ int ncols)
+{
+ QImage image = OImageEffect::unbalancedGradient(pixmap.size(), ca, cb,
+ (OImageEffect::GradientType) eff,
+ xfactor, yfactor, ncols);
+ pixmap.convertFromImage(image);
+
+ return pixmap;
+}
+
+
+//======================================================================
+//
+// Intensity effects
+//
+//======================================================================
+
+
+
+OPixmap& OPixmapEffect::intensity(OPixmap &pixmap, float percent)
+{
+ QImage image = pixmap.convertToImage();
+ OImageEffect::intensity(image, percent);
+ pixmap.convertFromImage(image);
+
+ return pixmap;
+}
+
+
+// -----------------------------------------------------------------------------
+
+OPixmap& OPixmapEffect::channelIntensity(OPixmap &pixmap, float percent,
+ RGBComponent channel)
+{
+ QImage image = pixmap.convertToImage();
+ OImageEffect::channelIntensity(image, percent,
+ (OImageEffect::RGBComponent) channel);
+ pixmap.convertFromImage(image);
+
+ return pixmap;
+}
+
+
+//======================================================================
+//
+// Blend effects
+//
+//======================================================================
+
+
+OPixmap& OPixmapEffect::blend(OPixmap &pixmap, float initial_intensity,
+ const QColor &bgnd, GradientType eff,
+ bool anti_dir, int ncols)
+{
+
+ QImage image = pixmap.convertToImage();
+ if (image.depth() <=8)
+ image = image.convertDepth(32); //Sloww..
+
+ OImageEffect::blend(image, initial_intensity, bgnd,
+ (OImageEffect::GradientType) eff, anti_dir);
+
+ unsigned int tmp;
+
+ if(pixmap.depth() <= 8 ) {
+ if ( ncols < 2 || ncols > 256 )
+ ncols = 3;
+ QColor *dPal = new QColor[ncols];
+ for (int i=0; i<ncols; i++) {
+ tmp = 0 + 255 * i / ( ncols - 1 );
+ dPal[i].setRgb ( tmp, tmp, tmp );
+ }
+ OImageEffect::dither(image, dPal, ncols);
+ pixmap.convertFromImage(image);
+ delete [] dPal;
+ }
+ else
+ pixmap.convertFromImage(image);
+
+ return pixmap;
+}
+
+
+//======================================================================
+//
+// Hash effects
+//
+//======================================================================
+
+OPixmap& OPixmapEffect::hash(OPixmap &pixmap, Lighting lite,
+ unsigned int spacing, int ncols)
+{
+ QImage image = pixmap.convertToImage();
+ OImageEffect::hash(image, (OImageEffect::Lighting) lite, spacing);
+
+ unsigned int tmp;
+
+ if(pixmap.depth() <= 8 ) {
+ if ( ncols < 2 || ncols > 256 )
+ ncols = 3;
+ QColor *dPal = new QColor[ncols];
+ for (int i=0; i<ncols; i++) {
+ tmp = 0 + 255 * i / ( ncols - 1 );
+ dPal[i].setRgb ( tmp, tmp, tmp );
+ }
+ OImageEffect::dither(image, dPal, ncols);
+ pixmap.convertFromImage(image);
+ delete [] dPal;
+ }
+ else
+ pixmap.convertFromImage(image);
+
+ return pixmap;
+}
+
+
+//======================================================================
+//
+// Pattern effects
+//
+//======================================================================
+
+#if 0
+void OPixmapEffect::pattern(OPixmap &pixmap, const QColor &ca,
+ const QColor &cb, unsigned pat[8])
+{
+ QImage img = pattern(pixmap.size(), ca, cb, pat);
+ pixmap.convertFromImage(img);
+}
+#endif
+
+// -----------------------------------------------------------------------------
+
+OPixmap OPixmapEffect::pattern(const OPixmap& pmtile, QSize size,
+ const QColor &ca, const QColor &cb, int ncols)
+{
+ if (pmtile.depth() > 8)
+ ncols = 0;
+
+ QImage img = pmtile.convertToImage();
+ OImageEffect::flatten(img, ca, cb, ncols);
+ OPixmap pixmap;
+ pixmap.convertFromImage(img);
+
+ return OPixmapEffect::createTiled(pixmap, size);
+}
+
+
+// -----------------------------------------------------------------------------
+
+OPixmap OPixmapEffect::createTiled(const OPixmap& pixmap, QSize size)
+{
+ OPixmap pix;
+
+ QPainter p(&pix);
+ p.drawTiledPixmap(0, 0, size.width(), size.height(), pixmap);
+
+ return pix;
+}
+
+
+//======================================================================
+//
+// Fade effects
+//
+//======================================================================
+
+OPixmap& OPixmapEffect::fade(OPixmap &pixmap, double val, const QColor &color)
+{
+ QImage img = pixmap.convertToImage();
+ OImageEffect::fade(img, val, color);
+ pixmap.convertFromImage(img);
+
+ return pixmap;
+}
+
+
+// -----------------------------------------------------------------------------
+OPixmap& OPixmapEffect::toGray(OPixmap &pixmap, bool fast)
+{
+ QImage img = pixmap.convertToImage();
+ OImageEffect::toGray(img, fast);
+ pixmap.convertFromImage(img);
+
+ return pixmap;
+}
+
+// -----------------------------------------------------------------------------
+OPixmap& OPixmapEffect::desaturate(OPixmap &pixmap, float desat)
+{
+ QImage img = pixmap.convertToImage();
+ OImageEffect::desaturate(img, desat);
+ pixmap.convertFromImage(img);
+
+ return pixmap;
+}
+// -----------------------------------------------------------------------------
+OPixmap& OPixmapEffect::contrast(OPixmap &pixmap, int c)
+{
+ QImage img = pixmap.convertToImage();
+ OImageEffect::contrast(img, c);
+ pixmap.convertFromImage(img);
+
+ return pixmap;
+}
+
+//======================================================================
+//
+// Dither effects
+//
+//======================================================================
+
+// -----------------------------------------------------------------------------
+OPixmap& OPixmapEffect::dither(OPixmap &pixmap, const QColor *palette, int size)
+{
+ QImage img = pixmap.convertToImage();
+ OImageEffect::dither(img, palette, size);
+ pixmap.convertFromImage(img);
+
+ return pixmap;
+}
+
+//======================================================================
+//
+// Other effects
+//
+//======================================================================
+
+OPixmap OPixmapEffect::selectedPixmap( const OPixmap &pix, const QColor &col )
+{
+ QImage img = pix.convertToImage();
+ OImageEffect::selectedImage(img, col);
+ OPixmap outPix;
+ outPix.convertFromImage(img);
+ return outPix;
+}
diff --git a/libopie2/opieui/opixmapeffect.h b/libopie2/opieui/opixmapeffect.h
new file mode 100644
index 0000000..283fe2d
--- a/dev/null
+++ b/libopie2/opieui/opixmapeffect.h
@@ -0,0 +1,215 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
+ (C) 1998, 1999 Daniel M. Duley <mosfet@kde.org>
+ (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
+
+*/
+
+// $Id$
+
+#ifndef __OPIXMAP_EFFECT_H
+#define __OPIXMAP_EFFECT_H
+
+
+#include <qsize.h>
+typedef QPixmap OPixmap;
+class QColor;
+
+/**
+ * This class includes various pixmap-based graphical effects.
+ *
+ * Everything is
+ * static, so there is no need to create an instance of this class. You can
+ * just call the static methods. They are encapsulated here merely to provide
+ * a common namespace.
+ */
+class OPixmapEffect
+{
+public:
+ enum GradientType { VerticalGradient, HorizontalGradient,
+ DiagonalGradient, CrossDiagonalGradient,
+ PyramidGradient, RectangleGradient,
+ PipeCrossGradient, EllipticGradient };
+ enum RGBComponent { Red, Green, Blue };
+
+ enum Lighting {NorthLite, NWLite, WestLite, SWLite,
+ SouthLite, SELite, EastLite, NELite};
+
+ /**
+ * Creates a gradient from color a to color b of the specified type.
+ *
+ * @param pixmap The pixmap to process.
+ * @param ca Color a.
+ * @param cb Color b.
+ * @param type The type of gradient.
+ * @param ncols The number of colors to use when not running on a
+ * truecolor display. The gradient will be dithered to this number of
+ * colors. Pass 0 to prevent dithering.
+ * @return Returns the generated pixmap, for convenience.
+ */
+ static OPixmap& gradient(OPixmap& pixmap, const QColor &ca, const QColor &cb,
+ GradientType type, int ncols=3);
+
+ /**
+ * Creates an unbalanced gradient.
+ *
+ * An unbalanced gradient is a gradient where the transition from
+ * color a to color b is not linear, but in this case, exponential.
+ *
+ * @param pixmap The pixmap that should be written.
+ * @param ca Color a.
+ * @param cb Color b.
+ * @param type The type of gradient.
+ * @param xfactor The x decay length. Use a value between -200 and 200.
+ * @param yfactor The y decay length.
+ * @param ncols The number of colors. See #gradient.
+ * @return The generated pixmap, for convencience.
+ */
+ static OPixmap& unbalancedGradient(OPixmap& pixmap, const QColor &ca,
+ const QColor &cb, GradientType type, int xfactor = 100,
+ int yfactor = 100, int ncols=3);
+
+ /**
+ * Creates a pixmap of a given size with the given pixmap.
+ *
+ * if the
+ * given size is bigger than the size of the pixmap, the pixmap is
+ * tiled.
+ *
+ * @param pixmap This is the source pixmap
+ * @param size The size the new pixmap should have.
+ * @return The generated, tiled pixmap.
+ */
+ static OPixmap createTiled(const OPixmap& pixmap, QSize size);
+
+ /**
+ * Either brightens or dims a pixmap by a specified ratio.
+ *
+ * @param pixmap The pixmap to process.
+ * @param ratio The ratio to use. Use negative value to dim.
+ * @return Returns The @ref pixmap(), provided for convenience.
+ */
+ static OPixmap& intensity(OPixmap& pixmap, float ratio);
+
+ /**
+ * Modifies the intensity of a pixmap's RGB channel component.
+ *
+ * @param pixmap The pixmap to process.
+ * @param ratio value. Use negative value to dim.
+ * @param channel Which channel(s) should be modified
+ * @return Returns the @ref pixmap(), provided for convenience.
+ */
+ static OPixmap& channelIntensity(OPixmap& pixmap, float ratio,
+ RGBComponent channel);
+
+ /**
+ * Blends the provided pixmap into a background of the indicated color.
+ *
+ * @param pixmap The pixmap to process.
+ * @param initial_intensity this parameter takes values from -1 to 1:
+ * @li If positive, it tells how much to fade the image in its
+ * less affected spot.
+ * @li If negative, it tells roughly indicates how much of the image
+ * remains unaffected
+ * @param bgnd Indicates the color of the background to blend in.
+ * @param eff Lets you choose what kind of blending you like.
+ * @param anti_dir Blend in the opposite direction (makes no much sense
+ * with concentric blending effects).
+ * @return Returns the @ref pixmap(), provided for convenience.
+ */
+ static OPixmap& blend(OPixmap& pixmap, float initial_intensity,
+ const QColor &bgnd, GradientType eff,
+ bool anti_dir=false, int ncols=3);
+
+ /**
+ * Builds a hash on any given pixmap.
+ *
+ * @param pixmap The pixmap to process.
+ * @param lite The hash faces the indicated lighting (cardinal poles)
+ * @param spacing How many unmodified pixels inbetween hashes.
+ * @return Returns The @ref pixmap(), provided for convenience.
+ */
+ static OPixmap& hash(OPixmap& pixmap, Lighting lite=NorthLite,
+ unsigned int spacing=0, int ncols=3);
+
+ /**
+ * Creates a pattern from a pixmap.
+ *
+ * The given pixmap is "flattened"
+ * between color a to color b.
+ *
+ * @param pixmap The pixmap to process.
+ * @param ca Color a.
+ * @param cb Color b.
+ * @param ncols The number of colors to use. The image will be
+ * dithered to this depth. Pass zero to prevent dithering.
+ * @return The @ref pixmap(), provided for convenience.
+ */
+ static OPixmap pattern(const OPixmap& pixmap, QSize size,
+ const QColor &ca, const QColor &cb, int ncols=8);
+
+ /**
+ * Recolors a pixmap.
+ *
+ * The most dark color will become color a,
+ * the most bright one color b, and in between.
+ *
+ * @param pixmap The pixmap to process.
+ * @param ca Color a.
+ * @param cb Color b.
+ * @param ncols The number of colors to use. Pass zero to prevent
+ * dithering.
+ * @return Returns the @ref pixmap(), provided for convenience.
+ */
+ static OPixmap& fade(OPixmap& pixmap, double val, const QColor &color);
+
+ /**
+ * Converts a pixmap to grayscale.
+ *
+ * @param pixmap The pixmap to process.
+ * @param fast Set to @p true in order to use a faster but non-photographic
+ * quality algorithm. Appropriate for things such as toolbar icons.
+ * @return Returns the @ref pixmap(), provided for convenience.
+ */
+ static OPixmap& toGray(OPixmap& pixmap, bool fast=false);
+
+ /**
+ * Desaturates a pixmap.
+ *
+ * @param pixmap The pixmap to process.
+ * @param desat A value between 0 and 1 setting the degree of desaturation
+ * @return Returns The @ref pixmap(), provided for convenience.
+ */
+ static OPixmap& desaturate(OPixmap& pixmap, float desat = 0.3);
+
+ /**
+ * Modifies the contrast of a pixmap.
+ *
+ * @param pixmap The pixmap to process.
+ * @param c A contrast value between -255 and 255.
+ * @return Returns the @ref pixmap(), provided for convenience.
+ */
+ static OPixmap& contrast(OPixmap& pixmap, int c);
+
+ /**
+ * Dithers a pixmap using Floyd-Steinberg dithering for low-color
+ * situations.
+ *
+ * @param pixmap The pixmap to process.
+ * @param palette The color palette to use.
+ * @param size The size of the palette.
+ * @return Returns the @ref pixmap(), provided for convenience.
+ */
+ static OPixmap& dither(OPixmap &pixmap, const QColor *palette, int size);
+
+ /**
+ * Calculate a 'selected' pixmap, for instance a selected icon
+ * on the desktop.
+ * @param pixmap the pixmap to select
+ * @param col the selected color, usually from QColorGroup::highlight().
+ */
+ static OPixmap selectedPixmap( const OPixmap &pixmap, const QColor &col );
+};
+
+
+#endif
diff --git a/libopie2/opieui/opixmapprovider.cpp b/libopie2/opieui/opixmapprovider.cpp
new file mode 100644
index 0000000..7be9e3b
--- a/dev/null
+++ b/libopie2/opieui/opixmapprovider.cpp
@@ -0,0 +1,27 @@
+/* This file is part of the KDE libraries
+
+ Copyright (c) 2000 Carsten Pfeiffer <pfeiffer@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 (LGPL) 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <opie2/opixmapprovider.h>
+
+OPixmapProvider::~OPixmapProvider() {}
+
+void OPixmapProvider::virtual_hook( int , void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
diff --git a/libopie2/opieui/opixmapprovider.h b/libopie2/opieui/opixmapprovider.h
new file mode 100644
index 0000000..5b76647
--- a/dev/null
+++ b/libopie2/opieui/opixmapprovider.h
@@ -0,0 +1,54 @@
+/* This file is part of the KDE libraries
+
+ Copyright (c) 2000 Carsten Pfeiffer <pfeiffer@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 (LGPL) 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef OPIXMAPPROVIDER_H
+#define OPIXMAPPROVIDER_H
+
+#include <qpixmap.h>
+
+/**
+ * A tiny abstract class with just one method:
+ * @ref pixmapFor()
+ *
+ * It will be called whenever an icon is searched for @p text.
+ *
+ * Used e.g. by @ref KHistoryCombo
+ *
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ * @short an abstract interface for looking up icons
+ */
+class OPixmapProvider
+{
+public:
+ virtual ~OPixmapProvider();
+ /**
+ * You may subclass this and return a pixmap of size @p size for @p text.
+ * @param text the text that is associated with the pixmap
+ * @param size the size of the icon in pixels, 0 for defaylt size.
+ * See @ref KIcon::StdSize.
+ * @return the pixmap for the arguments, or null if there is none
+ */
+ virtual QPixmap pixmapFor( const QString& text, int size = 0 ) = 0;
+protected:
+ virtual void virtual_hook( int id, void* data );
+};
+
+
+#endif // OPIXMAPPROVIDER_H
diff --git a/libopie2/opieui/opopupmenu.cpp b/libopie2/opieui/opopupmenu.cpp
new file mode 100644
index 0000000..ac73188
--- a/dev/null
+++ b/libopie2/opieui/opopupmenu.cpp
@@ -0,0 +1,604 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Daniel M. Duley <mosfet@kde.org>
+ Copyright (C) 2002 Hamish Rodda <meddie@yoyo.its.monash.edu.au>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/* QT */
+
+#include <qapplication.h>
+#include <qcursor.h>
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include <qtimer.h>
+#include <qfont.h>
+#include <qfontmetrics.h>
+#include <qregexp.h>
+#include <qstyle.h>
+
+/* OPIE */
+
+#include <opie2/opopupmenu.h>
+#include <opie2/oconfig.h>
+
+OPopupTitle::OPopupTitle(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ setMinimumSize(16, fontMetrics().height()+8);
+}
+
+OPopupTitle::OPopupTitle(OPixmapEffect::GradientType /* gradient */,
+ const QColor &/* color */, const QColor &/* textColor */,
+ QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ setMinimumSize(16, fontMetrics().height()+8);
+}
+
+OPopupTitle::OPopupTitle(const OPixmap & /* background */, const QColor &/* color */,
+ const QColor &/* textColor */, QWidget *parent,
+ const char *name)
+ : QWidget(parent, name)
+{
+ setMinimumSize(16, fontMetrics().height()+8);
+}
+
+void OPopupTitle::setTitle(const QString &text, const QPixmap *icon)
+{
+ titleStr = text;
+ if (icon)
+ miniicon = *icon;
+ else
+ miniicon.resize(0, 0);
+
+ int w = miniicon.width()+fontMetrics().width(titleStr);
+ int h = QMAX( fontMetrics().height(), miniicon.height() );
+ setMinimumSize( w+16, h+8 );
+}
+
+void OPopupTitle::setText( const QString &text )
+{
+ titleStr = text;
+ int w = miniicon.width()+fontMetrics().width(titleStr);
+ int h = QMAX( fontMetrics().height(), miniicon.height() );
+ setMinimumSize( w+16, h+8 );
+}
+
+void OPopupTitle::setIcon( const QPixmap &pix )
+{
+ miniicon = pix;
+ int w = miniicon.width()+fontMetrics().width(titleStr);
+ int h = QMAX( fontMetrics().height(), miniicon.height() );
+ setMinimumSize( w+16, h+8 );
+}
+
+void OPopupTitle::paintEvent(QPaintEvent *)
+{
+ QRect r(rect());
+ QPainter p(this);
+ #if QT_VERSION > 290
+ qApp->style().drawPrimitive(QStyle::PE_HeaderSection, &p, r, palette().active());
+ #else
+ #warning OPopupMenu is not fully functional on Qt2
+ #endif
+
+ if (!miniicon.isNull())
+ p.drawPixmap(4, (r.height()-miniicon.height())/2, miniicon);
+
+ if (!titleStr.isNull())
+ {
+ p.setPen(palette().active().text());
+ QFont f = p.font();
+ f.setBold(true);
+ p.setFont(f);
+ if(!miniicon.isNull())
+ {
+ p.drawText(miniicon.width()+8, 0, width()-(miniicon.width()+8),
+ height(), AlignLeft | AlignVCenter | SingleLine,
+ titleStr);
+ }
+ else
+ {
+ p.drawText(0, 0, width(), height(),
+ AlignCenter | SingleLine, titleStr);
+ }
+ }
+
+ p.setPen(palette().active().highlight());
+ p.drawLine(0, 0, r.right(), 0);
+}
+
+QSize OPopupTitle::sizeHint() const
+{
+ return(minimumSize());
+}
+
+class OPopupMenu::OPopupMenuPrivate
+{
+public:
+ OPopupMenuPrivate ()
+ : noMatches(false)
+ , shortcuts(false)
+ , autoExec(false)
+ , lastHitIndex(-1)
+ , m_ctxMenu(0)
+ {}
+
+ ~OPopupMenuPrivate ()
+ {
+ delete m_ctxMenu;
+ }
+
+ QString m_lastTitle;
+
+ // variables for keyboard navigation
+ QTimer clearTimer;
+
+ bool noMatches : 1;
+ bool shortcuts : 1;
+ bool autoExec : 1;
+
+ QString keySeq;
+ QString originalText;
+
+ int lastHitIndex;
+
+ // support for RMB menus on menus
+ QPopupMenu* m_ctxMenu;
+ static bool s_continueCtxMenuShow;
+ static int s_highlightedItem;
+ static OPopupMenu* s_contextedMenu;
+};
+
+int OPopupMenu::OPopupMenuPrivate::s_highlightedItem(-1);
+OPopupMenu* OPopupMenu::OPopupMenuPrivate::s_contextedMenu(0);
+bool OPopupMenu::OPopupMenuPrivate::s_continueCtxMenuShow(true);
+
+OPopupMenu::OPopupMenu(QWidget *parent, const char *name)
+ : QPopupMenu(parent, name)
+{
+ d = new OPopupMenuPrivate;
+ resetKeyboardVars();
+ connect(&(d->clearTimer), SIGNAL(timeout()), SLOT(resetKeyboardVars()));
+}
+
+OPopupMenu::~OPopupMenu()
+{
+ if (OPopupMenuPrivate::s_contextedMenu == this)
+ {
+ OPopupMenuPrivate::s_contextedMenu = 0;
+ OPopupMenuPrivate::s_highlightedItem = -1;
+ }
+
+ delete d;
+}
+
+int OPopupMenu::insertTitle(const QString &text, int id, int index)
+{
+ OPopupTitle *titleItem = new OPopupTitle();
+ titleItem->setTitle(text);
+ int ret = insertItem(titleItem, id, index);
+ setItemEnabled(id, false);
+ return ret;
+}
+
+int OPopupMenu::insertTitle(const QPixmap &icon, const QString &text, int id,
+ int index)
+{
+ OPopupTitle *titleItem = new OPopupTitle();
+ titleItem->setTitle(text, &icon);
+ int ret = insertItem(titleItem, id, index);
+ setItemEnabled(id, false);
+ return ret;
+}
+
+void OPopupMenu::changeTitle(int id, const QString &text)
+{
+ QMenuItem *item = findItem(id);
+ if(item){
+ if(item->widget())
+ ((OPopupTitle *)item->widget())->setTitle(text);
+#ifndef NDEBUG
+ else
+ qWarning( "KPopupMenu: changeTitle() called with non-title id %d", id );
+#endif
+ }
+#ifndef NDEBUG
+ else
+ qWarning( "KPopupMenu: changeTitle() called with invalid id %d", id );
+#endif
+}
+
+void OPopupMenu::changeTitle(int id, const QPixmap &icon, const QString &text)
+{
+ QMenuItem *item = findItem(id);
+ if(item){
+ if(item->widget())
+ ((OPopupTitle *)item->widget())->setTitle(text, &icon);
+#ifndef NDEBUG
+ else
+ qWarning( "KPopupMenu: changeTitle() called with non-title id %d", id );
+#endif
+ }
+#ifndef NDEBUG
+ else
+ qWarning( "KPopupMenu: changeTitle() called with invalid id %d", id );
+#endif
+}
+
+QString OPopupMenu::title(int id) const
+{
+ if(id == -1) // obsolete
+ return(d->m_lastTitle);
+ QMenuItem *item = findItem(id);
+ if(item){
+ if(item->widget())
+ return(((OPopupTitle *)item->widget())->title());
+ else
+ qWarning("OPopupMenu: title() called with non-title id %d.", id);
+ }
+ else
+ qWarning("OPopupMenu: title() called with invalid id %d.", id);
+ return(QString::null);
+}
+
+QPixmap OPopupMenu::titlePixmap(int id) const
+{
+ QMenuItem *item = findItem(id);
+ if(item){
+ if(item->widget())
+ return(((OPopupTitle *)item->widget())->icon());
+ else
+ qWarning("KPopupMenu: titlePixmap() called with non-title id %d.", id);
+ }
+ else
+ qWarning("KPopupMenu: titlePixmap() called with invalid id %d.", id);
+ QPixmap tmp;
+ return(tmp);
+}
+
+/**
+ * This is re-implemented for keyboard navigation.
+ */
+void OPopupMenu::closeEvent(QCloseEvent*e)
+{
+ if (d->shortcuts)
+ resetKeyboardVars();
+ QPopupMenu::closeEvent(e);
+}
+
+void OPopupMenu::keyPressEvent(QKeyEvent* e)
+{
+ if (!d->shortcuts) {
+ // continue event processing by Qpopup
+ //e->ignore();
+ QPopupMenu::keyPressEvent(e);
+ return;
+ }
+
+ int i = 0;
+ bool firstpass = true;
+ QString keyString = e->text();
+
+ // check for common commands dealt with by QPopup
+ int key = e->key();
+ if (key == Key_Escape || key == Key_Return || key == Key_Enter
+ || key == Key_Up || key == Key_Down || key == Key_Left
+ || key == Key_Right || key == Key_F1) {
+
+ resetKeyboardVars();
+ // continue event processing by Qpopup
+ //e->ignore();
+ QPopupMenu::keyPressEvent(e);
+ return;
+ }
+
+ // check to see if the user wants to remove a key from the sequence (backspace)
+ // or clear the sequence (delete)
+ if (!d->keySeq.isNull()) {
+
+ if (key == Key_Backspace) {
+
+ if (d->keySeq.length() == 1) {
+ resetKeyboardVars();
+ return;
+ }
+
+ // keep the last sequence in keyString
+ keyString = d->keySeq.left(d->keySeq.length() - 1);
+
+ // allow sequence matching to be tried again
+ resetKeyboardVars();
+
+ } else if (key == Key_Delete) {
+ resetKeyboardVars();
+
+ // clear active item
+ setActiveItem(0);
+ return;
+
+ } else if (d->noMatches) {
+ // clear if there are no matches
+ resetKeyboardVars();
+
+ // clear active item
+ setActiveItem(0);
+
+ } else {
+ // the key sequence is not a null string
+ // therefore the lastHitIndex is valid
+ i = d->lastHitIndex;
+ }
+ } else if (key == Key_Backspace && parentMenu) {
+ // backspace with no chars in the buffer... go back a menu.
+ hide();
+ resetKeyboardVars();
+ return;
+ }
+
+ d->keySeq += keyString;
+ int seqLen = d->keySeq.length();
+
+ for (; i < (int)count(); i++) {
+ // compare typed text with text of this entry
+ int j = idAt(i);
+
+ // don't search disabled entries
+ if (!isItemEnabled(j))
+ continue;
+
+ QString thisText;
+
+ // retrieve the right text
+ // (the last selected item one may have additional ampersands)
+ if (i == d->lastHitIndex)
+ thisText = d->originalText;
+ else
+ thisText = text(j);
+
+ // if there is an accelerator present, remove it
+ if ((int)accel(j) != 0)
+ thisText = thisText.replace(QRegExp("&"), "");
+
+ // chop text to the search length
+ thisText = thisText.left(seqLen);
+
+ // do the search
+ if (thisText.find(d->keySeq, 0, false) == 0) {
+
+ if (firstpass) {
+ // match
+ setActiveItem(i);
+
+ // check to see if we're underlining a different item
+ if (d->lastHitIndex != i)
+ // yes; revert the underlining
+ changeItem(idAt(d->lastHitIndex), d->originalText);
+
+ // set the original text if it's a different item
+ if (d->lastHitIndex != i || d->lastHitIndex == -1)
+ d->originalText = text(j);
+
+ // underline the currently selected item
+ changeItem(j, underlineText(d->originalText, d->keySeq.length()));
+
+ // remeber what's going on
+ d->lastHitIndex = i;
+
+ // start/restart the clear timer
+ d->clearTimer.start(5000, true);
+
+ // go around for another try, to see if we can execute
+ firstpass = false;
+ } else {
+ // don't allow execution
+ return;
+ }
+ }
+
+ // fall through to allow execution
+ }
+
+ if (!firstpass) {
+ if (d->autoExec) {
+ // activate anything
+ activateItemAt(d->lastHitIndex);
+ resetKeyboardVars();
+
+ } else if (findItem(idAt(d->lastHitIndex)) &&
+ findItem(idAt(d->lastHitIndex))->popup()) {
+ // only activate sub-menus
+ activateItemAt(d->lastHitIndex);
+ resetKeyboardVars();
+ }
+
+ return;
+ }
+
+ // no matches whatsoever, clean up
+ resetKeyboardVars(true);
+ //e->ignore();
+ QPopupMenu::keyPressEvent(e);
+}
+
+QString OPopupMenu::underlineText(const QString& text, uint length)
+{
+ QString ret = text;
+ for (uint i = 0; i < length; i++) {
+ if (ret[2*i] != '&')
+ ret.insert(2*i, "&");
+ }
+ return ret;
+}
+
+void OPopupMenu::resetKeyboardVars(bool noMatches /* = false */)
+{
+ // Clean up keyboard variables
+ if (d->lastHitIndex != -1) {
+ changeItem(idAt(d->lastHitIndex), d->originalText);
+ d->lastHitIndex = -1;
+ }
+
+ if (!noMatches) {
+ d->keySeq = QString::null;
+ }
+
+ d->noMatches = noMatches;
+}
+
+void OPopupMenu::setKeyboardShortcutsEnabled(bool enable)
+{
+ d->shortcuts = enable;
+}
+
+void OPopupMenu::setKeyboardShortcutsExecute(bool enable)
+{
+ d->autoExec = enable;
+}
+/**
+ * End keyboard navigation.
+ */
+
+/**
+ * RMB menus on menus
+ */
+QPopupMenu* OPopupMenu::contextMenu()
+{
+ if (!d->m_ctxMenu)
+ {
+ d->m_ctxMenu = new QPopupMenu(this);
+ installEventFilter(this);
+ connect(d->m_ctxMenu, SIGNAL(aboutToHide()), this, SLOT(ctxMenuHiding()));
+ }
+
+ return d->m_ctxMenu;
+}
+
+void OPopupMenu::cancelContextMenuShow()
+{
+ OPopupMenuPrivate::s_continueCtxMenuShow = false;
+}
+
+int OPopupMenu::contextMenuFocusItem()
+{
+ return OPopupMenuPrivate::s_highlightedItem;
+}
+
+OPopupMenu* OPopupMenu::contextMenuFocus()
+{
+ return OPopupMenuPrivate::s_contextedMenu;
+}
+
+void OPopupMenu::itemHighlighted(int /* whichItem */)
+{
+ if (!d->m_ctxMenu || !d->m_ctxMenu->isVisible())
+ {
+ return;
+ }
+
+ d->m_ctxMenu->hide();
+ showCtxMenu(mapFromGlobal(QCursor::pos()));
+}
+
+void OPopupMenu::showCtxMenu(QPoint pos)
+{
+ OPopupMenuPrivate::s_highlightedItem = idAt(pos);
+
+ if (OPopupMenuPrivate::s_highlightedItem == -1)
+ {
+ OPopupMenuPrivate::s_contextedMenu = 0;
+ return;
+ }
+
+ emit aboutToShowContextMenu(this, OPopupMenuPrivate::s_highlightedItem, d->m_ctxMenu);
+
+ if (!OPopupMenuPrivate::s_continueCtxMenuShow)
+ {
+ OPopupMenuPrivate::s_continueCtxMenuShow = true;
+ return;
+ }
+
+ OPopupMenuPrivate::s_contextedMenu = this;
+ d->m_ctxMenu->popup(this->mapToGlobal(pos));
+ connect(this, SIGNAL(highlighted(int)), this, SLOT(itemHighlighted(int)));
+}
+
+void OPopupMenu::ctxMenuHiding()
+{
+ disconnect(this, SIGNAL(highlighted(int)), this, SLOT(itemHighlighted(int)));
+ OPopupMenuPrivate::s_continueCtxMenuShow = true;
+}
+
+bool OPopupMenu::eventFilter(QObject* obj, QEvent* event)
+{
+ if (d->m_ctxMenu && obj == this)
+ {
+ if (event->type() == QEvent::MouseButtonRelease)
+ {
+ if (d->m_ctxMenu->isVisible())
+ {
+ return true;
+ }
+ }
+ #if QT_VERSION > 290
+ else if (event->type() == QEvent::ContextMenu)
+ #else
+ else if ( (event->type() == QEvent::MouseButtonPress) &&
+ ( (QMouseEvent*) event )->button() == QMouseEvent::RightButton )
+ #endif
+ {
+ showCtxMenu(mapFromGlobal(QCursor::pos()));
+ return true;
+ }
+ }
+
+ return QWidget::eventFilter(obj, event);
+}
+
+void OPopupMenu::hideEvent(QHideEvent*)
+{
+ if (d->m_ctxMenu)
+ {
+ d->m_ctxMenu->hide();
+ }
+}
+/**
+ * end of RMB menus on menus support
+ */
+
+// Obsolete
+OPopupMenu::OPopupMenu(const QString& title, QWidget *parent, const char *name)
+ : QPopupMenu(parent, name)
+{
+ d = new OPopupMenuPrivate;
+ setTitle(title);
+}
+
+// Obsolete
+void OPopupMenu::setTitle(const QString &title)
+{
+ OPopupTitle *titleItem = new OPopupTitle();
+ titleItem->setTitle(title);
+ insertItem(titleItem);
+ d->m_lastTitle = title;
+}
+
+void OPopupTitle::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void OPopupMenu::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
diff --git a/libopie2/opieui/opopupmenu.h b/libopie2/opieui/opopupmenu.h
new file mode 100644
index 0000000..94f05f4
--- a/dev/null
+++ b/libopie2/opieui/opopupmenu.h
@@ -0,0 +1,256 @@
+/* This file is part of the ODE libraries
+ Copyright (C) 2000 Daniel M. Duley <mosfet@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 version 2 as published by the Free Software Foundation.
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#ifndef _OPOPUP_H
+#define _OPOPUP_H
+
+#define INCLUDE_MENUITEM_DEF
+
+/* QT */
+
+#include <qpopupmenu.h>
+
+/* OPIE */
+
+#include <opie2/opixmapeffect.h>
+
+/**
+ * Title widget for use in @ref OPopupMenu.
+ *
+ * You usually don't have to create this manually since
+ * @ref OPopupMenu::insertTitle will do it for you, but it is allowed if
+ * you wish to customize it's look.
+ *
+ * @author Daniel M. Duley <mosfet@kde.org>
+ * @short OPopupMenu title widget.
+ */
+class OPopupTitle : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a title widget with the user specified gradient, pixmap,
+ * and colors.
+ */
+ OPopupTitle(QWidget *parent=0, const char *name=0);
+ /**
+ * @deprecated
+ * Constructs a title widget with the specified gradient and colors.
+ */
+ OPopupTitle(OPixmapEffect::GradientType gradient, const QColor &color,
+ const QColor &textColor, QWidget *parent=0,
+ const char *name=0);
+ /**
+ * @deprecated
+ * Constructs a title widget with the specified pixmap and colors.
+ */
+ OPopupTitle(const OPixmap &background, const QColor &color,
+ const QColor &textColor, QWidget *parent=0,
+ const char *name=0);
+ /**
+ * Sets the title string and optional icon for the title widget.
+ *
+ * You will want to call this before inserting into a menu.
+ */
+ void setTitle(const QString &text, const QPixmap *icon=NULL);
+ /**
+ * Returns the current title.
+ */
+ QString title() const { return(titleStr); }
+ /**
+ * Returns the current icon.
+ */
+ QPixmap icon() const { return(miniicon); }
+
+ QSize sizeHint() const;
+
+public slots:
+ /// @since 3.1
+ void setText( const QString &text );
+ /// @since 3.1
+ void setIcon( const QPixmap &pix );
+
+protected:
+ void paintEvent(QPaintEvent *ev);
+
+ QString titleStr;
+ QPixmap miniicon;
+
+ // Remove in KDE4
+ OPixmapEffect::GradientType grType;
+ QPixmap fill;
+ QColor fgColor, bgColor, grHigh, grLow;
+ bool useGradient;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class OPopupTitlePrivate;
+ OPopupTitlePrivate *d;
+};
+
+/**
+ * OPopupMenu is a class for menus with standard title items and keyboard
+ * accessibility for popups with many options and/or varying options. It acts
+ * identically to QPopupMenu, with the addition of insertTitle(),
+ * changeTitle(), setKeyboardShortcutsEnabled() and
+ * setKeyboardShortcutsExecute() methods.
+ *
+ * The titles support a text string, an icon, plus user defined gradients,
+ * colors, and background pixmaps.
+ *
+ * The keyboard search algorithm is incremental with additional underlining
+ * for user feedback.
+ *
+ * @short A menu with title items.
+ * @author Daniel M. Duley <mosfet@kde.org>
+ * @author Hamish Rodda <meddie@yoyo.its.monash.edu.au>
+ */
+class OPopupMenu : public QPopupMenu {
+ Q_OBJECT
+public:
+ /**
+ * Constructs a OPopupMenu.
+ */
+ OPopupMenu(QWidget *parent=0, const char *name=0);
+
+ /**
+ * Destructs the object
+ */
+ ~OPopupMenu();
+
+ /**
+ * Inserts a title item with no icon.
+ */
+ int insertTitle(const QString &text, int id=-1, int index=-1);
+ /**
+ * Inserts a title item with the given icon and title.
+ */
+ int insertTitle(const QPixmap &icon, const QString &text, int id=-1,
+ int index=-1);
+ /**
+ * Changes the title of the item at the specified id. If a icon was
+ * previously set it is cleared.
+ */
+ void changeTitle(int id, const QString &text);
+ /**
+ * Changes the title and icon of the title item at the specified id.
+ */
+ void changeTitle(int id, const QPixmap &icon, const QString &text);
+ /**
+ * Returns the title of the title item at the specified id. The default
+ * id of -1 is for backwards compatibility only, you should always specify
+ * the id.
+ */
+ QString title(int id=-1) const;
+ /**
+ * Returns the icon of the title item at the specified id.
+ */
+ QPixmap titlePixmap(int id) const;
+
+ /**
+ * Enables keyboard navigation by searching for the entered key sequence.
+ * Also underlines the currently selected item, providing feedback on the search.
+ *
+ * Defaults to off.
+ *
+ * WARNING: calls to text() of currently keyboard-selected items will
+ * contain additional ampersand characters.
+ *
+ * WARNING: though pre-existing keyboard shortcuts will not interfere with the
+ * operation of this feature, they may be confusing to the user as the existing
+ * shortcuts will not work.
+ * @since 3.1
+ */
+ void setKeyboardShortcutsEnabled(bool enable);
+
+ /**
+ * Enables execution of the menu item once it is uniquely specified.
+ * Defaults to off.
+ * @since 3.1
+ */
+ void setKeyboardShortcutsExecute(bool enable);
+
+ /**
+ * Obsolete method provided for backwards compatibility only. Use the
+ * normal constructor and insertTitle instead.
+ */
+ OPopupMenu(const QString &title, QWidget *parent=0, const char *name=0);
+ /**
+ * Obsolete method provided for backwards compatibility only. Use
+ * insertTitle and changeTitle instead.
+ */
+ void setTitle(const QString &title);
+
+ /**
+ * Returns the context menu associated with this menu
+ * @since 3.2
+ */
+ QPopupMenu* contextMenu();
+
+ /**
+ * Hides the context menu if shown
+ * @since 3.2
+ */
+ void cancelContextMenuShow();
+
+ /**
+ * Returns the OPopupMenu associated with the current context menu
+ * @since 3.2
+ */
+ static OPopupMenu* contextMenuFocus();
+
+ /**
+ * returns the ID of the menuitem associated with the current context menu
+ * @since 3.2
+ */
+ static int contextMenuFocusItem();
+
+signals:
+ /**
+ * connect to this signal to be notified when a context menu is about to be shown
+ * @param menu The menu that the context menu is about to be shown for
+ * @param menuItem The menu item that the context menu is currently on
+ * @param ctxMenu The context menu itself
+ * @since 3.2
+ */
+ void aboutToShowContextMenu(OPopupMenu* menu, int menuItem, QPopupMenu* ctxMenu);
+
+protected:
+ virtual void closeEvent(QCloseEvent *);
+ virtual void keyPressEvent(QKeyEvent* e);
+ virtual bool eventFilter(QObject* obj, QEvent* event);
+ virtual void hideEvent(QHideEvent*);
+
+ virtual void virtual_hook( int id, void* data );
+
+protected slots:
+ /// @since 3.1
+ QString underlineText(const QString& text, uint length);
+ /// @since 3.1
+ void resetKeyboardVars(bool noMatches = false);
+ void itemHighlighted(int whichItem);
+ void showCtxMenu(QPoint pos);
+ void ctxMenuHiding();
+
+private:
+ class OPopupMenuPrivate;
+ OPopupMenuPrivate *d;
+};
+
+#endif
diff --git a/libopie2/opieui/oselector.cpp b/libopie2/opieui/oselector.cpp
new file mode 100644
index 0000000..ec5af6b
--- a/dev/null
+++ b/libopie2/opieui/oselector.cpp
@@ -0,0 +1,716 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Martin Jones (mjones@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/* QT */
+
+#include <qimage.h>
+#include <qpainter.h>
+#include <qdrawutil.h>
+
+/* OPIE */
+
+#include <opie2/oimageeffect.h>
+#include <opie2/oselector.h>
+
+#define STORE_W 8
+#define STORE_W2 STORE_W * 2
+
+//-----------------------------------------------------------------------------
+/*
+ * 2D value selector.
+ * The contents of the selector are drawn by derived class.
+ */
+
+OXYSelector::OXYSelector( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ xPos = 0;
+ yPos = 0;
+ minX = 0;
+ minY = 0;
+ maxX = 100;
+ maxY = 100;
+ store.setOptimization( QPixmap::BestOptim );
+ store.resize( STORE_W2, STORE_W2 );
+}
+
+
+OXYSelector::~OXYSelector()
+{}
+
+
+void OXYSelector::setRange( int _minX, int _minY, int _maxX, int _maxY )
+{
+ px = 2;
+ py = 2;
+ minX = _minX;
+ minY = _minY;
+ maxX = _maxX;
+ maxY = _maxY;
+}
+
+void OXYSelector::setValues( int _xPos, int _yPos )
+{
+ xPos = _xPos;
+ yPos = _yPos;
+
+ if ( xPos > maxX )
+ xPos = maxX;
+ else if ( xPos < minX )
+ xPos = minX;
+
+ if ( yPos > maxY )
+ yPos = maxY;
+ else if ( yPos < minY )
+ yPos = minY;
+
+ int xp = 2 + (width() - 4) * xPos / (maxX - minX);
+ int yp = height() - 2 - (height() - 4) * yPos / (maxY - minY);
+
+ setPosition( xp, yp );
+}
+
+QRect OXYSelector::contentsRect() const
+{
+ return QRect( 2, 2, width()-4, height()-4 );
+}
+
+void OXYSelector::paintEvent( QPaintEvent *ev )
+{
+ QRect cursorRect( px - STORE_W, py - STORE_W, STORE_W2, STORE_W2);
+ QRect paintRect = ev->rect();
+
+ QPainter painter;
+ painter.begin( this );
+
+ QBrush brush;
+ qDrawShadePanel( &painter, 0, 0, width(), height(), colorGroup(),
+ TRUE, 2, &brush );
+
+ drawContents( &painter );
+ if (paintRect.contains(cursorRect))
+ {
+ bitBlt( &store, 0, 0, this, px - STORE_W, py - STORE_W,
+ STORE_W2, STORE_W2, CopyROP );
+ drawCursor( &painter, px, py );
+ }
+ else if (paintRect.intersects(cursorRect))
+ {
+ repaint( cursorRect, false);
+ }
+
+ painter.end();
+}
+
+void OXYSelector::mousePressEvent( QMouseEvent *e )
+{
+ int xVal, yVal;
+ valuesFromPosition( e->pos().x() - 2, e->pos().y() - 2, xVal, yVal );
+ setValues( xVal, yVal );
+
+ emit valueChanged( xPos, yPos );
+}
+
+void OXYSelector::mouseMoveEvent( QMouseEvent *e )
+{
+ int xVal, yVal;
+ valuesFromPosition( e->pos().x() - 2, e->pos().y() - 2, xVal, yVal );
+ setValues( xVal, yVal );
+
+ emit valueChanged( xPos, yPos );
+}
+
+void OXYSelector::wheelEvent( QWheelEvent *e )
+{
+ #if QT_VERSION > 290
+ if ( e->orientation() == Qt::Horizontal )
+ setValues( xValue() + e->delta()/120, yValue() );
+ else
+ setValues( xValue(), yValue() + e->delta()/120 );
+
+ emit valueChanged( xPos, yPos );
+ #endif
+}
+
+void OXYSelector::valuesFromPosition( int x, int y, int &xVal, int &yVal ) const
+{
+ xVal = ( (maxX-minX) * (x-2) ) / ( width()-4 );
+ yVal = maxY - ( ( (maxY-minY) * (y-2) ) / ( height()-4 ) );
+
+ if ( xVal > maxX )
+ xVal = maxX;
+ else if ( xVal < minX )
+ xVal = minX;
+
+ if ( yVal > maxY )
+ yVal = maxY;
+ else if ( yVal < minY )
+ yVal = minY;
+}
+
+void OXYSelector::setPosition( int xp, int yp )
+{
+ if ( xp < 2 )
+ xp = 2;
+ else if ( xp > width() - 2 )
+ xp = width() - 2;
+
+ if ( yp < 2 )
+ yp = 2;
+ else if ( yp > height() - 2 )
+ yp = height() - 2;
+
+ QPainter painter;
+ painter.begin( this );
+
+ bitBlt( this, px - STORE_W, py - STORE_W, &store, 0, 0,
+ STORE_W2, STORE_W2, CopyROP );
+ bitBlt( &store, 0, 0, this, xp - STORE_W, yp - STORE_W,
+ STORE_W2, STORE_W2, CopyROP );
+ drawCursor( &painter, xp, yp );
+ px = xp;
+ py = yp;
+
+ painter.end();
+}
+
+void OXYSelector::drawContents( QPainter * )
+{}
+
+
+void OXYSelector::drawCursor( QPainter *p, int xp, int yp )
+{
+ p->setPen( QPen( white ) );
+
+ p->drawLine( xp - 6, yp - 6, xp - 2, yp - 2 );
+ p->drawLine( xp - 6, yp + 6, xp - 2, yp + 2 );
+ p->drawLine( xp + 6, yp - 6, xp + 2, yp - 2 );
+ p->drawLine( xp + 6, yp + 6, xp + 2, yp + 2 );
+}
+
+//-----------------------------------------------------------------------------
+/*
+ * 1D value selector with contents drawn by derived class.
+ * See OColorDialog for example.
+ */
+
+
+OSelector::OSelector( QWidget *parent, const char *name )
+ : QWidget( parent, name ), QRangeControl()
+{
+ _orientation = Horizontal;
+ _indent = TRUE;
+}
+
+OSelector::OSelector( Orientation o, QWidget *parent, const char *name )
+ : QWidget( parent, name ), QRangeControl()
+{
+ _orientation = o;
+ _indent = TRUE;
+}
+
+
+OSelector::~OSelector()
+{}
+
+
+QRect OSelector::contentsRect() const
+{
+ if ( orientation() == Vertical )
+ return QRect( 2, 5, width()-9, height()-10 );
+ else
+ return QRect( 5, 2, width()-10, height()-9 );
+}
+
+void OSelector::paintEvent( QPaintEvent * )
+{
+ QPainter painter;
+
+ painter.begin( this );
+
+ drawContents( &painter );
+
+ QBrush brush;
+
+ if ( indent() )
+ {
+ if ( orientation() == Vertical )
+ qDrawShadePanel( &painter, 0, 3, width()-5, height()-6,
+ colorGroup(), TRUE, 2, &brush );
+ else
+ qDrawShadePanel( &painter, 3, 0, width()-6, height()-5,
+ colorGroup(), TRUE, 2, &brush );
+ }
+
+ QPoint pos = calcArrowPos( value() );
+ drawArrow( &painter, TRUE, pos );
+
+ painter.end();
+}
+
+void OSelector::mousePressEvent( QMouseEvent *e )
+{
+ moveArrow( e->pos() );
+}
+
+void OSelector::mouseMoveEvent( QMouseEvent *e )
+{
+ moveArrow( e->pos() );
+}
+
+void OSelector::wheelEvent( QWheelEvent *e )
+{
+ int val = value() + e->delta()/120;
+ emit valueChanged( val );
+ setValue( val );
+}
+
+void OSelector::valueChange()
+{
+ QPainter painter;
+ QPoint pos;
+
+ painter.begin( this );
+
+ pos = calcArrowPos( prevValue() );
+ drawArrow( &painter, FALSE, pos );
+
+ pos = calcArrowPos( value() );
+ drawArrow( &painter, TRUE, pos );
+
+ painter.end();
+}
+
+void OSelector::moveArrow( const QPoint &pos )
+{
+ int val;
+
+ if ( orientation() == Vertical )
+ val = ( maxValue() - minValue() ) * (height()-pos.y()-3)
+ / (height()-10) + minValue();
+ else
+ val = ( maxValue() - minValue() ) * (width()-pos.x()-3)
+ / (width()-10) + minValue();
+
+ if ( val > maxValue() )
+ val = maxValue();
+ if ( val < minValue() )
+ val = minValue();
+
+ emit valueChanged( val );
+ setValue( val );
+}
+
+QPoint OSelector::calcArrowPos( int val )
+{
+ QPoint p;
+
+ if ( orientation() == Vertical )
+ {
+ p.setY( height() - ( (height()-10) * val
+ / ( maxValue() - minValue() ) + 5 ) );
+ p.setX( width() - 5 );
+ }
+ else
+ {
+ p.setX( width() - ( (width()-10) * val
+ / ( maxValue() - minValue() ) + 5 ) );
+ p.setY( height() - 5 );
+ }
+
+ return p;
+}
+
+void OSelector::drawContents( QPainter * )
+{}
+
+void OSelector::drawArrow( QPainter *painter, bool show, const QPoint &pos )
+{
+ if ( show )
+ {
+ QPointArray array(3);
+
+ painter->setPen( QPen() );
+ painter->setBrush( QBrush( colorGroup().buttonText() ) );
+ if ( orientation() == Vertical )
+ {
+ array.setPoint( 0, pos.x()+0, pos.y()+0 );
+ array.setPoint( 1, pos.x()+5, pos.y()+5 );
+ array.setPoint( 2, pos.x()+5, pos.y()-5 );
+ }
+ else
+ {
+ array.setPoint( 0, pos.x()+0, pos.y()+0 );
+ array.setPoint( 1, pos.x()+5, pos.y()+5 );
+ array.setPoint( 2, pos.x()-5, pos.y()+5 );
+ }
+
+ painter->drawPolygon( array );
+ }
+ else
+ {
+ if ( orientation() == Vertical )
+ {
+ repaint(pos.x(), pos.y()-5, 6, 11, true);
+ }
+ else
+ {
+ repaint(pos.x()-5, pos.y(), 11, 6, true);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+OGradientSelector::OGradientSelector( QWidget *parent, const char *name )
+ : OSelector( parent, name )
+{
+ init();
+}
+
+
+OGradientSelector::OGradientSelector( Orientation o, QWidget *parent,
+ const char *name )
+ : OSelector( o, parent, name )
+{
+ init();
+}
+
+
+OGradientSelector::~OGradientSelector()
+{}
+
+
+void OGradientSelector::init()
+{
+ color1.setRgb( 0, 0, 0 );
+ color2.setRgb( 255, 255, 255 );
+
+ text1 = text2 = "";
+}
+
+
+void OGradientSelector::drawContents( QPainter *painter )
+{
+ QImage image( contentsRect().width(), contentsRect().height(), 32 );
+
+ QColor col;
+ float scale;
+
+ int redDiff = color2.red() - color1.red();
+ int greenDiff = color2.green() - color1.green();
+ int blueDiff = color2.blue() - color1.blue();
+
+ if ( orientation() == Vertical )
+ {
+ for ( int y = 0; y < image.height(); y++ )
+ {
+ scale = 1.0 * y / image.height();
+ col.setRgb( color1.red() + int(redDiff*scale),
+ color1.green() + int(greenDiff*scale),
+ color1.blue() + int(blueDiff*scale) );
+
+ unsigned int *p = (uint *) image.scanLine( y );
+ for ( int x = 0; x < image.width(); x++ )
+ *p++ = col.rgb();
+ }
+ }
+ else
+ {
+ unsigned int *p = (uint *) image.scanLine( 0 );
+
+ for ( int x = 0; x < image.width(); x++ )
+ {
+ scale = 1.0 * x / image.width();
+ col.setRgb( color1.red() + int(redDiff*scale),
+ color1.green() + int(greenDiff*scale),
+ color1.blue() + int(blueDiff*scale) );
+ *p++ = col.rgb();
+ }
+
+ for ( int y = 1; y < image.height(); y++ )
+ memcpy( image.scanLine( y ), image.scanLine( y - 1),
+ sizeof( unsigned int ) * image.width() );
+ }
+
+ QColor ditherPalette[8];
+
+ for ( int s = 0; s < 8; s++ )
+ ditherPalette[s].setRgb( color1.red() + redDiff * s / 8,
+ color1.green() + greenDiff * s / 8,
+ color1.blue() + blueDiff * s / 8 );
+
+ OImageEffect::dither( image, ditherPalette, 8 );
+
+ QPixmap p;
+ p.convertFromImage( image );
+
+ painter->drawPixmap( contentsRect().x(), contentsRect().y(), p );
+
+ if ( orientation() == Vertical )
+ {
+ int yPos = contentsRect().top() + painter->fontMetrics().ascent() + 2;
+ int xPos = contentsRect().left() + (contentsRect().width() -
+ painter->fontMetrics().width( text2 )) / 2;
+ QPen pen( color2 );
+ painter->setPen( pen );
+ painter->drawText( xPos, yPos, text2 );
+
+ yPos = contentsRect().bottom() - painter->fontMetrics().descent() - 2;
+ xPos = contentsRect().left() + (contentsRect().width() -
+ painter->fontMetrics().width( text1 )) / 2;
+ pen.setColor( color1 );
+ painter->setPen( pen );
+ painter->drawText( xPos, yPos, text1 );
+ }
+ else
+ {
+ int yPos = contentsRect().bottom()-painter->fontMetrics().descent()-2;
+
+ QPen pen( color2 );
+ painter->setPen( pen );
+ painter->drawText( contentsRect().left() + 2, yPos, text1 );
+
+ pen.setColor( color1 );
+ painter->setPen( pen );
+ painter->drawText( contentsRect().right() -
+ painter->fontMetrics().width( text2 ) - 2, yPos, text2 );
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+static QColor *standardPalette = 0;
+
+#define STANDARD_PAL_SIZE 17
+
+OColor::OColor()
+: QColor()
+{
+ r = 0; g = 0; b = 0; h = 0; s = 0; v = 0;
+};
+
+OColor::OColor( const OColor &col)
+: QColor( col )
+{
+ h = col.h; s = col.s; v = col.v;
+ r = col.r; g = col.g; b = col.b;
+};
+
+OColor::OColor( const QColor &col)
+: QColor( col )
+{
+ QColor::rgb(&r, &g, &b);
+ QColor::hsv(&h, &s, &v);
+};
+
+bool OColor::operator==(const OColor& col) const
+{
+ return (h == col.h) && (s == col.s) && (v == col.v) &&
+ (r == col.r) && (g == col.g) && (b == col.b);
+}
+
+OColor& OColor::operator=(const OColor& col)
+{
+ *(QColor *)this = col;
+ h = col.h; s = col.s; v = col.v;
+ r = col.r; g = col.g; b = col.b;
+ return *this;
+}
+
+void
+OColor::setHsv(int _h, int _s, int _v)
+{
+ h = _h; s = _s; v = _v;
+ QColor::setHsv(h, s, v);
+ QColor::rgb(&r, &g, &b);
+};
+
+void
+OColor::setRgb(int _r, int _g, int _b)
+{
+ r = _r; g = _g; b = _b;
+ QColor::setRgb(r, g, b);
+ QColor::hsv(&h, &s, &v);
+}
+
+void
+OColor::rgb(int *_r, int *_g, int *_b) const
+{
+ *_r = r; *_g = g; *_b = b;
+}
+
+void
+OColor::hsv(int *_h, int *_s, int *_v) const
+{
+ *_h = h; *_s = s; *_v = v;
+}
+
+static void createStandardPalette()
+{
+ if ( standardPalette )
+ return;
+
+ standardPalette = new QColor[STANDARD_PAL_SIZE];
+
+ int i = 0;
+
+ standardPalette[i++] = Qt::red;
+ standardPalette[i++] = Qt::green;
+ standardPalette[i++] = Qt::blue;
+ standardPalette[i++] = Qt::cyan;
+ standardPalette[i++] = Qt::magenta;
+ standardPalette[i++] = Qt::yellow;
+ standardPalette[i++] = Qt::darkRed;
+ standardPalette[i++] = Qt::darkGreen;
+ standardPalette[i++] = Qt::darkBlue;
+ standardPalette[i++] = Qt::darkCyan;
+ standardPalette[i++] = Qt::darkMagenta;
+ standardPalette[i++] = Qt::darkYellow;
+ standardPalette[i++] = Qt::white;
+ standardPalette[i++] = Qt::lightGray;
+ standardPalette[i++] = Qt::gray;
+ standardPalette[i++] = Qt::darkGray;
+ standardPalette[i++] = Qt::black;
+}
+
+
+OHSSelector::OHSSelector( QWidget *parent, const char *name )
+ : OXYSelector( parent, name )
+{
+ setRange( 0, 0, 359, 255 );
+}
+
+void OHSSelector::updateContents()
+{
+ drawPalette(&pixmap);
+}
+
+void OHSSelector::resizeEvent( QResizeEvent * )
+{
+ updateContents();
+}
+
+void OHSSelector::drawContents( QPainter *painter )
+{
+ painter->drawPixmap( contentsRect().x(), contentsRect().y(), pixmap );
+}
+
+void OHSSelector::drawPalette( QPixmap *pixmap )
+{
+ int xSize = contentsRect().width(), ySize = contentsRect().height();
+ QImage image( xSize, ySize, 32 );
+ QColor col;
+ int h, s;
+ uint *p;
+
+ for ( s = ySize-1; s >= 0; s-- )
+ {
+ p = (uint *) image.scanLine( ySize - s - 1 );
+ for( h = 0; h < xSize; h++ )
+ {
+ col.setHsv( 359*h/(xSize-1), 255*s/(ySize-1), 192 );
+ *p = col.rgb();
+ p++;
+ }
+ }
+
+ if ( QColor::numBitPlanes() <= 8 )
+ {
+ createStandardPalette();
+ OImageEffect::dither( image, standardPalette, STANDARD_PAL_SIZE );
+ }
+ pixmap->convertFromImage( image );
+}
+
+
+//-----------------------------------------------------------------------------
+
+OValueSelector::OValueSelector( QWidget *parent, const char *name )
+ : OSelector( OSelector::Vertical, parent, name ), _hue(0), _sat(0)
+{
+ setRange( 0, 255 );
+ pixmap.setOptimization( QPixmap::BestOptim );
+}
+
+OValueSelector::OValueSelector(Orientation o, QWidget *parent, const char *name
+ )
+ : OSelector( o, parent, name), _hue(0), _sat(0)
+{
+ setRange( 0, 255 );
+ pixmap.setOptimization( QPixmap::BestOptim );
+}
+
+void OValueSelector::updateContents()
+{
+ drawPalette(&pixmap);
+}
+
+void OValueSelector::resizeEvent( QResizeEvent * )
+{
+ updateContents();
+}
+
+void OValueSelector::drawContents( QPainter *painter )
+{
+ painter->drawPixmap( contentsRect().x(), contentsRect().y(), pixmap );
+}
+
+void OValueSelector::drawPalette( QPixmap *pixmap )
+{
+ int xSize = contentsRect().width(), ySize = contentsRect().height();
+ QImage image( xSize, ySize, 32 );
+ QColor col;
+ uint *p;
+ QRgb rgb;
+
+ if ( orientation() == OSelector::Horizontal )
+ {
+ for ( int v = 0; v < ySize; v++ )
+ {
+ p = (uint *) image.scanLine( ySize - v - 1 );
+
+ for( int x = 0; x < xSize; x++ )
+ {
+ col.setHsv( _hue, _sat, 255*x/(xSize-1) );
+ rgb = col.rgb();
+ *p++ = rgb;
+ }
+ }
+ }
+
+ if( orientation() == OSelector::Vertical )
+ {
+ for ( int v = 0; v < ySize; v++ )
+ {
+ p = (uint *) image.scanLine( ySize - v - 1 );
+ col.setHsv( _hue, _sat, 255*v/(ySize-1) );
+ rgb = col.rgb();
+ for ( int i = 0; i < xSize; i++ )
+ *p++ = rgb;
+ }
+ }
+
+ if ( QColor::numBitPlanes() <= 8 )
+ {
+ createStandardPalette();
+ OImageEffect::dither( image, standardPalette, STANDARD_PAL_SIZE );
+ }
+ pixmap->convertFromImage( image );
+}
diff --git a/libopie2/opieui/oselector.h b/libopie2/opieui/oselector.h
new file mode 100644
index 0000000..f832239
--- a/dev/null
+++ b/libopie2/opieui/oselector.h
@@ -0,0 +1,518 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Martin Jones (mjones@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+//-----------------------------------------------------------------------------
+// Selector widgets for KDE Color Selector, but probably useful for other
+// stuff also.
+
+#ifndef __OSELECT_H__
+#define __OSELECT_H__
+
+#include <qwidget.h>
+#include <qrangecontrol.h>
+#include <qpixmap.h>
+
+/**
+ * OXYSelector is the base class for other widgets which
+ * provides the ability to choose from a two-dimensional
+ * range of values. The currently chosen value is indicated
+ * by a cross. An example is the @ref OHSSelector which
+ * allows to choose from a range of colors, and which is
+ * used in OColorDialog.
+ *
+ * A custom drawing routine for the widget surface has
+ * to be provided by the subclass.
+ */
+class OXYSelector : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a two-dimensional selector widget which
+ * has a value range of [0..100] in both directions.
+ */
+ OXYSelector( QWidget *parent=0, const char *name=0 );
+ /**
+ * Destructs the widget.
+ */
+ ~OXYSelector();
+
+ /**
+ * Sets the current values in horizontal and
+ * vertical direction.
+ */
+ void setValues( int xPos, int yPos );
+ /**
+ * Sets the range of possible values.
+ */
+ void setRange( int minX, int minY, int maxX, int maxY );
+
+ /**
+ * @return the current value in horizontal direction.
+ */
+ int xValue() const { return xPos; }
+ /**
+ * @return the current value in vertical direction.
+ */
+ int yValue() const { return yPos; }
+
+ /**
+ * @return the rectangle on which subclasses should draw.
+ */
+ QRect contentsRect() const;
+
+signals:
+ /**
+ * This signal is emitted whenever the user chooses a value,
+ * e.g. by clicking with the mouse on the widget.
+ */
+ void valueChanged( int x, int y );
+
+protected:
+ /**
+ * Override this function to draw the contents of the widget.
+ * The default implementation does nothing.
+ *
+ * Draw within @ref contentsRect() only.
+ */
+ virtual void drawContents( QPainter * );
+ /**
+ * Override this function to draw the cursor which
+ * indicates the currently selected value pair.
+ */
+ virtual void drawCursor( QPainter *p, int xp, int yp );
+ /**
+ * @reimplemented
+ */
+ virtual void paintEvent( QPaintEvent *e );
+ /**
+ * @reimplemented
+ */
+ virtual void mousePressEvent( QMouseEvent *e );
+ /**
+ * @reimplemented
+ */
+ virtual void mouseMoveEvent( QMouseEvent *e );
+ /**
+ * @reimplemented
+ */
+ virtual void wheelEvent( QWheelEvent * );
+ /**
+ * Converts a pixel position to its corresponding values.
+ */
+ void valuesFromPosition( int x, int y, int& xVal, int& yVal ) const;
+
+private:
+ void setPosition( int xp, int yp );
+ int px;
+ int py;
+ int xPos;
+ int yPos;
+ int minX;
+ int maxX;
+ int minY;
+ int maxY;
+ QPixmap store;
+
+private:
+ class OXYSelectorPrivate;
+ OXYSelectorPrivate *d;
+};
+
+
+/**
+ * OSelector is the base class for other widgets which
+ * provides the ability to choose from a one-dimensional
+ * range of values. An example is the @ref OGradientSelector
+ * which allows to choose from a range of colors.
+ *
+ * A custom drawing routine for the widget surface has
+ * to be provided by the subclass.
+ */
+class OSelector : public QWidget, public QRangeControl
+{
+ Q_OBJECT
+ Q_PROPERTY( int value READ value WRITE setValue )
+ Q_PROPERTY( int minValue READ minValue WRITE setMinValue )
+ Q_PROPERTY( int maxValue READ maxValue WRITE setMaxValue )
+public:
+
+ /**
+ * Constructs a horizontal one-dimensional selection widget.
+ */
+ OSelector( QWidget *parent=0, const char *name=0 );
+ /**
+ * Constructs a one-dimensional selection widget with
+ * a given orientation.
+ */
+ OSelector( Orientation o, QWidget *parent = 0L, const char *name = 0L );
+ /*
+ * Destructs the widget.
+ */
+ ~OSelector();
+
+ /**
+ * @return the orientation of the widget.
+ */
+ Orientation orientation() const
+ { return _orientation; }
+
+ /**
+ * @return the rectangle on which subclasses should draw.
+ */
+ QRect contentsRect() const;
+
+ /**
+ * Sets the indent option of the widget to i.
+ * This determines whether a shaded frame is drawn.
+ */
+ void setIndent( bool i )
+ { _indent = i; }
+ /**
+ * @return whether the indent option is set.
+ */
+ bool indent() const
+ { return _indent; }
+
+ /**
+ * Sets the value.
+ */
+ void setValue(int value)
+ { QRangeControl::setValue(value); }
+
+ /**
+ * @returns the value.
+ */
+ int value() const
+ { return QRangeControl::value(); }
+
+ /**
+ * Sets the min value.
+ */
+ #if ( QT_VERSION > 290 )
+ void setMinValue(int value) { QRangeControl::setMinValue(value); }
+ #else
+ void setMinValue(int value) { QRangeControl::setRange(value,QRangeControl::maxValue()); }
+ #endif
+
+ /**
+ * @return the min value.
+ */
+ int minValue() const
+ { return QRangeControl::minValue(); }
+
+ /**
+ * Sets the max value.
+ */
+ #if ( QT_VERSION > 290 )
+ void setMaxValue(int value) { QRangeControl::setMaxValue(value); }
+ #else
+ void setMaxValue(int value) { QRangeControl::setRange(QRangeControl::minValue(),value); }
+ #endif
+
+ /**
+ * @return the max value.
+ */
+ int maxValue() const
+ { return QRangeControl::maxValue(); }
+
+signals:
+ /**
+ * This signal is emitted whenever the user chooses a value,
+ * e.g. by clicking with the mouse on the widget.
+ */
+ void valueChanged( int value );
+
+protected:
+ /**
+ * Override this function to draw the contents of the control.
+ * The default implementation does nothing.
+ *
+ * Draw only within contentsRect().
+ */
+ virtual void drawContents( QPainter * );
+ /**
+ * Override this function to draw the cursor which
+ * indicates the current value. This function is
+ * always called twice, once with argument show=false
+ * to clear the old cursor, once with argument show=true
+ * to draw the new one.
+ */
+ virtual void drawArrow( QPainter *painter, bool show, const QPoint &pos );
+
+ /**
+ * @reimplemented
+ */
+ virtual void valueChange();
+ /**
+ * @reimplemented
+ */
+ virtual void paintEvent( QPaintEvent * );
+ /**
+ * @reimplemented
+ */
+ virtual void mousePressEvent( QMouseEvent *e );
+ /**
+ * @reimplemented
+ */
+ virtual void mouseMoveEvent( QMouseEvent *e );
+ /**
+ * @reimplemented
+ */
+ virtual void wheelEvent( QWheelEvent * );
+
+private:
+ QPoint calcArrowPos( int val );
+ void moveArrow( const QPoint &pos );
+
+ Orientation _orientation;
+ bool _indent;
+
+private:
+ class OSelectorPrivate;
+ OSelectorPrivate *d;
+};
+
+
+/**
+ * The OGradientSelector widget allows the user to choose
+ * from a one-dimensional range of colors which is given as a
+ * gradient between two colors provided by the programmer.
+ */
+class OGradientSelector : public OSelector
+{
+ Q_OBJECT
+
+ Q_PROPERTY( QColor firstColor READ firstColor WRITE setFirstColor )
+ Q_PROPERTY( QColor secondColor READ secondColor WRITE setSecondColor )
+ Q_PROPERTY( QString firstText READ firstText WRITE setFirstText )
+ Q_PROPERTY( QString secondText READ secondText WRITE setSecondText )
+
+public:
+ /**
+ * Constructs a horizontal color selector which
+ * contains a gradient between white and black.
+ */
+ OGradientSelector( QWidget *parent=0, const char *name=0 );
+ /**
+ * Constructs a colors selector with orientation o which
+ * contains a gradient between white and black.
+ */
+ OGradientSelector( Orientation o, QWidget *parent=0, const char *name=0 );
+ /**
+ * Destructs the widget.
+ */
+ ~OGradientSelector();
+ /**
+ * Sets the two colors which span the gradient.
+ */
+ void setColors( const QColor &col1, const QColor &col2 )
+ { color1 = col1; color2 = col2; update();}
+ void setText( const QString &t1, const QString &t2 )
+ { text1 = t1; text2 = t2; update(); }
+
+ /**
+ * Set each color on its own.
+ */
+ void setFirstColor( const QColor &col )
+ { color1 = col; update(); }
+ void setSecondColor( const QColor &col )
+ { color2 = col; update(); }
+
+ /**
+ * Set each description on its own
+ */
+ void setFirstText( const QString &t )
+ { text1 = t; update(); }
+ void setSecondText( const QString &t )
+ { text2 = t; update(); }
+
+ const QColor firstColor() const
+ { return color1; }
+ const QColor secondColor() const
+ { return color2; }
+
+ const QString firstText() const
+ { return text1; }
+ const QString secondText() const
+ { return text2; }
+
+protected:
+ /**
+ * @reimplemented
+ */
+ virtual void drawContents( QPainter * );
+
+ /**
+ * @reimplemented
+ */
+ virtual QSize minimumSize() const
+ { return sizeHint(); }
+
+private:
+ void init();
+ QColor color1;
+ QColor color2;
+ QString text1;
+ QString text2;
+
+private:
+ class OGradientSelectorPrivate;
+ OGradientSelectorPrivate *d;
+};
+
+/**
+ * Widget for Hue/Saturation selection.
+ * The actual values can be fetched using the inherited xValue and yValue
+ * methods.
+ *
+ * @see OXYSelector, OValueSelector, OColorDialog
+ * @author Martin Jones (mjones@kde.org)
+ * @version $Id$
+*/
+class OHSSelector : public OXYSelector
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a hue/saturation selection widget.
+ */
+ OHSSelector( QWidget *parent=0, const char *name=0 );
+
+protected:
+ /**
+ * Draws the contents of the widget on a pixmap,
+ * which is used for buffering.
+ */
+ virtual void drawPalette( QPixmap *pixmap );
+ /**
+ * @reimplemented
+ */
+ virtual void resizeEvent( QResizeEvent * );
+ /**
+ * Reimplemented from OXYSelector. This drawing is
+ * buffered in a pixmap here. As real drawing
+ * routine, drawPalette() is used.
+ */
+ virtual void drawContents( QPainter *painter );
+
+private:
+ void updateContents();
+ QPixmap pixmap;
+
+private:
+ class OHSSelectorPrivate;
+ OHSSelectorPrivate *d;
+};
+
+
+class OValueSelectorPrivate;
+/**
+ * Widget for color value selection.
+ *
+ * @see OHSSelector, OColorDialog
+ * @author Martin Jones (mjones@kde.org)
+ * @version $Id$
+ */
+class OValueSelector : public OSelector
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a widget for color selection.
+ */
+ OValueSelector( QWidget *parent=0, const char *name=0 );
+ /**
+ * Constructs a widget for color selection with a given orientation
+ */
+ OValueSelector( Orientation o, QWidget *parent = 0, const char *name = 0 );
+
+ int hue() const
+ { return _hue; }
+ void setHue( int h )
+ { _hue = h; }
+ int saturation() const
+ { return _sat; }
+ void setSaturation( int s )
+ { _sat = s; }
+
+ void updateContents();
+protected:
+ /**
+ * Draws the contents of the widget on a pixmap,
+ * which is used for buffering.
+ */
+ virtual void drawPalette( QPixmap *pixmap );
+ /**
+ * @reimplemented
+ */
+ virtual void resizeEvent( QResizeEvent * );
+ /**
+ * Reimplemented from OSelector. The drawing is
+ * buffered in a pixmap here. As real drawing
+ * routine, drawPalette() is used.
+ */
+ virtual void drawContents( QPainter *painter );
+
+private:
+ int _hue;
+ int _sat;
+ QPixmap pixmap;
+
+private:
+ class OValueSelectorPrivate;
+ OValueSelectorPrivate *d;
+};
+
+
+class OColor : public QColor
+{
+public:
+ OColor();
+ OColor( const OColor &col);
+ OColor( const QColor &col);
+
+ OColor& operator=( const OColor& col);
+
+ bool operator==( const OColor& col) const;
+
+ void setHsv(int _h, int _s, int _v);
+ void setRgb(int _r, int _g, int _b);
+
+ void rgb(int *_r, int *_g, int *_b) const;
+ void hsv(int *_h, int *_s, int *_v) const;
+protected:
+ int h;
+ int s;
+ int v;
+ int r;
+ int g;
+ int b;
+
+private:
+ class OColorPrivate;
+ OColorPrivate *d;
+};
+
+
+
+#endif // __OSELECT_H__
+
diff --git a/libopie2/opieui/oseparator.cpp b/libopie2/opieui/oseparator.cpp
new file mode 100644
index 0000000..85181dc
--- a/dev/null
+++ b/libopie2/opieui/oseparator.cpp
@@ -0,0 +1,128 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ Copyright (C) 1997 Michael Roth <mroth@wirlweb.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* QT */
+
+#include <qstyle.h>
+
+/* OPIE */
+
+#include <opie2/oseparator.h>
+
+OSeparator::OSeparator(QWidget* parent, const char* name, WFlags f)
+ : QFrame(parent, name, f)
+{
+ setLineWidth(1);
+ setMidLineWidth(0);
+ setOrientation( HLine );
+}
+
+
+
+OSeparator::OSeparator(int orientation, QWidget* parent, const char* name, WFlags f)
+ : QFrame(parent, name, f)
+{
+ setLineWidth(1);
+ setMidLineWidth(0);
+ setOrientation( orientation );
+}
+
+
+
+void OSeparator::setOrientation(int orientation)
+{
+ switch(orientation)
+ {
+ case Vertical:
+ case VLine:
+ setFrameStyle( QFrame::VLine | QFrame::Sunken );
+ setMinimumSize(2, 0);
+ break;
+
+ default:
+ qWarning( "OSeparator::setOrientation(): invalid orientation, using default orientation HLine" );
+
+ case Horizontal:
+ case HLine:
+ setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ setMinimumSize(0, 2);
+ break;
+ }
+}
+
+
+
+int OSeparator::orientation() const
+{
+ if ( frameStyle() & VLine )
+ return VLine;
+
+ if ( frameStyle() & HLine )
+ return HLine;
+
+ return 0;
+}
+
+void OSeparator::drawFrame(QPainter *p)
+{
+ QPoint p1, p2;
+ QRect r = frameRect();
+ const QColorGroup & g = colorGroup();
+
+ if ( frameStyle() & HLine ) {
+ p1 = QPoint( r.x(), r.height()/2 );
+ p2 = QPoint( r.x()+r.width(), p1.y() );
+ }
+ else {
+ p1 = QPoint( r.x()+r.width()/2, 0 );
+ p2 = QPoint( p1.x(), r.height() );
+ }
+
+#if QT_VERSION < 300
+ style().drawSeparator( p, p1.x(), p1.y(), p2.x(), p2.y(), g, true, 1, midLineWidth() );
+#else
+ QStyleOption opt( lineWidth(), midLineWidth() );
+ style().drawPrimitive( QStyle::PE_Separator, p, QRect( p1, p2 ), g, QStyle::Style_Sunken, opt );
+#endif
+}
+
+
+QSize OSeparator::sizeHint() const
+{
+ if ( frameStyle() & VLine )
+ return QSize(2, 0);
+
+ if ( frameStyle() & HLine )
+ return QSize(0, 2);
+
+ return QSize(-1, -1);
+}
diff --git a/libopie2/opieui/oseparator.h b/libopie2/opieui/oseparator.h
new file mode 100644
index 0000000..e59b3f4
--- a/dev/null
+++ b/libopie2/opieui/oseparator.h
@@ -0,0 +1,90 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ Copyright (C) 1997 Michael Roth <mroth@wirlweb.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OSEPARATOR_H
+#define OSEPARATOR_H
+
+#include <qframe.h>
+
+/**
+ * Standard horizontal or vertical separator.
+ *
+ * @author Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ * @author Michael Roth <mroth@wirlweb.de>
+ * @version $Id$
+*/
+class OSeparator : public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY( int orientation READ orientation WRITE setOrientation )
+ public:
+ /**
+ * Constructor.
+ **/
+ OSeparator(QWidget* parent=0, const char* name=0, WFlags f=0);
+ /**
+ * Constructor.
+ *
+ * @param orientation Set the orientation of the separator.
+ * Possible values are HLine or Horizontal and VLine or Vertical.
+ **/
+ OSeparator(int orientation, QWidget* parent=0, const char* name=0,
+ WFlags f=0);
+
+ /**
+ * Returns the orientation of the separator.
+ *
+ * Possible values are VLine and HLine.
+ **/
+ int orientation() const;
+
+ /**
+ * Set the orientation of the separator to @p orient
+ *
+ * Possible values are VLine and HLine.
+ */
+ void setOrientation(int orient);
+
+ /**
+ * The recommended height (width) for a horizontal (vertical) separator.
+ **/
+ virtual QSize sizeHint() const;
+
+protected:
+ virtual void drawFrame( QPainter * );
+
+private:
+ class OSeparatorPrivate* d;
+};
+
+
+#endif // OSEPARATOR_H
diff --git a/libopie2/opieui/oversatileview.cpp b/libopie2/opieui/oversatileview.cpp
new file mode 100644
index 0000000..32855be
--- a/dev/null
+++ b/libopie2/opieui/oversatileview.cpp
@@ -0,0 +1,1179 @@
+/*
+                 This file is part of the Opie Project
+
+ =. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* QT */
+
+#include <qaction.h>
+#include <qbrush.h>
+#include <qfont.h>
+#include <qiconset.h>
+#include <qiconview.h>
+#include <qlistview.h>
+#include <qpalette.h>
+#include <qpoint.h>
+#include <qpopupmenu.h>
+#include <qrect.h>
+#include <qsize.h>
+#include <qstring.h>
+#include <qwidgetstack.h>
+
+/* OPIE */
+
+#include <opie2/oversatileview.h>
+#include <opie2/oversatileviewitem.h>
+#include <opie2/olistview.h>
+
+/* XPM */
+static const char * view_icon_xpm[] = {
+"16 16 16 1",
+" c None",
+". c #87BD88",
+"+ c #8BBE8B",
+"@ c #81BA81",
+"# c #6DAF6D",
+"$ c #87BD87",
+"% c #FCFDFC",
+"& c #AED0AE",
+"* c #4E9C4C",
+"= c #91BD91",
+"- c #72B172",
+"; c #448643",
+"> c #519F50",
+", c #499247",
+"' c #356A35",
+") c #686868",
+" ",
+" .+@# .+@# ",
+" $%&* $%&* ",
+" @=-; @=-; ",
+" #>,' #>,' ",
+" ",
+" )))))) )))))) ",
+" ",
+" ",
+" .+@# .+@# ",
+" $%&* $%&* ",
+" @=-; @=-; ",
+" #>,' #>,' ",
+" ",
+" )))))) )))))) ",
+" "};
+
+/* XPM */
+static const char * view_tree_xpm[] = {
+"16 16 17 1",
+" c None",
+". c #3A3A3A",
+"+ c #87BD88",
+"@ c #8BBE8B",
+"# c #81BA81",
+"$ c #6DAF6D",
+"% c #87BD87",
+"& c #FCFDFC",
+"* c #AED0AE",
+"= c #4E9C4C",
+"- c #91BD91",
+"; c #72B172",
+"> c #448643",
+", c #686868",
+"' c #519F50",
+") c #499247",
+"! c #356A35",
+" . ",
+" . ",
+" . +@#$ ",
+" . %&*= ",
+" .. #-;> ,, ,,,",
+" . $')! ",
+" . ",
+" . ",
+" . ",
+" . +@#$ ",
+" . %&*= ",
+" .. #-;> ,, ,,,",
+" $')! ",
+" ",
+" ",
+" "};
+
+OVersatileView::OVersatileView( QWidget* parent, const char* name, int mode )
+ :QWidgetStack( parent, name ),
+ _viewmode( mode ), _warningpolicy( None ),
+ _treeleaf(), _treeopened(), _treeclosed(),
+ _iconleaf(), _iconopened(), _iconclosed()
+{
+ //
+ // Create child widgets and set some reasonable default styles
+ //
+
+ _listview = new OListView( this, "oversatileview embedded listview" );
+ _iconview = new QIconView( this, "oversatileview embedded iconview" );
+
+ _listview->setAllColumnsShowFocus( true );
+ _listview->setRootIsDecorated( true );
+ _listview->setShowSortIndicator( true );
+ _iconview->setGridX( 90 );
+ _iconview->setGridY( 42 );
+ _iconview->setAutoArrange( true );
+
+ #ifdef QWS // TODO: Let this depend on current geometry (rotation)
+ _iconview->setArrangement( QIconView::TopToBottom );
+ #else
+ _iconview->setArrangement( QIconView::LeftToRight );
+ #endif
+
+ _iconview->setResizeMode( QIconView::Adjust );
+
+ // qt-embedded: map stylus right on hold to right button press
+
+ #ifdef QWS
+ ( (QPEApplication*) qApp)->setStylusOperation( _iconview->viewport(), QPEApplication::RightOnHold );
+ ( (QPEApplication*) qApp)->setStylusOperation( _listview->viewport(), QPEApplication::RightOnHold );
+ #endif
+
+ setViewMode( mode ); // TODO: Read last style from config
+ // setSynchronization( true ); // TODO: Implement this
+
+ // create context menu allowing to switch between the views
+
+ _contextmenu = new QPopupMenu( 0, "oversatileview contextmenu" );
+ _contextmenu->setCaption( "Style" );
+ _contextmenu->setCheckable( true );
+ QActionGroup* ag = new QActionGroup( _contextmenu, "style option group" );
+ QAction* a1 = new QAction( "View Items in Icon Style", QIconSet( QPixmap( view_icon_xpm ) ),
+ "View Icons", 0, ag, "viewicon action", true );
+ QAction* a2 = new QAction( "View Items in Tree Style", QIconSet( QPixmap( view_tree_xpm ) ),
+ "View Tree", 0, ag, "viewtree action", true );
+ ag->addTo( _contextmenu );
+ if ( mode == Icons )
+ a1->setOn( true );
+ else if ( mode == Tree )
+ a2->setOn( true );
+ connect( a1, SIGNAL( activated() ), this, SLOT( setIconViewMode() ) );
+ connect( a2, SIGNAL( activated() ), this, SLOT( setTreeViewMode() ) );
+
+ #if (QT_VERSION >= 0x030000)
+ connect( _listview, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint&, int ) ), this, SLOT( contextMenuRequested( QListViewItem*, const QPoint&, int ) ) );
+ connect( _iconview, SIGNAL( contextMenuRequested( QIconViewItem*, const QPoint& ) ), this, SLOT( contextMenuRequested( QIconViewItem*, const QPoint& ) ) );
+ #else
+ connect( _listview, SIGNAL( rightButtonPressed( QListViewItem*, const QPoint&, int ) ), this, SLOT( contextMenuRequested( QListViewItem*, const QPoint&, int ) ) );
+ connect( _iconview, SIGNAL( rightButtonPressed( QIconViewItem*, const QPoint& ) ), this, SLOT( contextMenuRequested( QIconViewItem*, const QPoint& ) ) );
+ #endif
+
+ //
+ // signal forwarders
+ //
+ // unfortunately we can't short-circuit all the QListView and QIconView signals
+ // to OVersatileView signals, because the signal/slot mechanism doesn't allow
+ // type-conversion :-(
+
+ // common signals for listview
+
+ connect( _listview, SIGNAL( selectionChanged() ), this, SIGNAL( selectionChanged() ) );
+ connect( _listview, SIGNAL( selectionChanged( QListViewItem * ) ), this, SLOT( selectionChanged( QListViewItem * ) ) );
+ connect( _listview, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( currentChanged( QListViewItem * ) ) );
+ connect( _listview, SIGNAL( clicked( QListViewItem * ) ), this, SLOT( clicked( QListViewItem * ) ) );
+ connect( _listview, SIGNAL( pressed( QListViewItem * ) ), this, SLOT( pressed( QListViewItem * ) ) );
+
+ connect( _listview, SIGNAL( doubleClicked( QListViewItem * ) ), this, SLOT( doubleClicked( QListViewItem * ) ) );
+ connect( _listview, SIGNAL( returnPressed( QListViewItem * ) ), this, SLOT( returnPressed( QListViewItem * ) ) );
+
+ connect( _listview, SIGNAL( onItem( QListViewItem * ) ), this, SLOT( onItem( QListViewItem * ) ) );
+ connect( _listview, SIGNAL( onViewport() ), this, SIGNAL( onViewport() ) );
+
+ // common signals for iconview
+
+ connect( _iconview, SIGNAL( selectionChanged() ), this, SIGNAL( selectionChanged() ) );
+ connect( _iconview, SIGNAL( selectionChanged( QIconViewItem * ) ), this, SLOT( selectionChanged( QIconViewItem * ) ) );
+ connect( _iconview, SIGNAL( currentChanged( QIconViewItem * ) ), this, SLOT( currentChanged( QIconViewItem * ) ) );
+ connect( _iconview, SIGNAL( clicked( QIconViewItem * ) ), this, SLOT( clicked( QIconViewItem * ) ) );
+ connect( _iconview, SIGNAL( pressed( QIconViewItem * ) ), this, SLOT( pressed( QIconViewItem * ) ) );
+
+ connect( _iconview, SIGNAL( doubleClicked( QIconViewItem * ) ), this, SLOT( doubleClicked( QIconViewItem * ) ) );
+ connect( _iconview, SIGNAL( returnPressed( QIconViewItem * ) ), this, SLOT( returnPressed( QIconViewItem * ) ) );
+
+ connect( _iconview, SIGNAL( onItem( QIconViewItem * ) ), this, SLOT( onItem( QIconViewItem * ) ) );
+ connect( _iconview, SIGNAL( onViewport() ), this, SIGNAL( onViewport() ) );
+
+ // listview only signals
+
+ connect( _listview, SIGNAL( expanded( QListViewItem * ) ), this, SLOT( expanded( QListViewItem * ) ) );
+ connect( _listview, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( collapsed( QListViewItem * ) ) );
+
+ // iconview only signals
+
+ connect( _iconview, SIGNAL( moved() ), this, SIGNAL( moved() ) );
+}
+
+OVersatileView::~OVersatileView()
+{
+}
+
+QPopupMenu* OVersatileView::contextMenu() const
+{
+ return _contextmenu;
+}
+
+void OVersatileView::contextMenuRequested( QListViewItem* item, const QPoint& pos, int col )
+{
+ // can't use QObject::inherits here, because ListViewItems, beit Q, O or K,
+ // do not inherit from QObject - assuming here the programmer is
+ // disciplined enough to only add OVersatileViewItems to an OVersatileView
+ popupContextMenu( static_cast<OVersatileViewItem*>( item ), pos, col );
+}
+
+void OVersatileView::contextMenuRequested( QIconViewItem* item, const QPoint& pos )
+{
+ // see above
+ popupContextMenu( static_cast<OVersatileViewItem*>( item ), pos, -1 );
+}
+
+void OVersatileView::popupContextMenu( OVersatileViewItem* item, const QPoint& pos, int col )
+{
+ if ( not item )
+ _contextmenu->exec( pos );
+ else
+ emit( contextMenuRequested( item, pos, col ) );
+}
+
+void OVersatileView::setSynchronization( bool sync )
+{
+ _synchronization = sync;
+}
+
+bool OVersatileView::synchronization()
+{
+ return _synchronization;
+}
+
+void OVersatileView::setDefaultPixmaps( int mode, QPixmap& leaf, QPixmap& opened, QPixmap& closed )
+{
+ if ( mode == Tree )
+ {
+ _treeleaf = leaf;
+ _treeopened = opened;
+ _treeclosed = closed;
+ }
+ else if ( mode == Icons )
+ {
+ _iconleaf = leaf;
+ _iconopened = opened;
+ _iconclosed = closed;
+ }
+ else
+ {
+ qDebug( "OVersatileView::setDefaultPixmaps(): invalid mode" );
+ }
+}
+
+QIconView* OVersatileView::iconView() const
+{
+ return _iconview;
+}
+
+OListView* OVersatileView::listView() const
+{
+ return _listview;
+}
+
+void OVersatileView::setViewMode( int mode )
+{
+ if ( mode == Tree )
+ {
+ _viewmode = mode;
+ raiseWidget( _listview );
+ }
+ else if ( mode == Icons )
+ {
+ _viewmode = mode;
+ raiseWidget( _iconview );
+ }
+ else
+ {
+ qDebug( "OVersatileView::setViewMode(): invalid mode" );
+ }
+}
+
+void OVersatileView::setIconViewMode()
+{
+ setViewMode( Icons );
+}
+
+void OVersatileView::setTreeViewMode()
+{
+ setViewMode( Tree );
+}
+
+bool OVersatileView::isValidViewMode( int mode ) const
+{
+ switch ( _warningpolicy )
+ {
+ case OVersatileView::None:
+ {
+ return true;
+ }
+ case OVersatileView::Warn:
+ {
+ if ( _viewmode != mode )
+ {
+ qDebug( "OVersatileView::isValidViewMode(): Requested operation not valid in current mode." );
+ return true;
+ }
+ }
+ case OVersatileView::WarnReturn:
+ {
+ if ( _viewmode != mode )
+ {
+ qDebug( "OVersatileView::isValidViewMode(): Requested operation not valid in current mode." );
+ return false;
+ }
+ }
+ default:
+ {
+ qWarning( "OVersatileView::isValidViewMode(): Inconsistent object state!" );
+ return true;
+ }
+ }
+}
+void OVersatileView::setWarningPolicy( int policy ) const
+{
+ _warningpolicy = policy;
+}
+bool OVersatileView::warningPolicy() const
+{
+ return _warningpolicy;
+}
+//==============================================================================================//
+// Stupid Signal forwarders...
+// Folks, this is why I like python with its dynamic typing:
+// I can code the following dozens of lines C++ in four Python lines...
+//==============================================================================================//
+
+void OVersatileView::selectionChanged( QListViewItem * item )
+{
+ emit( selectionChanged( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::selectionChanged( QIconViewItem * item )
+{
+ emit( selectionChanged( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::currentChanged( QListViewItem * item )
+{
+ emit( currentChanged( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::currentChanged( QIconViewItem * item )
+{
+ emit( currentChanged( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::clicked( QListViewItem * item )
+{
+ emit( clicked( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::clicked( QIconViewItem * item )
+{
+ emit( clicked( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::pressed( QListViewItem * item )
+{
+ emit( pressed( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::pressed( QIconViewItem * item )
+{
+ emit( pressed( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::doubleClicked( QListViewItem * item )
+{
+ emit( doubleClicked( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::doubleClicked( QIconViewItem * item )
+{
+ emit( doubleClicked( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::returnPressed( QListViewItem * item )
+{
+ emit( returnPressed( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::returnPressed( QIconViewItem * item )
+{
+ emit( returnPressed( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::onItem( QListViewItem * item )
+{
+ emit( onItem( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::onItem( QIconViewItem * item )
+{
+ emit( onItem( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+void OVersatileView::expanded( QListViewItem *item ) // QListView
+{
+ //qDebug( "OVersatileView::expanded(): opening tree..." );
+ if ( not _treeopened.isNull() )
+ item->setPixmap( 0, _treeopened );
+ emit( expanded( static_cast<OVersatileViewItem*>( item ) ) );
+}
+void OVersatileView::collapsed( QListViewItem *item ) // QListView
+{
+ if ( not _treeclosed.isNull() )
+ item->setPixmap( 0, _treeclosed );
+ emit( collapsed( static_cast<OVersatileViewItem*>( item ) ) );
+}
+
+//=============================================================================================//
+// OVersatileView Case I - API only existing in QListView or QIconView but not in both!
+//==============================================================================================//
+
+int OVersatileView::treeStepSize() const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return -1;
+ }
+ return _listview->treeStepSize();
+}
+ void OVersatileView::setTreeStepSize( int size ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->setTreeStepSize( size );
+}
+
+QHeader * OVersatileView::header() const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return 0;
+ }
+ return _listview->header();
+}
+
+ int OVersatileView::addColumn( const QString &label, int size ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return -1;
+ }
+ return _listview->addColumn( label, size );
+}
+
+ int OVersatileView::addColumn( const QIconSet& iconset, const QString &label, int size ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return -1;
+ }
+ return _listview->addColumn( iconset, label, size );
+}
+
+void OVersatileView::removeColumn( int index ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->removeColumn( index );
+}
+ void OVersatileView::setColumnText( int column, const QString &label ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->setColumnText( column, label );
+}
+ void OVersatileView::setColumnText( int column, const QIconSet& iconset, const QString &label ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->setColumnText( column, iconset, label );
+}
+QString OVersatileView::columnText( int column ) const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return QString::null;
+ }
+ return _listview->columnText( column );
+}
+ void OVersatileView::setColumnWidth( int column, int width ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->setColumnWidth( column, width );
+}
+int OVersatileView::columnWidth( int column ) const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return -1;
+ }
+ return _listview->columnWidth( column );
+}
+ void OVersatileView::setColumnWidthMode( int column, WidthMode mode ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->setColumnWidth( column, mode );
+}
+int OVersatileView::columns() const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return -1;
+ }
+ return _listview->columns();
+}
+
+ void OVersatileView::setColumnAlignment( int column, int align ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->setColumnAlignment( column, align );
+}
+int OVersatileView::columnAlignment( int column ) const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return -1;
+ }
+ return _listview->columnAlignment( column );
+}
+
+OVersatileViewItem * OVersatileView::itemAt( const QPoint & screenPos ) const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return 0;
+ }
+ return static_cast<OVersatileViewItem*>( _listview->itemAt( screenPos ) );
+}
+QRect OVersatileView::itemRect( const OVersatileViewItem * item ) const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return QRect( -1, -1, -1, -1 );
+ }
+ return _listview->itemRect( item );
+}
+int OVersatileView::itemPos( const OVersatileViewItem * item ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return -1;
+ }
+ return _listview->itemPos( item );
+}
+
+bool OVersatileView::isSelected( const OVersatileViewItem * item ) const // QListView // also in QIconViewItem but !in QIconView *shrug*
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return false;
+ }
+ return _listview->isSelected( item );
+}
+
+ void OVersatileView::setMultiSelection( bool enable )
+{
+ _listview->setMultiSelection( enable );
+}
+bool OVersatileView::isMultiSelection() const
+{
+ return _listview->isMultiSelection();
+}
+
+OVersatileViewItem * OVersatileView::selectedItem() const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return 0;
+ }
+ return static_cast<OVersatileViewItem*>( _listview->selectedItem() );
+}
+ void OVersatileView::setOpen( OVersatileViewItem * item, bool open ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->setOpen( item, open );
+}
+bool OVersatileView::isOpen( const OVersatileViewItem * item ) const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return false;
+ }
+ return _listview->isOpen( item );
+}
+
+OVersatileViewItem * OVersatileView::firstChild() const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return 0;
+ }
+ return static_cast<OVersatileViewItem*>( _listview->firstChild() );
+}
+int OVersatileView::childCount() const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return -1;
+ }
+ return _listview->childCount();
+}
+
+ void OVersatileView::setAllColumnsShowFocus( bool focus ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->setAllColumnsShowFocus( focus );
+}
+bool OVersatileView::allColumnsShowFocus() const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return false;
+ }
+ return _listview->allColumnsShowFocus();
+}
+
+ void OVersatileView::setItemMargin( int margin ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->setItemMargin( margin );
+}
+int OVersatileView::itemMargin() const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return -1;
+ }
+ return _listview->itemMargin();
+}
+
+ void OVersatileView::setRootIsDecorated( bool decorate ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->setRootIsDecorated( decorate );
+}
+bool OVersatileView::rootIsDecorated() const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return false;
+ }
+ return _listview->rootIsDecorated();
+}
+
+void OVersatileView::setShowSortIndicator( bool show ) // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->setShowSortIndicator( show );
+}
+bool OVersatileView::showSortIndicator() const // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return false;
+ }
+ return _listview->showSortIndicator();
+}
+
+void OVersatileView::triggerUpdate() // QListView
+{
+ if ( not isValidViewMode( Tree ) )
+ {
+ return;
+ }
+ _listview->triggerUpdate();
+}
+
+//
+// only in QIconView
+//
+
+uint OVersatileView::count() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return 0;
+ }
+ return _iconview->count();
+}
+
+int OVersatileView::index( const OVersatileViewItem *item ) const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return -1;
+ }
+ return _iconview->index( item );
+}
+
+OVersatileViewItem* OVersatileView::firstItem() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return 0;
+ }
+ return static_cast<OVersatileViewItem*>( _iconview->firstItem() );
+}
+OVersatileViewItem* OVersatileView::lastItem() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return 0;
+ }
+ return static_cast<OVersatileViewItem*>( _iconview->lastItem() );
+}
+
+OVersatileViewItem* OVersatileView::findItem( const QPoint &pos ) const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return 0;
+ }
+ return static_cast<OVersatileViewItem*>( _iconview->findItem( pos ) );
+}
+OVersatileViewItem* OVersatileView::findItem( const QString &text ) const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return 0;
+ }
+ return static_cast<OVersatileViewItem*>( _iconview->findItem( text ) );
+}
+
+OVersatileViewItem* OVersatileView::findFirstVisibleItem( const QRect &r ) const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return 0;
+ }
+ return static_cast<OVersatileViewItem*>( _iconview->findFirstVisibleItem( r ) );
+}
+OVersatileViewItem* OVersatileView::findLastVisibleItem( const QRect &r ) const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return 0;
+ }
+ return static_cast<OVersatileViewItem*>( _iconview->findLastVisibleItem( r ) );
+}
+
+ void OVersatileView::setGridX( int rx ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setGridX( rx );
+}
+ void OVersatileView::setGridY( int ry ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setGridY( ry );
+}
+int OVersatileView::gridX() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return -1;
+ }
+ return _iconview->gridX();
+}
+int OVersatileView::gridY() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return -1;
+ }
+ return _iconview->gridY();
+}
+ void OVersatileView::setSpacing( int sp ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setSpacing( sp );
+}
+int OVersatileView::spacing() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return -1;
+ }
+ return _iconview->spacing();
+}
+ void OVersatileView::setItemTextPos( QIconView::ItemTextPos pos ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setItemTextPos( pos );
+}
+QIconView::ItemTextPos OVersatileView::itemTextPos() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return (QIconView::ItemTextPos) -1;
+ }
+ return _iconview->itemTextPos();
+}
+ void OVersatileView::setItemTextBackground( const QBrush &b ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setItemTextBackground( b );
+}
+QBrush OVersatileView::itemTextBackground() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return QBrush();
+ }
+ return _iconview->itemTextBackground();
+}
+ void OVersatileView::setArrangement( QIconView::Arrangement am ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setArrangement( am );
+}
+QIconView::Arrangement OVersatileView::arrangement() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return (QIconView::Arrangement) -1;
+ }
+ return _iconview->arrangement();
+}
+ void OVersatileView::setResizeMode( QIconView::ResizeMode am ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setResizeMode( am );
+}
+QIconView::ResizeMode OVersatileView::resizeMode() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return (QIconView::ResizeMode) -1;
+ }
+ return _iconview->resizeMode();
+}
+ void OVersatileView::setMaxItemWidth( int w ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setMaxItemWidth( w );
+}
+int OVersatileView::maxItemWidth() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return -1;
+ }
+ return _iconview->maxItemWidth();
+}
+ void OVersatileView::setMaxItemTextLength( int w ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setMaxItemTextLength( w );
+}
+int OVersatileView::maxItemTextLength() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return -1;
+ }
+ return _iconview->maxItemTextLength();
+}
+ void OVersatileView::setAutoArrange( bool b ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setAutoArrange( b );
+}
+bool OVersatileView::autoArrange() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return false;
+ }
+ return _iconview->autoArrange();
+}
+ void OVersatileView::setShowToolTips( bool b ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setShowToolTips( b );
+}
+bool OVersatileView::showToolTips() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return false;
+ }
+ return _iconview->showToolTips();
+}
+
+bool OVersatileView::sorting() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return false;
+ }
+ return _iconview->sorting();
+}
+bool OVersatileView::sortDirection() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return false;
+ }
+ return _iconview->sortDirection();
+}
+
+ void OVersatileView::setItemsMovable( bool b ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setItemsMovable( b );
+}
+bool OVersatileView::itemsMovable() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return false;
+ }
+ return _iconview->itemsMovable();
+}
+void OVersatileView::setWordWrapIconText( bool b ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->setWordWrapIconText( b );
+}
+bool OVersatileView::wordWrapIconText() const // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return false;
+ }
+ return _iconview->wordWrapIconText();
+}
+
+void OVersatileView::arrangeItemsInGrid( const QSize &grid, bool update ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->arrangeItemsInGrid( grid, update );
+}
+void OVersatileView::arrangeItemsInGrid( bool update ) // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->arrangeItemsInGrid( update );
+}
+void OVersatileView::updateContents() // QIconView
+{
+ if ( not isValidViewMode( Icons ) )
+ {
+ return;
+ }
+ _iconview->updateContents();
+}
+
+//==============================================================================================//
+// OVersatileView Case II - QListView / QIconView common API
+//==============================================================================================//
+
+void OVersatileView::clear()
+{
+ _iconview->clear();
+ _listview->clear();
+}
+
+void OVersatileView::setFont( const QFont & font )
+{
+ _iconview->setFont( font );
+ _listview->setFont( font );
+}
+void OVersatileView::setPalette( const QPalette & palette )
+{
+ _iconview->setPalette( palette );
+ _listview->setPalette( palette );
+}
+
+void OVersatileView::takeItem( OVersatileViewItem * item )
+{
+ _iconview->takeItem( item );
+ _listview->takeItem( item );
+}
+
+void OVersatileView::setSelectionMode( SelectionMode mode )
+{
+ _iconview->setSelectionMode( (QIconView::SelectionMode) mode );
+ _listview->setSelectionMode( (QListView::SelectionMode) mode );
+}
+OVersatileView::SelectionMode OVersatileView::selectionMode() const
+{
+ return (OVersatileView::SelectionMode) _iconview->selectionMode();
+}
+
+void OVersatileView::selectAll( bool select )
+{
+ _iconview->selectAll( select );
+}
+void OVersatileView::clearSelection()
+{
+ _iconview->clearSelection();
+ _listview->clearSelection();
+}
+void OVersatileView::invertSelection()
+{
+ _iconview->invertSelection();
+ _listview->invertSelection();
+}
+
+void OVersatileView::ensureItemVisible( const OVersatileViewItem * item )
+{
+ _iconview->ensureItemVisible( const_cast<OVersatileViewItem*>( item ) );
+ _listview->ensureItemVisible( item );
+}
+void OVersatileView::repaintItem( const OVersatileViewItem * item ) const
+{
+ _iconview->repaintItem( const_cast<OVersatileViewItem*>( item ) );
+ _listview->repaintItem( item );
+}
+
+void OVersatileView::setCurrentItem( OVersatileViewItem * item )
+{
+ _iconview->setCurrentItem( item );
+ _listview->setCurrentItem( item );
+}
+OVersatileViewItem * OVersatileView::currentItem() const
+{
+ return static_cast<OVersatileViewItem*>( _listview->currentItem() );
+}
+
+// bool eventFilter( QObject * o, QEvent * ) // use QWidgetStack implementation
+
+// QSize minimumSizeHint() const // use QWidgetStack implementation
+// QSizePolicy sizePolicy() const // use QWidgetStack implementation
+// QSize sizeHint() const // use QWidgetStack implementation
+
+//==============================================================================================//
+// OVersatileView Case III - APIs which differ slightly
+//==============================================================================================//
+
+/*
+
+ void OVersatileView::insertItem( OVersatileViewItem * ) // QListView
+ void OVersatileView::insertItem( OVersatileViewItem *item, OVersatileViewItem *after = 0L ) // QIconView
+
+ void OVersatileView::setSelected( OVersatileViewItem *, bool ) // QListView
+ void OVersatileView::setSelected( OVersatileViewItem *item, bool s, bool cb = FALSE ) // QIconView
+
+ void OVersatileView::setSorting( int column, bool increasing = TRUE ) // QListView
+void OVersatileView::setSorting( bool sort, bool ascending = TRUE ) // QIconView
+
+void OVersatileView::sort() // #### make in next major release // QListView
+ void OVersatileView::sort( bool ascending = TRUE ) // QIconView
+
+*/
+
+
diff --git a/libopie2/opieui/oversatileview.h b/libopie2/opieui/oversatileview.h
new file mode 100644
index 0000000..1df8154
--- a/dev/null
+++ b/libopie2/opieui/oversatileview.h
@@ -0,0 +1,394 @@
+/*
+                 This file is part of the Opie Project
+
+ =. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OVERSATILEVIEW_H
+#define OVERSATILEVIEW_H
+
+/* QT */
+
+#include <qwidgetstack.h>
+#include <qiconview.h>
+
+/* OPIE */
+
+#include <qpe/qpeapplication.h>
+
+/* FORWARDS */
+
+class QHeader;
+class QIconSet;
+class QIconViewItem;
+class OListView;
+class QListViewItem;
+class QPopupMenu;
+class QString;
+
+#ifndef QT_NO_DRAGANDDROP
+class QIconDragItem;
+#endif
+
+class OVersatileView : public QWidgetStack
+{
+ Q_OBJECT
+
+ friend class OVersatileViewItem;
+
+ //==============================================================================================//
+ // OVersatileView High Level API
+ //==============================================================================================//
+
+ public:
+ OVersatileView( QWidget* parent = 0, const char* name = 0, int mode = 0 );
+ ~OVersatileView();
+
+ QPopupMenu* contextMenu() const;
+
+ void setSynchronization( bool sync );
+ bool synchronization();
+
+ enum ViewMode { Tree = 0, Icons };
+ int viewMode();
+
+ QIconView* iconView() const;
+ OListView* listView() const;
+
+ enum WarningPolicy { None = 0, Warn, WarnReturn };
+
+ void setWarningPolicy( int ) const; // warn, if calling a method which doesn't apply to the current viewmode
+ bool warningPolicy() const;
+
+ void setDefaultPixmaps( int mode, QPixmap& leaf, QPixmap& opened, QPixmap& closed );
+
+ public slots:
+ void setViewMode( int mode );
+ void setIconViewMode();
+ void setTreeViewMode();
+
+ protected:
+ virtual bool isValidViewMode( int mode ) const;
+ virtual void popupContextMenu( OVersatileViewItem* item, const QPoint& pos, int col = 0 );
+
+ private:
+ int _viewmode;
+ bool _synchronization;
+ mutable int _warningpolicy;
+
+ OListView* _listview;
+ QIconView* _iconview;
+
+ QPixmap _treeleaf;
+ QPixmap _treeopened;
+ QPixmap _treeclosed;
+
+ QPixmap _iconleaf;
+ QPixmap _iconopened;
+ QPixmap _iconclosed;
+
+ QPopupMenu* _contextmenu;
+
+ int _iconstyle;
+ int _treestyle;
+
+ private slots:
+
+ void contextMenuRequested( QListViewItem*, const QPoint&, int );
+ void contextMenuRequested( QIconViewItem*, const QPoint& );
+
+ // type converting signal forwarders
+
+ void selectionChanged( QListViewItem * );
+ void currentChanged( QListViewItem * );
+ void clicked( QListViewItem * );
+ void pressed( QListViewItem * );
+ void doubleClicked( QListViewItem * );
+ void returnPressed( QListViewItem * );
+ void onItem( QListViewItem * );
+
+ void selectionChanged( QIconViewItem * );
+ void currentChanged( QIconViewItem * );
+ void clicked( QIconViewItem * );
+ void pressed( QIconViewItem * );
+ void doubleClicked( QIconViewItem * );
+ void returnPressed( QIconViewItem * );
+ void onItem( QIconViewItem * );
+
+ void expanded( QListViewItem * item ); // QListView
+ void collapsed( QListViewItem * item ); // QListView
+
+ signals:
+
+ void contextMenuRequested( OVersatileViewItem * item, const QPoint& pos, int col );
+
+ /*#ifndef QT_NO_DRAGANDDROP
+ void dropped( QDropEvent *e, const QValueList<QIconDragItem> &lst ); // QIconView
+ #endif
+ void itemRenamed( OVersatileViewItem *item, const QString & ); // QIconView
+ void itemRenamed( OVersatileViewItem *item ); // QIconView
+ */
+
+ //==============================================================================================//
+ // "Derived" API - Case 1: Methods existing either only in QListView or only in QIconView
+ //==============================================================================================//
+
+public:
+
+ /*
+ enum Arrangement { // QIconView
+ LeftToRight = 0,
+ TopToBottom
+ };
+ enum ResizeMode { // QIconView
+ Fixed = 0,
+ Adjust
+ };
+ enum ItemTextPos { // QIconView
+ Bottom = 0,
+ Right
+ };
+ */
+
+ //
+ // only in QListView
+ //
+
+ int treeStepSize() const; // QListView
+ virtual void setTreeStepSize( int ); // QListView
+
+ QHeader * header() const; // QListView
+
+ virtual int addColumn( const QString &label, int size = -1); // QListView
+ virtual int addColumn( const QIconSet& iconset, const QString &label, int size = -1); // QListView
+ void removeColumn( int index ); // #### make virtual in next major release! // QListView
+ virtual void setColumnText( int column, const QString &label ); // QListView
+ virtual void setColumnText( int column, const QIconSet& iconset, const QString &label ); // QListView
+ QString columnText( int column ) const; // QListView
+ virtual void setColumnWidth( int column, int width ); // QListView
+ int columnWidth( int column ) const; // QListView
+ enum WidthMode { Manual, Maximum }; // QListView
+ virtual void setColumnWidthMode( int column, WidthMode ); // QListView
+ WidthMode columnWidthMode( int column ) const; // QListView
+ int columns() const; // QListView
+
+ virtual void setColumnAlignment( int, int ); // QListView
+ int columnAlignment( int ) const; // QListView
+
+ OVersatileViewItem * itemAt( const QPoint & screenPos ) const; // QListView
+ QRect itemRect( const OVersatileViewItem * ) const; // QListView
+ int itemPos( const OVersatileViewItem * ); // QListView
+
+ bool isSelected( const OVersatileViewItem * ) const; // QListView // also in QIconViewItem but not in QIconView *shrug*
+
+ virtual void setMultiSelection( bool enable ); // QListView
+ bool isMultiSelection() const; // QListView
+
+ OVersatileViewItem * selectedItem() const; // QListView
+ virtual void setOpen( OVersatileViewItem *, bool ); // QListView
+ bool isOpen( const OVersatileViewItem * ) const; // QListView
+
+ OVersatileViewItem * firstChild() const; // QListView
+ int childCount() const; // QListView
+
+ virtual void setAllColumnsShowFocus( bool ); // QListView
+ bool allColumnsShowFocus() const; // QListView
+
+ virtual void setItemMargin( int ); // QListView
+ int itemMargin() const; // QListView
+
+ virtual void setRootIsDecorated( bool ); // QListView
+ bool rootIsDecorated() const; // QListView
+
+ void setShowSortIndicator( bool show ); // QListView
+ bool showSortIndicator() const; // QListView
+
+ int index( const OVersatileViewItem *item ) const; // QIconView
+
+ public slots:
+ void triggerUpdate(); // QListView
+
+ signals:
+ void expanded( OVersatileViewItem *item ); // QListView
+ void collapsed( OVersatileViewItem *item ); // QListView
+
+ //
+ // only in QIconView
+ //
+
+ public:
+ uint count() const; // QIconView
+
+ OVersatileViewItem *firstItem() const; // QIconView
+ OVersatileViewItem *lastItem() const; // QIconView
+
+ OVersatileViewItem *findItem( const QPoint &pos ) const; // QIconView
+ OVersatileViewItem *findItem( const QString &text ) const; // QIconView
+
+ OVersatileViewItem* findFirstVisibleItem( const QRect &r ) const; // QIconView
+ OVersatileViewItem* findLastVisibleItem( const QRect &r ) const; // QIconView
+
+ virtual void setGridX( int rx ); // QIconView
+ virtual void setGridY( int ry ); // QIconView
+ int gridX() const; // QIconView
+ int gridY() const; // QIconView
+ virtual void setSpacing( int sp ); // QIconView
+ int spacing() const; // QIconView
+ virtual void setItemTextPos( QIconView::ItemTextPos pos ); // QIconView
+ QIconView::ItemTextPos itemTextPos() const; // QIconView
+ virtual void setItemTextBackground( const QBrush &b ); // QIconView
+ QBrush itemTextBackground() const; // QIconView
+ virtual void setArrangement( QIconView::Arrangement am ); // QIconView
+ QIconView::Arrangement arrangement() const; // QIconView
+ virtual void setResizeMode( QIconView::ResizeMode am ); // QIconView
+ QIconView::ResizeMode resizeMode() const; // QIconView
+ virtual void setMaxItemWidth( int w ); // QIconView
+ int maxItemWidth() const; // QIconView
+ virtual void setMaxItemTextLength( int w ); // QIconView
+ int maxItemTextLength() const; // QIconView
+ virtual void setAutoArrange( bool b ); // QIconView
+ bool autoArrange() const; // QIconView
+ virtual void setShowToolTips( bool b ); // QIconView
+ bool showToolTips() const; // QIconView
+
+ bool sorting() const; // QIconView
+ bool sortDirection() const; // QIconView
+
+ virtual void setItemsMovable( bool b ); // QIconView
+ bool itemsMovable() const; // QIconView
+ virtual void setWordWrapIconText( bool b ); // QIconView
+ bool wordWrapIconText() const; // QIconView
+
+ public slots:
+ virtual void arrangeItemsInGrid( const QSize &grid, bool update = TRUE ); // QIconView
+ virtual void arrangeItemsInGrid( bool update = TRUE ); // QIconView
+ virtual void updateContents(); // QIconView
+
+ signals:
+ /*#ifndef QT_NO_DRAGANDDROP
+ void dropped( QDropEvent *e, const QValueList<QIconDragItem> &lst ); // QIconView
+ #endif
+ */
+ void moved(); // QIconView
+ void itemRenamed( OVersatileViewItem *item, const QString & ); // QIconView
+ void itemRenamed( OVersatileViewItem *item ); // QIconView
+
+ //==============================================================================================//
+ // "Derived" API - Case 2: Methods existing in QListView and QIconView with the same signatures
+ //==============================================================================================//
+
+ public:
+ enum SelectionMode {
+ Single = 0,
+ Multi,
+ Extended,
+ NoSelection
+ };
+
+ virtual void clear();
+
+ virtual void setFont( const QFont & );
+ virtual void setPalette( const QPalette & );
+
+ virtual void takeItem( OVersatileViewItem * );
+
+ void setSelectionMode( SelectionMode mode );
+ SelectionMode selectionMode() const;
+
+ virtual void selectAll( bool select );
+ virtual void clearSelection();
+ virtual void invertSelection();
+
+ void ensureItemVisible( const OVersatileViewItem * );
+ virtual void repaintItem( const OVersatileViewItem * ) const;
+
+ virtual void setCurrentItem( OVersatileViewItem * );
+ OVersatileViewItem * currentItem() const;
+
+ // bool eventFilter( QObject * o, QEvent * ); // use QWidgetStack implementation
+
+ // QSize minimumSizeHint() const; // use QWidgetStack implementation
+ // QSizePolicy sizePolicy() const; // use QWidgetStack implementation
+ // QSize sizeHint() const; // use QWidgetStack implementation
+
+ signals:
+ void selectionChanged();
+ void selectionChanged( OVersatileViewItem * );
+ void currentChanged( OVersatileViewItem * );
+ void clicked( OVersatileViewItem * );
+ void pressed( OVersatileViewItem * );
+
+ void doubleClicked( OVersatileViewItem * );
+ void returnPressed( OVersatileViewItem * );
+
+ void onItem( OVersatileViewItem * );
+ void onViewport();
+
+ //==============================================================================================//
+ // "Derived" API - Case 2: Methods existing in QListView and QIconView with differing signatures
+ //==============================================================================================//
+
+ /*
+
+ public:
+ virtual void insertItem( OVersatileViewItem * ); // QListView
+ virtual void insertItem( OVersatileViewItem *item, OVersatileViewItem *after = 0L ); // QIconView
+
+ virtual void setSelected( OVersatileViewItem *, bool ); // QListView
+ virtual void setSelected( OVersatileViewItem *item, bool s, bool cb = FALSE ); // QIconView
+
+ virtual void setSorting( int column, bool increasing = TRUE ); // QListView
+ void setSorting( bool sort, bool ascending = TRUE ); // QIconView
+
+ void sort(); // #### make virtual in next major release // QListView
+ virtual void sort( bool ascending = TRUE ); // QIconView
+
+ */
+
+ signals:
+ void clicked( OVersatileViewItem *, const QPoint &, int ); // QListView
+ void clicked( OVersatileViewItem *, const QPoint & ); // QIconView
+
+ void pressed( OVersatileViewItem *, const QPoint &, int ); // QListView
+ void pressed( OVersatileViewItem *, const QPoint & ); // QIconView
+
+ void rightButtonClicked( OVersatileViewItem* item, const QPoint& pos ); // QIconView
+ void rightButtonClicked( OVersatileViewItem *, const QPoint&, int ); // QListView
+
+ void rightButtonPressed( OVersatileViewItem* item, const QPoint& pos ); // QIconView
+ void rightButtonPressed( OVersatileViewItem *, const QPoint&, int ); // QListView
+
+ void mouseButtonPressed( int, OVersatileViewItem *, const QPoint& , int ); // QListView
+ void mouseButtonPressed( int button, OVersatileViewItem* item, const QPoint& pos ); // QIconView
+
+ void mouseButtonClicked( int, OVersatileViewItem *, const QPoint&, int ); // QListView
+ void mouseButtonClicked( int button, OVersatileViewItem* item, const QPoint& pos ); // QIconView
+
+};
+
+#endif
+
diff --git a/libopie2/opieui/oversatileviewitem.cpp b/libopie2/opieui/oversatileviewitem.cpp
new file mode 100644
index 0000000..379ce24
--- a/dev/null
+++ b/libopie2/opieui/oversatileviewitem.cpp
@@ -0,0 +1,132 @@
+/*
+                 This file is part of the Opie Project
+
+ =. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include <opie2/oversatileviewitem.h>
+#include <opie2/oversatileview.h>
+
+OVersatileViewItem::OVersatileViewItem( OVersatileView * parent )
+ :OListViewItem( parent->_listview ), QIconViewItem( parent->_iconview ),
+ _versatileview( parent )
+{
+ init();
+}
+
+OVersatileViewItem::OVersatileViewItem( OVersatileView * parent, OVersatileViewItem * after )
+ :OListViewItem( parent->_listview, after ), QIconViewItem( parent->_iconview, after ),
+ _versatileview( parent )
+{
+ init();
+}
+
+OVersatileViewItem::OVersatileViewItem( OVersatileView * parent,
+ QString a, QString b, QString c, QString d,
+ QString e, QString f, QString g, QString h )
+ :OListViewItem( parent->_listview, a, b, c, d, e, f, g, h ),
+ QIconViewItem( parent->_iconview, a ),
+ _versatileview( parent )
+{
+ init();
+}
+
+OVersatileViewItem::OVersatileViewItem( OVersatileView * parent, OVersatileViewItem* after,
+ QString a, QString b, QString c, QString d,
+ QString e, QString f, QString g, QString h )
+ :OListViewItem( parent->_listview, after, a, b, c, d, e, f, g, h ),
+ QIconViewItem( parent->_iconview, after, a ),
+ _versatileview( parent )
+{
+ init();
+}
+
+OVersatileViewItem::OVersatileViewItem( OVersatileViewItem * parent,
+ QString a, QString b, QString c, QString d,
+ QString e, QString f, QString g, QString h )
+ :OListViewItem( parent, a, b, c, d, e, f, g, h ),
+ QIconViewItem( parent->_versatileview->_iconview, a ),
+ _versatileview( parent->_versatileview )
+{
+ init();
+}
+
+OVersatileViewItem::OVersatileViewItem( OVersatileViewItem * parent, OVersatileViewItem* after,
+ QString a, QString b, QString c, QString d,
+ QString e, QString f, QString g, QString h )
+ :OListViewItem( parent, after, a, b, c, d, e, f, g, h ),
+ QIconViewItem( parent->_versatileview->_iconview, after, a ),
+ _versatileview( parent->_versatileview )
+{
+ init();
+}
+
+OVersatileViewItem::~OVersatileViewItem()
+{
+}
+
+OVersatileView* OVersatileViewItem::versatileView() const
+{
+ return _versatileview;
+}
+
+void OVersatileViewItem::init()
+{
+ if ( not firstChild() )
+ {
+ // I'm a sweet yellow and browne autumn leaf
+
+ OListViewItem::setPixmap( 0, _versatileview->_treeleaf );
+ QIconViewItem::setPixmap( _versatileview->_iconleaf );
+ }
+ else
+ {
+ // I'm a node and I have a little baby child
+
+ if ( isOpen() )
+ {
+ OListViewItem::setPixmap( 0, _versatileview->_treeopened );
+ QIconViewItem::setPixmap( _versatileview->_iconopened );
+ }
+ else
+ {
+ OListViewItem::setPixmap( 0, _versatileview->_treeclosed );
+ QIconViewItem::setPixmap( _versatileview->_iconclosed );
+ }
+ }
+
+}
+
+void OVersatileViewItem::setRenameEnabled( bool allow )
+{
+ #if (QT_VERSION >= 0x030000)
+ OListViewItem::setRenameEnabled( 0, allow ); // TODO: Backport to Qt-Embedded 2.x?
+ #endif
+ QIconViewItem::setRenameEnabled( allow );
+}
+
+
diff --git a/libopie2/opieui/oversatileviewitem.h b/libopie2/opieui/oversatileviewitem.h
new file mode 100644
index 0000000..ee8ee20
--- a/dev/null
+++ b/libopie2/opieui/oversatileviewitem.h
@@ -0,0 +1,100 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OVERSATILEVIEWITEM_H
+#define OVERSATILEVIEWITEM_H
+
+/* QT */
+
+#include <qiconview.h>
+
+/* OPIE */
+
+#include <opie2/olistview.h>
+
+class OVersatileView;
+
+class OVersatileViewItem : public OListViewItem, public QIconViewItem
+{
+ public:
+ OVersatileViewItem( OVersatileView * parent );
+
+ OVersatileViewItem( OVersatileView * parent, OVersatileViewItem * after );
+
+ OVersatileViewItem( OVersatileViewItem * parent, OVersatileViewItem * after );
+
+ OVersatileViewItem( OVersatileView * parent, QString,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null );
+
+ OVersatileViewItem( OVersatileViewItem * parent, QString,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null );
+
+ OVersatileViewItem( OVersatileView * parent, OVersatileViewItem * after, QString,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null );
+
+ OVersatileViewItem( OVersatileViewItem * parent, OVersatileViewItem * after, QString,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null );
+
+ virtual ~OVersatileViewItem();
+
+ OVersatileView* versatileView() const;
+
+ // TODO: Implement the remaining constructors from QIconView
+
+ /* OIconViewItem( QIconView *parent, const QString &text, const QPixmap &icon );
+ OIconViewItem( QIconView *parent, QIconViewItem *after, const QString &text, const QPixmap &icon );
+ */
+
+ virtual void setRenameEnabled( bool );
+
+ // TODO: Implement the remaining method multiplexers
+
+ private:
+ OVersatileView* _versatileview;
+
+ private:
+ void init();
+
+};
+
+#endif
diff --git a/libopie2/pics/view_icon.png b/libopie2/pics/view_icon.png
new file mode 100644
index 0000000..4ae49f4
--- a/dev/null
+++ b/libopie2/pics/view_icon.png
Binary files differ
diff --git a/libopie2/pics/view_icon.xpm b/libopie2/pics/view_icon.xpm
new file mode 100644
index 0000000..70cb833
--- a/dev/null
+++ b/libopie2/pics/view_icon.xpm
@@ -0,0 +1,35 @@
+/* XPM */
+static char * view_icon_xpm[] = {
+"16 16 16 1",
+" c None",
+". c #87BD88",
+"+ c #8BBE8B",
+"@ c #81BA81",
+"# c #6DAF6D",
+"$ c #87BD87",
+"% c #FCFDFC",
+"& c #AED0AE",
+"* c #4E9C4C",
+"= c #91BD91",
+"- c #72B172",
+"; c #448643",
+"> c #519F50",
+", c #499247",
+"' c #356A35",
+") c #686868",
+" ",
+" .+@# .+@# ",
+" $%&* $%&* ",
+" @=-; @=-; ",
+" #>,' #>,' ",
+" ",
+" )))))) )))))) ",
+" ",
+" ",
+" .+@# .+@# ",
+" $%&* $%&* ",
+" @=-; @=-; ",
+" #>,' #>,' ",
+" ",
+" )))))) )))))) ",
+" "};
diff --git a/libopie2/pics/view_tree.png b/libopie2/pics/view_tree.png
new file mode 100644
index 0000000..192d25e
--- a/dev/null
+++ b/libopie2/pics/view_tree.png
Binary files differ
diff --git a/libopie2/pics/view_tree.xpm b/libopie2/pics/view_tree.xpm
new file mode 100644
index 0000000..de819c0
--- a/dev/null
+++ b/libopie2/pics/view_tree.xpm
@@ -0,0 +1,36 @@
+/* XPM */
+static char * view_tree_xpm[] = {
+"16 16 17 1",
+" c None",
+". c #3A3A3A",
+"+ c #87BD88",
+"@ c #8BBE8B",
+"# c #81BA81",
+"$ c #6DAF6D",
+"% c #87BD87",
+"& c #FCFDFC",
+"* c #AED0AE",
+"= c #4E9C4C",
+"- c #91BD91",
+"; c #72B172",
+"> c #448643",
+", c #686868",
+"' c #519F50",
+") c #499247",
+"! c #356A35",
+" . ",
+" . ",
+" . +@#$ ",
+" . %&*= ",
+" .. #-;> ,, ,,,",
+" . $')! ",
+" . ",
+" . ",
+" . ",
+" . +@#$ ",
+" . %&*= ",
+" .. #-;> ,, ,,,",
+" $')! ",
+" ",
+" ",
+" "};
diff --git a/libopie2/qt3/opiecore/ocompletion.cpp b/libopie2/qt3/opiecore/ocompletion.cpp
new file mode 100644
index 0000000..7b263ab
--- a/dev/null
+++ b/libopie2/qt3/opiecore/ocompletion.cpp
@@ -0,0 +1,1061 @@
+/*
+                 This file is part of the Opie Project
+ Originally part of the KDE Project
+ Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <opie2/ocompletion.h>
+
+class OCompTreeNode;
+
+/**************************************************************************************************/
+/* OCompTreeNodeList
+/**************************************************************************************************/
+
+class OCompTreeNodeList
+{
+public:
+ OCompTreeNodeList() : first(0), last(0), m_count(0) {}
+ OCompTreeNode *begin() const { return first; }
+ OCompTreeNode *end() const { return last; }
+
+ OCompTreeNode *at(uint index) const;
+ void append(OCompTreeNode *item);
+ void prepend(OCompTreeNode *item);
+ void insert(OCompTreeNode *after, OCompTreeNode *item);
+ OCompTreeNode *remove(OCompTreeNode *item);
+ uint count() const { return m_count; }
+
+private:
+ OCompTreeNode *first, *last;
+ uint m_count;
+};
+
+typedef OCompTreeNodeList OCompTreeChildren;
+typedef OSortableValueList<QString> OCompletionMatchesList;
+
+/**
+ * A helper class for OCompletion. Implements a tree of QChar.
+ *
+ * The tree looks like this (containing the items "kde", "kde-ui",
+ * "kde-core" and "pfeiffer". Every item is delimited with QChar( 0x0 )
+ *
+ * some_root_node
+ * / \
+ * k p
+ * | |
+ * d f
+ * | |
+ * e e
+ * /| |
+ * 0x0 - i
+ * / \ |
+ * u c f
+ * | | |
+ * i o f
+ * | | |
+ * 0x0 r e
+ * | |
+ * e r
+ * | |
+ * 0x0 0x0
+ *
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ * @internal
+ */
+
+/**************************************************************************************************/
+/* OCompTreeNode
+/**************************************************************************************************/
+
+class OCompTreeNode : public QChar
+{
+public:
+ OCompTreeNode():QChar(), myWeight(0) {}
+ OCompTreeNode( const QChar& ch, uint weight = 0 ):QChar( ch ), myWeight( weight ) {}
+ ~OCompTreeNode();
+
+ // FIXME: Do we need this for Opie? [see also the static ZoneAllocater below]
+ //void * operator new( size_t s ) {
+ // return alloc.allocate( s );
+ //}
+ //void operator delete( void * s ) {
+ // alloc.deallocate( s );
+ //}
+
+ // Returns a child of this node matching ch, if available.
+ // Otherwise, returns 0L
+ inline OCompTreeNode * find( const QChar& ch ) const {
+ OCompTreeNode * cur = myChildren.begin();
+ while (cur && (*cur != ch)) cur = cur->next;
+ return cur;
+ }
+
+ OCompTreeNode * insert( const QChar&, bool sorted );
+ void remove( const QString& );
+
+ inline int childrenCount() const { return myChildren.count(); };
+
+ // weighting
+ inline void confirm() { myWeight++; };
+ inline void confirm(uint w) { myWeight += w; };
+ inline void decline() { myWeight--; };
+ inline uint weight() const { return myWeight; };
+
+ inline const OCompTreeChildren * children() const { return &myChildren; };
+ inline const OCompTreeNode * childAt(int index) const { return myChildren.at(index); };
+ inline const OCompTreeNode * firstChild() const { return myChildren.begin(); };
+ inline const OCompTreeNode * lastChild() const { return myChildren.end(); };
+
+ /* We want to handle a list of OCompTreeNodes on our own, to not
+ need to use QValueList<>. And to make it even more fast we don't
+ use an accessor, but just a public member. */
+ OCompTreeNode *next;
+
+private:
+ uint myWeight;
+ OCompTreeNodeList myChildren;
+ //static OZoneAllocator alloc; // FIXME: Do we need this for Opie?
+};
+
+/**************************************************************************************************/
+/* OCompletionMatchesWrapper
+/**************************************************************************************************/
+
+class OCompletionMatchesWrapper
+{
+public:
+ OCompletionMatchesWrapper( bool sort = false )
+ : sortedList( sort ? new OCompletionMatchesList : 0L ),
+ dirty( false )
+ {}
+ ~OCompletionMatchesWrapper() {
+ delete sortedList;
+ }
+
+ void setSorting( bool sort ) {
+ if ( sort && !sortedList )
+ sortedList = new OCompletionMatchesList;
+ else if ( !sort ) {
+ delete sortedList;
+ sortedList = 0L;
+ }
+ stringList.clear();
+ dirty = false;
+ }
+
+ bool sorting() const {
+ return sortedList != 0L;
+ }
+
+ void append( int i, const QString& string ) {
+ if ( sortedList )
+ sortedList->insert( i, string );
+ else
+ stringList.append( string );
+ dirty = true;
+ }
+
+ void clear() {
+ if ( sortedList )
+ sortedList->clear();
+ stringList.clear();
+ dirty = false;
+ }
+
+ uint count() const {
+ if ( sortedList )
+ return sortedList->count();
+ return stringList.count();
+ }
+
+ bool isEmpty() const {
+ return count() == 0;
+ }
+
+ QString first() const {
+ return list().first();
+ }
+
+ QString last() const {
+ return list().last();
+ }
+
+ QStringList list() const;
+
+ mutable QStringList stringList;
+ OCompletionMatchesList *sortedList;
+ mutable bool dirty;
+};
+
+/**************************************************************************************************/
+/* OCompletionPrivate
+/**************************************************************************************************/
+
+class OCompletionPrivate
+{
+public:
+ // not a member to avoid #including kcompletion_private.h from kcompletion.h
+ // list used for nextMatch() and previousMatch()
+ OCompletionMatchesWrapper matches;
+};
+
+/**************************************************************************************************/
+/* OCompletion
+/**************************************************************************************************/
+
+OCompletion::OCompletion()
+{
+ d = new OCompletionPrivate;
+
+ myCompletionMode = OGlobalSettings::completionMode();
+ myTreeRoot = new OCompTreeNode;
+ myBeep = true;
+ myIgnoreCase = false;
+ myHasMultipleMatches = false;
+ myRotationIndex = 0;
+ setOrder( Insertion );
+}
+
+
+OCompletion::~OCompletion()
+{
+ delete d;
+ delete myTreeRoot;
+}
+
+
+void OCompletion::setOrder( CompOrder order )
+{
+ myOrder = order;
+ d->matches.setSorting( order == Weighted );
+}
+
+
+void OCompletion::setIgnoreCase( bool ignoreCase )
+{
+ myIgnoreCase = ignoreCase;
+}
+
+
+void OCompletion::setItems( const QStringList& items )
+{
+ clear();
+ insertItems( items );
+}
+
+
+void OCompletion::insertItems( const QStringList& items )
+{
+ bool weighted = (myOrder == Weighted);
+ QStringList::ConstIterator it;
+ if ( weighted ) { // determine weight
+ for ( it = items.begin(); it != items.end(); ++it ) addWeightedItem( *it );
+ }
+ else {
+ for ( it = items.begin(); it != items.end(); ++it ) addItem( *it, 0 );
+ }
+}
+
+
+QStringList OCompletion::items() const
+{
+ OCompletionMatchesWrapper list; // unsorted
+ bool addWeight = (myOrder == Weighted);
+ extractStringsFromNode( myTreeRoot, QString::null, &list, addWeight );
+
+ return list.list();
+}
+
+
+void OCompletion::addItem( const QString& item )
+{
+ d->matches.clear();
+ myRotationIndex = 0;
+ myLastString = QString::null;
+
+ addItem( item, 0 );
+}
+
+
+void OCompletion::addItem( const QString& item, uint weight )
+{
+ if ( item.isEmpty() ) return;
+
+ OCompTreeNode *node = myTreeRoot;
+ uint len = item.length();
+
+ bool sorted = (myOrder == Sorted);
+ bool weighted = ((myOrder == Weighted) && weight > 1);
+
+ // knowing the weight of an item, we simply add this weight to all of its
+ // nodes.
+
+ for ( uint i = 0; i < len; i++ ) {
+ node = node->insert( item.at(i), sorted );
+ if ( weighted ) node->confirm( weight -1 ); // node->insert() sets weighting to 1
+ }
+
+ // add 0x0-item as delimiter with evtl. weight
+ node = node->insert( 0x0, true );
+ if ( weighted )
+ node->confirm( weight -1 );
+ //qDebug( "OCompletion: added: %s (%i)", item.latin1(), node->weight());
+}
+
+
+void OCompletion::addWeightedItem( const QString& item )
+{
+ if ( myOrder != Weighted ) {
+ addItem( item, 0 );
+ return;
+ }
+
+ uint len = item.length();
+ uint weight = 0;
+
+ // find out the weighting of this item (appended to the string as ":num")
+ int index = item.findRev(':');
+ if ( index > 0 ) {
+ bool ok;
+ weight = item.mid( index + 1 ).toUInt( &ok );
+ if ( !ok )
+ weight = 0;
+
+ len = index; // only insert until the ':'
+ }
+
+ addItem( item.left( len ), weight );
+ return;
+}
+
+
+void OCompletion::removeItem( const QString& item )
+{
+ d->matches.clear();
+ myRotationIndex = 0;
+ myLastString = QString::null;
+
+ myTreeRoot->remove( item );
+}
+
+
+void OCompletion::clear()
+{
+ d->matches.clear();
+ myRotationIndex = 0;
+ myLastString = QString::null;
+
+ delete myTreeRoot;
+ myTreeRoot = new OCompTreeNode;
+}
+
+
+QString OCompletion::makeCompletion( const QString& string )
+{
+ if ( myCompletionMode == OGlobalSettings::CompletionNone )
+ return QString::null;
+
+ //qDebug( "OCompletion: completing: %s", string );
+
+ d->matches.clear();
+ myRotationIndex = 0;
+ myHasMultipleMatches = false;
+ myLastMatch = myCurrentMatch;
+
+ // in Shell-completion-mode, emit all matches when we get the same
+ // complete-string twice
+ if ( myCompletionMode == OGlobalSettings::CompletionShell &&
+ string == myLastString ) {
+ // Don't use d->matches since calling postProcessMatches()
+ // on d->matches here would interfere with call to
+ // postProcessMatch() during rotation
+
+ findAllCompletions( string, &d->matches, myHasMultipleMatches );
+ QStringList l = d->matches.list();
+ postProcessMatches( &l );
+ emit matches( l );
+
+ if ( l.isEmpty() )
+ doBeep( NoMatch );
+
+ return QString::null;
+ }
+
+ QString completion;
+ // in case-insensitive popup mode, we search all completions at once
+ if ( myCompletionMode == OGlobalSettings::CompletionPopup ||
+ myCompletionMode == OGlobalSettings::CompletionPopupAuto ) {
+ findAllCompletions( string, &d->matches, myHasMultipleMatches );
+ if ( !d->matches.isEmpty() )
+ completion = d->matches.first();
+ }
+ else
+ completion = findCompletion( string );
+
+ if ( myHasMultipleMatches )
+ emit multipleMatches();
+
+ myLastString = string;
+ myCurrentMatch = completion;
+
+ postProcessMatch( &completion );
+
+ if ( !string.isEmpty() ) { // only emit match when string != ""
+ //qDebug( "OCompletion: Match: %s", completion );
+ emit match( completion );
+ }
+
+ if ( completion.isNull() )
+ doBeep( NoMatch );
+
+ return completion;
+}
+
+QStringList OCompletion::substringCompletion( const QString& string ) const
+{
+ // get all items in the tree, eventually in sorted order
+ bool sorted = (myOrder == Weighted);
+ OCompletionMatchesWrapper allItems( sorted );
+ extractStringsFromNode( myTreeRoot, QString::null, &allItems, false );
+
+ QStringList list = allItems.list();
+
+ // subStringMatches is invoked manually, via a shortcut, so we should
+ // beep here, if necessary.
+ if ( list.isEmpty() ) {
+ doBeep( NoMatch );
+ return list;
+ }
+
+ if ( string.isEmpty() ) { // shortcut
+ postProcessMatches( &list );
+ return list;
+ }
+
+ QStringList matches;
+ QStringList::ConstIterator it = list.begin();
+
+ for( ; it != list.end(); ++it ) {
+ QString item = *it;
+ if ( item.find( string, 0, false ) != -1 ) { // always case insensitive
+ postProcessMatch( &item );
+ matches.append( item );
+ }
+ }
+
+ if ( matches.isEmpty() )
+ doBeep( NoMatch );
+
+ return matches;
+}
+
+
+void OCompletion::setCompletionMode( OGlobalSettings::Completion mode )
+{
+ myCompletionMode = mode;
+}
+
+
+QStringList OCompletion::allMatches()
+{
+ // Don't use d->matches since calling postProcessMatches()
+ // on d->matches here would interfere with call to
+ // postProcessMatch() during rotation
+ OCompletionMatchesWrapper matches( myOrder == Weighted );
+ bool dummy;
+ findAllCompletions( myLastString, &matches, dummy );
+ QStringList l = matches.list();
+ postProcessMatches( &l );
+ return l;
+}
+
+
+OCompletionMatches OCompletion::allWeightedMatches()
+{
+ // Don't use d->matches since calling postProcessMatches()
+ // on d->matches here would interfere with call to
+ // postProcessMatch() during rotation
+ OCompletionMatchesWrapper matches( myOrder == Weighted );
+ bool dummy;
+ findAllCompletions( myLastString, &matches, dummy );
+ OCompletionMatches ret( matches );
+ postProcessMatches( &ret );
+ return ret;
+}
+
+QStringList OCompletion::allMatches( const QString &string )
+{
+ OCompletionMatchesWrapper matches( myOrder == Weighted );
+ bool dummy;
+ findAllCompletions( string, &matches, dummy );
+ QStringList l = matches.list();
+ postProcessMatches( &l );
+ return l;
+}
+
+OCompletionMatches OCompletion::allWeightedMatches( const QString &string )
+{
+ OCompletionMatchesWrapper matches( myOrder == Weighted );
+ bool dummy;
+ findAllCompletions( string, &matches, dummy );
+ OCompletionMatches ret( matches );
+ postProcessMatches( &ret );
+ return ret;
+}
+
+/////////////////////////////////////////////////////
+///////////////// tree operations ///////////////////
+
+
+QString OCompletion::nextMatch()
+{
+ QString completion;
+ myLastMatch = myCurrentMatch;
+
+ if ( d->matches.isEmpty() ) {
+ findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
+ completion = d->matches.first();
+ myCurrentMatch = completion;
+ myRotationIndex = 0;
+ postProcessMatch( &completion );
+ emit match( completion );
+ return completion;
+ }
+
+ QStringList matches = d->matches.list();
+ myLastMatch = matches[ myRotationIndex++ ];
+
+ if ( myRotationIndex == matches.count() -1 )
+ doBeep( Rotation ); // indicate last matching item -> rotating
+
+ else if ( myRotationIndex == matches.count() )
+ myRotationIndex = 0;
+
+ completion = matches[ myRotationIndex ];
+ myCurrentMatch = completion;
+ postProcessMatch( &completion );
+ emit match( completion );
+ return completion;
+}
+
+
+
+QString OCompletion::previousMatch()
+{
+ QString completion;
+ myLastMatch = myCurrentMatch;
+
+ if ( d->matches.isEmpty() ) {
+ findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
+ completion = d->matches.last();
+ myCurrentMatch = completion;
+ myRotationIndex = 0;
+ postProcessMatch( &completion );
+ emit match( completion );
+ return completion;
+ }
+
+ QStringList matches = d->matches.list();
+ myLastMatch = matches[ myRotationIndex ];
+ if ( myRotationIndex == 1 )
+ doBeep( Rotation ); // indicate first item -> rotating
+
+ else if ( myRotationIndex == 0 )
+ myRotationIndex = matches.count();
+
+ myRotationIndex--;
+
+ completion = matches[ myRotationIndex ];
+ myCurrentMatch = completion;
+ postProcessMatch( &completion );
+ emit match( completion );
+ return completion;
+}
+
+
+
+// tries to complete "string" from the tree-root
+QString OCompletion::findCompletion( const QString& string )
+{
+ QChar ch;
+ QString completion;
+ const OCompTreeNode *node = myTreeRoot;
+
+ // start at the tree-root and try to find the search-string
+ for( uint i = 0; i < string.length(); i++ ) {
+ ch = string.at( i );
+ node = node->find( ch );
+
+ if ( node )
+ completion += ch;
+ else
+ return QString::null; // no completion
+ }
+
+ // Now we have the last node of the to be completed string.
+ // Follow it as long as it has exactly one child (= longest possible
+ // completion)
+
+ while ( node->childrenCount() == 1 ) {
+ node = node->firstChild();
+ if ( !node->isNull() )
+ completion += *node;
+ }
+ // if multiple matches and auto-completion mode
+ // -> find the first complete match
+ if ( node && node->childrenCount() > 1 ) {
+ myHasMultipleMatches = true;
+
+ if ( myCompletionMode == OGlobalSettings::CompletionAuto ) {
+ myRotationIndex = 1;
+ if (myOrder != Weighted) {
+ while ( (node = node->firstChild()) ) {
+ if ( !node->isNull() )
+ completion += *node;
+ else
+ break;
+ }
+ }
+ else {
+ // don't just find the "first" match, but the one with the
+ // highest priority
+
+ const OCompTreeNode* temp_node = 0L;
+ while(1) {
+ int count = node->childrenCount();
+ temp_node = node->firstChild();
+ uint weight = temp_node->weight();
+ const OCompTreeNode* hit = temp_node;
+ for( int i = 1; i < count; i++ ) {
+ temp_node = node->childAt(i);
+ if( temp_node->weight() > weight ) {
+ hit = temp_node;
+ weight = hit->weight();
+ }
+ }
+ // 0x0 has the highest priority -> we have the best match
+ if ( hit->isNull() )
+ break;
+
+ node = hit;
+ completion += *node;
+ }
+ }
+ }
+
+ else
+ doBeep( PartialMatch ); // partial match -> beep
+ }
+
+ return completion;
+}
+
+
+void OCompletion::findAllCompletions(const QString& string,
+ OCompletionMatchesWrapper *matches,
+ bool& hasMultipleMatches) const
+{
+ //qDebug( "OCompletion: finding all completions for %s", (const char*) string );
+
+ if ( string.isEmpty() )
+ return;
+
+ if ( myIgnoreCase ) { // case insensitive completion
+ extractStringsFromNodeCI( myTreeRoot, QString::null, string, matches );
+ hasMultipleMatches = (matches->count() > 1);
+ return;
+ }
+
+ QChar ch;
+ QString completion;
+ const OCompTreeNode *node = myTreeRoot;
+
+ // start at the tree-root and try to find the search-string
+ for( uint i = 0; i < string.length(); i++ ) {
+ ch = string.at( i );
+ node = node->find( ch );
+
+ if ( node )
+ completion += ch;
+ else
+ return; // no completion -> return empty list
+ }
+
+ // Now we have the last node of the to be completed string.
+ // Follow it as long as it has exactly one child (= longest possible
+ // completion)
+
+ while ( node->childrenCount() == 1 ) {
+ node = node->firstChild();
+ if ( !node->isNull() )
+ completion += *node;
+ // kdDebug() << completion << node->latin1();
+ }
+
+
+ // there is just one single match)
+ if ( node->childrenCount() == 0 )
+ matches->append( node->weight(), completion );
+
+ else {
+ // node has more than one child
+ // -> recursively find all remaining completions
+ hasMultipleMatches = true;
+ extractStringsFromNode( node, completion, matches );
+ }
+}
+
+
+void OCompletion::extractStringsFromNode( const OCompTreeNode *node,
+ const QString& beginning,
+ OCompletionMatchesWrapper *matches,
+ bool addWeight ) const
+{
+ if ( !node || !matches ) return;
+
+ // kDebug() << "Beginning: " << beginning << endl;
+ const OCompTreeChildren *list = node->children();
+ QString string;
+ QString w;
+
+ // loop thru all children
+ for ( OCompTreeNode *cur = list->begin(); cur ; cur = cur->next) {
+ string = beginning;
+ node = cur;
+ if ( !node->isNull() )
+ string += *node;
+
+ while ( node && node->childrenCount() == 1 ) {
+ node = node->firstChild();
+ if ( node->isNull() ) break;
+ string += *node;
+ }
+
+ if ( node && node->isNull() ) { // we found a leaf
+ if ( addWeight ) {
+ // add ":num" to the string to store the weighting
+ string += ':';
+ w.setNum( node->weight() );
+ string.append( w );
+ }
+ matches->append( node->weight(), string );
+ }
+
+ // recursively find all other strings.
+ if ( node && node->childrenCount() > 1 )
+ extractStringsFromNode( node, string, matches, addWeight );
+ }
+}
+
+void OCompletion::extractStringsFromNodeCI( const OCompTreeNode *node,
+ const QString& beginning,
+ const QString& restString,
+ OCompletionMatchesWrapper *matches ) const
+{
+ if ( restString.isEmpty() ) {
+ extractStringsFromNode( node, beginning, matches, false /*noweight*/ );
+ return;
+ }
+
+ QChar ch1 = restString.at(0);
+ QString newRest = restString.mid(1);
+ OCompTreeNode *child1, *child2;
+
+ child1 = node->find( ch1 ); // the correct match
+ if ( child1 )
+ extractStringsFromNodeCI( child1, beginning + *child1, newRest,
+ matches );
+
+ // append the case insensitive matches, if available
+ if ( ch1.isLetter() ) {
+ // find out if we have to lower or upper it. Is there a better way?
+ QChar ch2 = ch1.lower();
+ if ( ch1 == ch2 )
+ ch2 = ch1.upper();
+ if ( ch1 != ch2 ) {
+ child2 = node->find( ch2 );
+ if ( child2 )
+ extractStringsFromNodeCI( child2, beginning + *child2, newRest,
+ matches );
+ }
+ }
+}
+
+// FIXME: Revise this for Opie?
+
+void OCompletion::doBeep( BeepMode mode ) const
+{
+ if ( !myBeep ) return;
+
+ QString text, event;
+
+ switch ( mode ) {
+ case Rotation:
+ event = QString::fromLatin1("Textcompletion: rotation");
+ text = tr("You reached the end of the list\nof matching items.\n");
+ break;
+ case PartialMatch:
+ if ( myCompletionMode == OGlobalSettings::CompletionShell ||
+ myCompletionMode == OGlobalSettings::CompletionMan ) {
+ event = QString::fromLatin1("Textcompletion: partial match");
+ text = tr("The completion is ambiguous, more than one\nmatch is available.\n");
+ }
+ break;
+ case NoMatch:
+ if ( myCompletionMode == OGlobalSettings::CompletionShell ) {
+ event = QString::fromLatin1("Textcompletion: no match");
+ text = tr("There is no matching item available.\n");
+ }
+ break;
+ }
+
+ //if ( !text.isEmpty() )
+ //ONotifyClient::event( event, text ); // FIXME: Revise for Opie?
+}
+
+// Implements the tree. Every node is a QChar and has a list of children, which
+// are Nodes as well.
+// QChar( 0x0 ) is used as the delimiter of a string; the last child of each
+// inserted string is 0x0.
+
+OCompTreeNode::~OCompTreeNode()
+{
+ // delete all children
+ OCompTreeNode *cur = myChildren.begin();
+ while (cur) {
+ OCompTreeNode * next = cur->next;
+ delete myChildren.remove(cur);
+ cur = next;
+ }
+}
+
+
+// Adds a child-node "ch" to this node. If such a node is already existant,
+// it will not be created. Returns the new/existing node.
+OCompTreeNode * OCompTreeNode::insert( const QChar& ch, bool sorted )
+{
+ OCompTreeNode *child = find( ch );
+ if ( !child ) {
+ child = new OCompTreeNode( ch );
+
+ // FIXME, first (slow) sorted insertion implementation
+ if ( sorted ) {
+ OCompTreeNode * prev = 0;
+ OCompTreeNode * cur = myChildren.begin();
+ while ( cur ) {
+ if ( ch > *cur ) {
+ prev = cur;
+ cur = cur->next;
+ } else
+ break;
+ }
+ if (prev)
+ myChildren.insert( prev, child );
+ else
+ myChildren.prepend(child);
+ }
+
+ else
+ myChildren.append( child );
+ }
+
+ // implicit weighting: the more often an item is inserted, the higher
+ // priority it gets.
+ child->confirm();
+
+ return child;
+}
+
+
+// Recursively removes a string from the tree (untested :-)
+void OCompTreeNode::remove( const QString& string )
+{
+ OCompTreeNode *child = 0L;
+
+ if ( string.isEmpty() ) {
+ child = find( 0x0 );
+ delete myChildren.remove( child );
+ return;
+ }
+
+ QChar ch = string.at(0);
+ child = find( ch );
+ if ( child ) {
+ child->remove( string.right( string.length() -1 ) );
+ if ( child->myChildren.count() == 0 ) {
+ delete myChildren.remove( child );
+ }
+ }
+}
+
+QStringList OCompletionMatchesWrapper::list() const {
+ if ( sortedList && dirty ) {
+ sortedList->sort();
+ dirty = false;
+
+ stringList.clear();
+
+ // high weight == sorted last -> reverse the sorting here
+ QValueListConstIterator<OSortableItem<QString> > it;
+ for ( it = sortedList->begin(); it != sortedList->end(); ++it )
+ stringList.prepend( (*it).value() );
+ }
+
+ return stringList;
+}
+
+OCompletionMatches::OCompletionMatches( bool sort_P )
+ : _sorting( sort_P )
+{
+}
+
+OCompletionMatches::OCompletionMatches( const OCompletionMatchesWrapper& matches )
+ : _sorting( matches.sorting())
+{
+ if( matches.sortedList != 0L )
+ OCompletionMatchesList::operator=( *matches.sortedList );
+ else {
+ QStringList l = matches.list();
+ for( QStringList::ConstIterator it = l.begin();
+ it != l.end();
+ ++it )
+ prepend( OSortableItem<QString, int>( 1, *it ) );
+ }
+}
+
+OCompletionMatches::~OCompletionMatches()
+{
+}
+
+QStringList OCompletionMatches::list( bool sort_P ) const
+{
+ if( _sorting && sort_P )
+ const_cast< OCompletionMatches* >( this )->sort();
+ QStringList stringList;
+ // high weight == sorted last -> reverse the sorting here
+ for ( ConstIterator it = begin(); it != end(); ++it )
+ stringList.prepend( (*it).value() );
+ return stringList;
+}
+
+void OCompletionMatches::removeDuplicates()
+{
+ Iterator it1, it2;
+ for ( it1 = begin(); it1 != end(); ++it1 ) {
+ for ( (it2 = it1), ++it2; it2 != end();) {
+ if( (*it1).value() == (*it2).value()) {
+ // use the max height
+ //(*it1).first = kMax( (*it1).index(), (*it2).index());
+ (*it1).first = (*it2).index() < (*it1).index() ? (*it1).index() : (*it2).index();
+ it2 = remove( it2 );
+ continue;
+ }
+ ++it2;
+ }
+ }
+}
+
+void OCompTreeNodeList::append(OCompTreeNode *item)
+{
+ m_count++;
+ if (!last) {
+ last = item;
+ last->next = 0;
+ first = item;
+ return;
+ }
+ last->next = item;
+ item->next = 0;
+ last = item;
+}
+
+void OCompTreeNodeList::prepend(OCompTreeNode *item)
+{
+ m_count++;
+ if (!last) {
+ last = item;
+ last->next = 0;
+ first = item;
+ return;
+ }
+ item->next = first;
+ first = item;
+}
+
+void OCompTreeNodeList::insert(OCompTreeNode *after, OCompTreeNode *item)
+{
+ if (!after) {
+ append(item);
+ return;
+ }
+
+ m_count++;
+
+ item->next = after->next;
+ after->next = item;
+
+ if (after == last)
+ last = item;
+}
+
+OCompTreeNode *OCompTreeNodeList::remove(OCompTreeNode *item)
+{
+ if (!first || !item)
+ return 0;
+ OCompTreeNode *cur = 0;
+
+ if (item == first)
+ first = first->next;
+ else {
+ cur = first;
+ while (cur && cur->next != item) cur = cur->next;
+ if (!cur)
+ return 0;
+ cur->next = item->next;
+ }
+ if (item == last)
+ last = cur;
+ m_count--;
+ return item;
+}
+
+OCompTreeNode *OCompTreeNodeList::at(uint index) const
+{
+ OCompTreeNode *cur = first;
+ while (index-- && cur) cur = cur->next;
+ return cur;
+}
+
+// FIXME: Revise for Opie?
+//OZoneAllocator OCompTreeNode::alloc(8192);
+
+//void OCompletion::virtual_hook( int, void* )
+//{ /*BASE::virtual_hook( id, data );*/ }
+
+//void OCompletionBase::virtual_hook( int, void* )
+//{ /*BASE::virtual_hook( id, data );*/ }
diff --git a/libopie2/qt3/opiecore/ocompletion.h b/libopie2/qt3/opiecore/ocompletion.h
new file mode 100644
index 0000000..0317c1b
--- a/dev/null
+++ b/libopie2/qt3/opiecore/ocompletion.h
@@ -0,0 +1,603 @@
+/*
+                 This file is part of the Opie Project
+ Originally part of the KDE Project
+ Copyright (C) 1999,2000 Carsten Pfeiffer <pfeiffer@kde.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef OCOMPLETION_H
+#define OCOMPLETION_H
+
+/* QT */
+
+#include <qmap.h>
+#include <qlist.h>
+#include <qobject.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qguardedptr.h>
+
+/* OPIE */
+
+#include <opie2/oglobalsettings.h>
+#include <opie2/osortablevaluelist.h>
+
+/* FORWARDS */
+
+class OCompTreeNode;
+class OCompletionPrivate;
+class OCompletionBasePrivate;
+class OCompletionMatchesWrapper;
+class OCompletionMatches;
+class QPopupMenu;
+
+// FIXME: Do we need special ShortCut handling in Opie? If so, revise this.
+class OShortcut
+{
+public:
+ bool isNull() const { return true; };
+ bool operator == ( const OShortcut& bla ) const { return false; };
+};
+
+
+/**
+ * This class offers easy use of "auto-completion", "manual-completion" or
+ * "shell completion" on QString objects. A common use is completing filenames
+ * or URLs (see @ref OURLCompletion()).
+ * But it is not limited to URL-completion -- everything should be completable!
+ * The user should be able to complete email-addresses, telephone-numbers,
+ * commands, SQL queries, ...
+ * Every time your program knows what the user can type into an edit-field, you
+ * should offer completion. With OCompletion, this is very easy, and if you are
+ * using a line edit widget (@ref OLineEdit), it is even more easy.
+ * Basically, you tell a OCompletion object what strings should be completable
+ * and whenever completion should be invoked, you call @ref makeCompletion().
+ * OLineEdit and (an editable) OComboBox even do this automatically for you.
+ *
+ * OCompletion offers the completed string via the signal @ref match() and
+ * all matching strings (when the result is ambiguous) via the method
+ * @ref allMatches().
+ *
+ * Notice: auto-completion, shell completion and manual completion work
+ * slightly differently:
+ *
+ * @li auto-completion always returns a complete item as match.
+ * When more than one matching items are available, it will deliver just
+ * the first (depending on sorting order) item. Iterating over all matches
+ * is possible via @ref nextMatch() and @ref previousMatch().
+ *
+ * @li popup-completion works in the same way, the only difference being that
+ * the completed items are not put into the edit-widget, but into a
+ * separate popup-box.
+ *
+ * @li manual completion works the same way as auto-completion, the
+ * subtle difference is, that it isn't invoked automatically while the user
+ * is typing, but only when the user presses a special key. The difference
+ * of manual and auto-completion is therefore only visible in UI classes,
+ * OCompletion needs to know whether to deliver partial matches
+ * (shell completion) or whole matches (auto/manual completion), therefore
+ * @ref OGlobalSettings::CompletionMan and
+ * @ref OGlobalSettings::CompletionAuto have the exact same effect in
+ * OCompletion.
+ *
+ * @li shell completion works like how shells complete filenames:
+ * when multiple matches are available, the longest possible string of all
+ * matches is returned (i.e. only a partial item).
+ * Iterating over all matching items (complete, not partial) is possible
+ * via @ref nextMatch() and @ref previousMatch().
+ *
+ * You don't have to worry much about that though, OCompletion handles
+ * that for you, according to the setting @ref setCompletionMode().
+ * The default setting is globally configured by the user and read
+ * from @ref OGlobalSettings::completionMode().
+ *
+ * A short example:
+ * <pre>
+ * OCompletion completion;
+ * completion.setOrder( OCompletion::Sorted );
+ * completion.addItem( "pfeiffer@kde.org" );
+ * completion.addItem( "coolo@kde.org" );
+ * completion.addItem( "carpdjih@sp.zrz.tu-berlin.de" );
+ * completion.addItem( "carp@cs.tu-berlin.de" );
+ *
+ * cout << completion.makeCompletion( "ca" ).latin1() << endl;
+ * </pre>
+ * In shell-completion-mode, this will be "carp"; in auto-completion-
+ * mode it will be "carp@cs.tu-berlin.de", as that is alphabetically
+ * smaller.
+ * If setOrder was set to Insertion, "carpdjih@sp.zrz.tu-berlin.de"
+ * would be completed in auto-completion-mode, as that was inserted before
+ * "carp@cs.tu-berlin.de".
+ *
+ * You can dynamically update the completable items by removing and adding them
+ * whenever you want.
+ * For advanced usage, you could even use multiple OCompletion objects. E.g.
+ * imagine an editor like kwrite with multiple open files. You could store
+ * items of each file in a different OCompletion object, so that you know (and
+ * tell the user) where a completion comes from.
+ *
+ * Note: OCompletion does not work with strings that contain 0x0 characters
+ * (unicode nul), as this is used internally as a delimiter.
+ *
+ * You may inherit from OCompletion and override @ref makeCompletion() in
+ * special cases (like reading directories/urls and then supplying the
+ * contents to OCompletion, as OURLCompletion does), but generally, this is
+ * not necessary.
+ *
+ *
+ * @short A generic class for completing QStrings
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ * @version $Id$
+ */
+
+class OCompletion : public QObject
+{
+ Q_ENUMS( CompOrder )
+ Q_PROPERTY( CompOrder order READ order WRITE setOrder )
+ Q_PROPERTY( bool ignoreCase READ ignoreCase WRITE setIgnoreCase )
+ Q_PROPERTY( QStringList items READ items WRITE setItems )
+ Q_OBJECT
+
+ public:
+ /**
+ * Constants that represent the order in which OCompletion performs
+ * completion-lookups.
+ */
+ enum CompOrder { Sorted, Insertion, Weighted };
+
+ /**
+ * Constructor, nothing special here :)
+ */
+ OCompletion();
+
+ // FIXME: copy constructor, assignment constructor...
+
+ /**
+ * Destructor, nothing special here, either.
+ */
+ virtual ~OCompletion();
+
+ /**
+ * Attempts to find an item in the list of available completions,
+ * that begins with @p string. Will either return the first matching item
+ * (if there is more than one match) or QString::null, if no match was
+ * found.
+ *
+ * In the latter case, a sound will be issued, depending on
+ * @ref isSoundsEnabled().
+ * If a match was found, it will also be emitted via the signal
+ * @ref match().
+ *
+ * If this is called twice or more often with the same string while no
+ * items were added or removed in the meantime, all available completions
+ * will be emitted via the signal @ref matches().
+ * This happens only in shell-completion-mode.
+ *
+ * @returns the matching item, or QString::null if there is no matching
+ * item.
+ * @see #slotMakeCompletion
+ * @see #substringCompletion
+ */
+ virtual QString makeCompletion( const QString& string );
+
+ /**
+ * @returns a list of items which all contain @p text as a substring,
+ * i.e. not necessarily at the beginning.
+ *
+ * @see #makeCompletion
+ */
+ QStringList substringCompletion( const QString& string ) const;
+
+ /**
+ * @returns the next item from the matching-items-list.
+ * When reaching the beginning, the list is rotated so it will return the
+ * last match and a sound is issued (depending on @ref isSoundsEnabled()).
+ * When there is no match, QString::null is returned and
+ * a sound is be issued.
+ * @see #slotPreviousMatch
+ */
+ QString previousMatch();
+
+ /**
+ * @returns the previous item from the matching-items-list
+ * When reaching the last item, the list is rotated, so it will return
+ * the first match and a sound is issued (depending on
+ * @ref isSoundsEnabled()). When there is no match, QString::null is
+ * returned and a sound is issued.
+ * @see #slotNextMatch
+ */
+ QString nextMatch();
+
+ /**
+ * @returns the last match. Might be useful if you need to check whether
+ * a completion is different from the last one.
+ * QString::null is returned when there is no last match.
+ */
+ virtual const QString& lastMatch() const { return myLastMatch; }
+
+ /**
+ * Returns a list of all items inserted into OCompletion. This is useful
+ * if you need to save the state of a OCompletion object and restore it
+ * later.
+ *
+ * Important note: when @ref order() == Weighted, then every item in the
+ * stringlist has its weight appended, delimited by a colon. E.g. an item
+ * "www.kde.org" might look like "www.kde.org:4", where 4 is the weight.
+ *
+ * This is necessary so that you can save the items along with its
+ * weighting on disk and load them back with @ref setItems(), restoring its
+ * weight as well. If you really don't want the appended weightings, call
+ * @ref setOrder( OCompletion::Insertion )
+ * before calling items().
+ *
+ * @returns a list of all items
+ * @see #setItems
+ */
+ QStringList items() const;
+
+ /**
+ * Sets the completion mode to Auto/Manual, Shell or None.
+ * If you don't set the mode explicitly, the global default value
+ * OGlobalSettings::completionMode() is used.
+ * @ref OGlobalSettings::CompletionNone disables completion.
+ * @see #completionMode
+ * @see #OGlobalSettings::completionMode
+ */
+ virtual void setCompletionMode( OGlobalSettings::Completion mode );
+
+ /**
+ * @returns the current completion mode.
+ * May be different from @ref OGlobalSettings::completionMode(), if you
+ * explicitly called @ref setCompletionMode().
+ * @see #setCompletionMode
+ */
+ OGlobalSettings::Completion completionMode() const { return myCompletionMode; };
+
+ /**
+ * OCompletion offers three different ways in which it offers its items:
+ * @li in the order of insertion
+ * @li sorted alphabetically
+ * @li weighted
+ *
+ * Choosing weighted makes OCompletion perform an implicit weighting based
+ * on how often an item is inserted. Imagine a web browser with a location
+ * bar, where the user enters URLs. The more often a URL is entered, the
+ * higher priority it gets.
+ *
+ * Note: Setting the order to sorted only affects new inserted items,
+ * already existing items will stay in the current order. So you probably
+ * want to call setOrder( Sorted ) before inserting items, when you want
+ * everything sorted.
+ *
+ * Default is insertion order
+ * @see #order
+ */
+ virtual void setOrder( CompOrder order );
+
+ /**
+ * @returns the current completion order.
+ * @see #setOrder
+ */
+ CompOrder order() const { return myOrder; }
+
+ /**
+ * Setting this to true makes OCompletion behave case insensitively.
+ * E.g. makeCompletion( "CA" ); might return "carp@cs.tu-berlin.de".
+ * Default is false (case sensitive).
+ * @see #ignoreCase
+ */
+ virtual void setIgnoreCase( bool ignoreCase );
+
+ /**
+ * @returns whether OCompletion acts case insensitively or not.
+ * Default is false (case sensitive).
+ * @see #setIgnoreCase
+ */
+ bool ignoreCase() const { return myIgnoreCase; };
+
+ /**
+ * @returns a list of all items matching the last completed string.
+ * Might take some time, when you have LOTS of items.
+ *
+ * @see #substringCompletion
+ */
+ QStringList allMatches();
+
+ /**
+ * @returns a list of all items matching @p string.
+ */
+ QStringList allMatches( const QString& string );
+
+ /**
+ * @returns a list of all items matching the last completed string.
+ * Might take some time, when you have LOTS of items.
+ * The matches are returned as OCompletionMatches, which also
+ * keeps the weight of the matches, allowing
+ * you to modify some matches or merge them with matches
+ * from another call to allWeightedMatches(), and sort the matches
+ * after that in order to have the matches ordered correctly
+ *
+ * @see #substringCompletion
+ */
+ OCompletionMatches allWeightedMatches();
+
+ /**
+ * @returns a list of all items matching @p string.
+ */
+ OCompletionMatches allWeightedMatches( const QString& string );
+
+ /**
+ * Enables/disables playing a sound when
+ * @li @ref makeCompletion() can't find a match
+ * @li there is a partial completion (= multiple matches in
+ * Shell-completion mode)
+ * @li @ref nextMatch() or @ref previousMatch() hit the last possible
+ * match -> rotation
+ *
+ * For playing the sounds, @ref ONotifyClient() is used. // FIXME: Revise this for Opie
+ *
+ * @see #isSoundsEnabled
+ */
+ virtual void setEnableSounds( bool enable ) { myBeep = enable; }
+
+ /**
+ * Tells you whether OCompletion will play sounds on certain occasions.
+ * Default is enabled
+ * @see #enableSounds
+ * @see #disableSounds
+ */
+ bool isSoundsEnabled() const { return myBeep; };
+
+ /**
+ * @returns true when more than one match is found
+ * @see #multipleMatches
+ */
+ bool hasMultipleMatches() const { return myHasMultipleMatches; };
+
+ public slots:
+ /**
+ * Attempts to complete "string" and emits the completion via @ref match().
+ * Same as @ref makeCompletion() (just as a slot).
+ * @see #makeCompletion
+ */
+ void slotMakeCompletion( const QString& string ) { (void) makeCompletion( string ); };
+
+ /**
+ * Searches the previous matching item and emits it via @ref match()
+ * Same as @ref previousMatch() (just as a slot).
+ * @see #previousMatch
+ */
+ void slotPreviousMatch() { (void) previousMatch(); };
+
+ /**
+ * Searches the next matching item and emits it via @ref match()
+ * Same as @ref nextMatch() (just as a slot).
+ * @see #nextMatch
+ */
+ void slotNextMatch() { (void) nextMatch(); };
+
+ /**
+ * Inserts @p items into the list of possible completions.
+ * Does the same as @ref setItems(), but does not call @ref clear() before.
+ */
+ void insertItems( const QStringList& items );
+
+ /**
+ * Sets the list of items available for completion. Removes all previous
+ * items.
+ *
+ * Notice: when order() == Weighted, then the weighting is looked up for
+ * every item in the stringlist. Every item should have ":number" appended,
+ * where number is an unsigned integer, specifying the weighting.
+ *
+ * If you don't like this, call
+ * setOrder( OCompletion::Insertion )
+ * before calling setItems().
+ *
+ * @see #items
+ */
+ virtual void setItems( const QStringList& );
+
+ /**
+ * Adds an item to the list of available completions.
+ * Resets the current item-state (@ref previousMatch() and @ref nextMatch()
+ * won't work anymore).
+ */
+ void addItem( const QString& );
+
+ /**
+ * Adds an item to the list of available completions.
+ * Resets the current item-state (@ref previousMatch() and @ref nextMatch()
+ * won't work anymore).
+ *
+ * Sets the weighting of the item to @p weight or adds it to the current
+ * weighting if the item is already available. The weight has to be greater
+ * than 1 to take effect (default weight is 1).
+ */
+ void addItem( const QString&, uint weight );
+
+ /**
+ * Removes an item from the list of available completions.
+ * Resets the current item-state (@ref previousMatch() and @ref nextMatch()
+ * won't work anymore).
+ */
+ void removeItem( const QString& );
+
+ /**
+ * Removes all inserted items.
+ */
+ virtual void clear();
+
+ signals:
+ /**
+ * The matching item. Will be emitted by @ref makeCompletion(),
+ * @ref previousMatch() or @ref nextMatch(). May be QString::null if there
+ * is no matching item.
+ */
+ void match( const QString& );
+
+ /**
+ * All matching items. Will be emitted by @ref makeCompletion() in shell-
+ * completion-mode, when the same string is passed to makeCompletion twice
+ * or more often.
+ */
+ void matches( const QStringList& );
+
+ /**
+ * This signal is emitted, when calling @ref makeCompletion() and more than
+ * one matching item is found.
+ * @see #hasMultipleMatches
+ */
+ void multipleMatches();
+
+ protected:
+ /**
+ * This method is called after a completion is found and before the
+ * matching string is emitted. You can override this method to modify the
+ * string that will be emitted.
+ * This is necessary e.g. in @ref OURLCompletion(), where files with spaces
+ * in their names are shown escaped ("filename\ with\ spaces"), but stored
+ * unescaped inside OCompletion.
+ * Never delete that pointer!
+ *
+ * Default implementation does nothing.
+ * @see #postProcessMatches
+ */
+ virtual void postProcessMatch( QString * /*match*/ ) const {}
+
+ /**
+ * This method is called before a list of all available completions is
+ * emitted via @ref matches. You can override this method to modify the
+ * found items before @ref match() or @ref matches() are emitted.
+ * Never delete that pointer!
+ *
+ * Default implementation does nothing.
+ * @see #postProcessMatch
+ */
+ virtual void postProcessMatches( QStringList * /*matches*/ ) const {}
+
+ /**
+ * This method is called before a list of all available completions is
+ * emitted via @ref matches. You can override this method to modify the
+ * found items before @ref match() or @ref matches() are emitted.
+ * Never delete that pointer!
+ *
+ * Default implementation does nothing.
+ * @see #postProcessMatch
+ */
+ virtual void postProcessMatches( OCompletionMatches * /*matches*/ ) const {}
+
+private:
+ void addWeightedItem( const QString& );
+ QString findCompletion( const QString& string );
+ void findAllCompletions( const QString&, OCompletionMatchesWrapper *matches, bool& hasMultipleMatches ) const;
+
+ void extractStringsFromNode( const OCompTreeNode *,
+ const QString& beginning,
+ OCompletionMatchesWrapper *matches,
+ bool addWeight = false ) const;
+ void extractStringsFromNodeCI( const OCompTreeNode *,
+ const QString& beginning,
+ const QString& restString,
+ OCompletionMatchesWrapper *matches) const;
+
+ enum BeepMode { NoMatch, PartialMatch, Rotation };
+ void doBeep( BeepMode ) const;
+
+ OGlobalSettings::Completion myCompletionMode;
+
+ CompOrder myOrder;
+ QString myLastString;
+ QString myLastMatch;
+ QString myCurrentMatch;
+ OCompTreeNode * myTreeRoot;
+ QStringList myRotations;
+ bool myBeep;
+ bool myIgnoreCase;
+ bool myHasMultipleMatches;
+ uint myRotationIndex;
+
+ private:
+ OCompletionPrivate *d;
+};
+
+// some more helper stuff
+typedef OSortableValueList<QString> OCompletionMatchesList;
+class OCompletionMatchesPrivate;
+
+/**
+ * This structure is returned by @ref OCompletion::allWeightedMatches .
+ * It also keeps the weight of the matches, allowing
+ * you to modify some matches or merge them with matches
+ * from another call to allWeightedMatches(), and sort the matches
+ * after that in order to have the matches ordered correctly
+ *
+ * Example (a simplified example of what Oonqueror's completion does):
+ * <pre>
+ * OCompletionMatches matches = completion->allWeightedMatches( location );
+ * if( !location.startsWith( "www." ))
+ matches += completion->allWeightedmatches( "www." + location" );
+ * matches.removeDuplicates();
+ * QStringList list = matches.list();
+ * </pre>
+ *
+ * @short List for keeping matches returned from OCompletion
+ */
+
+class OCompletionMatches
+ : public OCompletionMatchesList
+{
+ public:
+ OCompletionMatches( bool sort );
+ /**
+ * @internal
+ */
+ OCompletionMatches( const OCompletionMatchesWrapper& matches );
+ ~OCompletionMatches();
+ /**
+ * Removes duplicate matches. Needed only when you merged several matches
+ * results and there's a possibility of duplicates.
+ */
+ void removeDuplicates();
+ /**
+ * Returns the matches as a QStringList.
+ * @param sort if false, the matches won't be sorted before the conversion,
+ * use only if you're sure the sorting is not needed
+ */
+ QStringList list( bool sort = true ) const;
+ /**
+ * If sorting() returns false, the matches aren't sorted by their weight,
+ * even if true is passed to list().
+ */
+ bool sorting() const {
+ return _sorting;
+ }
+private:
+ bool _sorting;
+ OCompletionMatchesPrivate* d;
+};
+
+#endif // OCOMPLETION_H
diff --git a/libopie2/qt3/opiecore/ocompletionbase.cpp b/libopie2/qt3/opiecore/ocompletionbase.cpp
new file mode 100644
index 0000000..6ff129a
--- a/dev/null
+++ b/libopie2/qt3/opiecore/ocompletionbase.cpp
@@ -0,0 +1,171 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ Inspired by the KDE completion classes which are
+ Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <opie2/ocompletion.h>
+#include <opie2/ocompletionbase.h>
+
+OCompletionBase::OCompletionBase()
+{
+ m_delegate = 0L;
+ // Assign the default completion type to use.
+ m_iCompletionMode = OGlobalSettings::completionMode();
+
+ // Initialize all key-bindings to 0 by default so that
+ // the event filter will use the global settings.
+ useGlobalKeyBindings();
+
+ // By default we initialize everything to false.
+ // All the variables would be setup properly when
+ // the appropriate member functions are called.
+ setup( false, false, false );
+}
+
+OCompletionBase::~OCompletionBase()
+{
+ if( m_bAutoDelCompObj && m_pCompObj )
+ {
+ delete m_pCompObj;
+ }
+}
+
+void OCompletionBase::setDelegate( OCompletionBase *delegate )
+{
+ m_delegate = delegate;
+
+ if ( m_delegate ) {
+ m_delegate->m_bAutoDelCompObj = m_bAutoDelCompObj;
+ m_delegate->m_bHandleSignals = m_bHandleSignals;
+ m_delegate->m_bEmitSignals = m_bEmitSignals;
+ m_delegate->m_iCompletionMode = m_iCompletionMode;
+ m_delegate->m_keyMap = m_keyMap;
+ }
+}
+
+OCompletion* OCompletionBase::completionObject( bool hsig )
+{
+ if ( m_delegate )
+ return m_delegate->completionObject( hsig );
+
+ if ( !m_pCompObj )
+ {
+ setCompletionObject( new OCompletion(), hsig );
+ m_bAutoDelCompObj = true;
+ }
+ return m_pCompObj;
+}
+
+void OCompletionBase::setCompletionObject( OCompletion* compObj, bool hsig )
+{
+ if ( m_delegate ) {
+ m_delegate->setCompletionObject( compObj, hsig );
+ return;
+ }
+
+ if ( m_bAutoDelCompObj && compObj != m_pCompObj )
+ delete m_pCompObj;
+
+ m_pCompObj = compObj;
+
+ // We emit rotation and completion signals
+ // if completion object is not NULL.
+ setup( false, hsig, !m_pCompObj.isNull() );
+}
+
+// BC: Inline this function and possibly rename it to setHandleEvents??? (DA)
+void OCompletionBase::setHandleSignals( bool handle )
+{
+ if ( m_delegate )
+ m_delegate->setHandleSignals( handle );
+ else
+ m_bHandleSignals = handle;
+}
+
+void OCompletionBase::setCompletionMode( OGlobalSettings::Completion mode )
+{
+ if ( m_delegate ) {
+ m_delegate->setCompletionMode( mode );
+ return;
+ }
+
+ m_iCompletionMode = mode;
+ // Always sync up OCompletion mode with ours as long as we
+ // are performing completions.
+ if( m_pCompObj && m_iCompletionMode != OGlobalSettings::CompletionNone )
+ m_pCompObj->setCompletionMode( m_iCompletionMode );
+}
+
+bool OCompletionBase::setKeyBinding( KeyBindingType item, const OShortcut& cut )
+{
+ if ( m_delegate )
+ return m_delegate->setKeyBinding( item, cut );
+
+
+ if( !cut.isNull() )
+ {
+ for( KeyBindingMap::Iterator it = m_keyMap.begin(); it != m_keyMap.end(); ++it )
+ if( it.data() == cut ) return false;
+ }
+ m_keyMap.replace( item, cut );
+ return true;
+}
+
+void OCompletionBase::useGlobalKeyBindings()
+{
+
+/*
+
+ if ( m_delegate ) {
+ m_delegate->useGlobalKeyBindings();
+ return;
+ }
+
+ m_keyMap.clear();
+ m_keyMap.insert( TextCompletion, 0 );
+ m_keyMap.insert( PrevCompletionMatch, 0 );
+ m_keyMap.insert( NextCompletionMatch, 0 );
+ m_keyMap.insert( SubstringCompletion, 0 );
+
+*/
+
+}
+
+void OCompletionBase::setup( bool autodel, bool hsig, bool esig )
+{
+ if ( m_delegate ) {
+ m_delegate->setup( autodel, hsig, esig );
+ return;
+ }
+
+ m_bAutoDelCompObj = autodel;
+ m_bHandleSignals = hsig;
+ m_bEmitSignals = esig;
+}
diff --git a/libopie2/qt3/opiecore/ocompletionbase.h b/libopie2/qt3/opiecore/ocompletionbase.h
new file mode 100644
index 0000000..517667e
--- a/dev/null
+++ b/libopie2/qt3/opiecore/ocompletionbase.h
@@ -0,0 +1,403 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ Inspired by the KDE completion classes which are
+ Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef OCOMPLETIONBASE_H
+#define OCOMPLETIONBASE_H
+
+/**
+ * An abstract base class for adding a completion feature
+ * into widgets.
+ *
+ * This is a convenience class that provides the basic functions
+ * needed to add text completion support into widgets. All that
+ * is required is an implementation for the pure virtual function
+ * @ref setCompletedText. Refer to @ref OLineEdit or @ref OComboBox
+ * to see how easily such support can be added using this as a base
+ * class.
+ *
+ * @short An abstract class for adding text completion support to widgets.
+ * @author Dawit Alemayehu <adawit@kde.org>
+ */
+
+class OCompletionBase
+{
+
+ public:
+
+ /**
+ * Constants that represent the items whose short-cut
+ * key-binding is programmable. The default key-bindings
+ * for these items are defined in @ref OStdAccel.
+ */
+ enum KeyBindingType {
+ /**
+ * Text completion (by default Ctrl-E).
+ */
+ TextCompletion,
+ /**
+ * Switch to previous completion (by default Ctrl-Up).
+ */
+ PrevCompletionMatch,
+ /**
+ * Switch to next completion (by default Ctrl-Down).
+ */
+ NextCompletionMatch,
+ /**
+ * Substring completion (by default Ctrl-T).
+ */
+ SubstringCompletion
+ };
+
+
+ // Map for the key binding types mentioned above.
+ typedef QMap<KeyBindingType, OShortcut> KeyBindingMap;
+
+ /**
+ * Default constructor.
+ */
+ OCompletionBase();
+
+ /**
+ * Destructor.
+ */
+ virtual ~OCompletionBase();
+
+ /**
+ * Returns a pointer to the current completion object.
+ *
+ * If the object does not exist, it is automatically
+ * created. Note that the completion object created
+ * here is used by default to handle the signals
+ * internally. It is also deleted when this object's
+ * destructor is invoked. If you do not want these
+ * default settings, use @ref setAutoDeleteCompletionObject
+ * and @ref setHandleSignals to change the behavior.
+ * Alternatively, you can set the boolean parameter to
+ * false to disable the automatic handling of the signals
+ * by this object. Note that the boolean argument will be
+ * ignored if there already exists a completion object since
+ * no new object needs to be created. You need to use either
+ * @ref setHandleSignals or @ref setCompletionObject for
+ * such cases depending on your requirement.
+ *
+ * @param hsig if true, handles signals internally.
+ * @return a pointer the completion object.
+ */
+ OCompletion* completionObject( bool hsig = true );
+
+ /**
+ * Sets up the completion object to be used.
+ *
+ * This method assigns the completion object and sets it
+ * up to automatically handle the completion and rotation
+ * signals internally. You should use this function if
+ * you want to share one completion object among you widgets
+ * or need to use a customized completion object.
+ *
+ * The object assigned through this method is not deleted
+ * when this object's destructor is invoked unless you
+ * explicitly call @ref setAutoDeleteCompletionObject after
+ * calling this method. Also if you do not want the signals
+ * to be handled by an internal implementation, be sure to
+ * set the bool argument to false.
+ *
+ * This method is also called when a completion-object is created
+ * automatically, when completionObject() is called the first time.
+ *
+ * @param compObj a @ref OCompletion() or a derived child object.
+ * @param hsig if true, handles signals internally.
+ */
+ virtual void setCompletionObject( OCompletion* /*compObj*/, bool hsig = true );
+
+ /**
+ * Enables this object to handle completion and rotation
+ * events internally.
+ *
+ * This function simply assigns a boolean value that
+ * indicates whether it should handle rotation and
+ * completion events or not. Note that this does not
+ * stop the object from emitting signals when these
+ * events occur.
+ *
+ * @param handle if true, handle completion & rotation internally.
+ */
+ virtual void setHandleSignals( bool /*handle*/ );
+
+ /**
+ * Returns true if the completion object is deleted
+ * upon this widget's destruction.
+ *
+ * See @ref setCompletionObject() and @ref enableCompletion()
+ * for details.
+ *
+ * @return true if the completion object
+ */
+ bool isCompletionObjectAutoDeleted() const {
+ return m_delegate ? m_delegate->isCompletionObjectAutoDeleted() : m_bAutoDelCompObj;
+ }
+
+ /**
+ * Sets the completion object when this widget's destructor
+ * is called.
+ *
+ * If the argument is set to true, the completion object
+ * is deleted when this widget's destructor is called.
+ *
+ * @param autoDelete if true, delete completion object on destruction.
+ */
+ void setAutoDeleteCompletionObject( bool autoDelete ) {
+ if ( m_delegate )
+ m_delegate->setAutoDeleteCompletionObject( autoDelete );
+ else
+ m_bAutoDelCompObj = autoDelete;
+ }
+
+ /**
+ * Sets the widget's ability to emit text completion and
+ * rotation signals.
+ *
+ * Invoking this function with @p enable set to @p false will
+ * cause the completion & rotation signals not to be emitted.
+ * However, unlike setting the completion object to @p NULL
+ * using @ref setCompletionObject, disabling the emition of
+ * the signals through this method does not affect the current
+ * completion object.
+ *
+ * There is no need to invoke this function by default. When a
+ * completion object is created through @ref completionObject or
+ * @ref setCompletionObject, these signals are set to emit
+ * automatically. Also note that disabling this signals will not
+ * necessarily interfere with the objects ability to handle these
+ * events internally. See @ref setHandleSignals.
+ *
+ * @param enable if false, disables the emition of completion & rotation signals.
+ */
+ void setEnableSignals( bool enable ) {
+ if ( m_delegate )
+ m_delegate->setEnableSignals( enable );
+ else
+ m_bEmitSignals = enable;
+ }
+
+ /**
+ * Returns true if the object handles the signals
+ *
+ * @return true if this signals are handled internally.
+ */
+ bool handleSignals() const { return m_delegate ? m_delegate->handleSignals() : m_bHandleSignals; }
+
+ /**
+ * Returns true if the object emits the signals
+ *
+ * @return true if signals are emitted
+ */
+ bool emitSignals() const { return m_delegate ? m_delegate->emitSignals() : m_bEmitSignals; }
+
+ /**
+ * Sets the type of completion to be used.
+ *
+ * The completion modes supported are those defined in
+ * @ref OGlobalSettings(). See below.
+ *
+ * @param mode Completion type:
+ * @li CompletionNone: Disables completion feature.
+ * @li CompletionAuto: Attempts to find a match &
+ * fills-in the remaining text.
+ * @li CompletionMan: Acts the same as the above
+ * except the action has to be
+ * manually triggered through
+ * pre-defined completion key.
+ * @li CompletionShell: Mimics the completion feature
+ * found in typical *nix shell
+ * environments.
+ * @li CompletionPopup: Shows all available completions at once,
+ * in a listbox popping up.
+ */
+ virtual void setCompletionMode( OGlobalSettings::Completion mode );
+
+ /**
+ * Returns the current completion mode.
+ *
+ * The return values are of type @ref OGlobalSettings::Completion.
+ * See @ref setCompletionMode() for details.
+ *
+ * @return the completion mode.
+ */
+ OGlobalSettings::Completion completionMode() const {
+ return m_delegate ? m_delegate->completionMode() : m_iCompletionMode;
+ }
+
+ /**
+ * Sets the key-binding to be used for manual text
+ * completion, text rotation in a history list as
+ * well as a completion list.
+ *
+ *
+ * When the keys set by this function are pressed, a
+ * signal defined by the inheriting widget will be activated.
+ * If the default value or 0 is specified by the second
+ * parameter, then the key-binding as defined in the global
+ * setting should be used. This method returns false value
+ * for @p key is negative or the supplied key-binding conflicts
+ * with the ones set for one of the other features.
+ *
+ * NOTE: To use a modifier key (Shift, Ctrl, Alt) as part of
+ * the key-binding simply simply @p sum up the values of the
+ * modifier and the actual key. For example, to use CTRL+E as
+ * a key binding for one of the items, you would simply supply
+ * @p "Qt::CtrlButton + Qt::Key_E" as the second argument to this
+ * function.
+ *
+ * @param item the feature whose key-binding needs to be set:
+ *
+ * @li TextCompletion the manual completion key-binding.
+ * @li PrevCompletionMatch the previous match key for multiple completion.
+ * @li NextCompletionMatch the next match key for for multiple completion.
+ * @li SubstringCompletion the key for substring completion
+ *
+ * @param key key-binding used to rotate down in a list.
+ *
+ * @return true if key-binding can successfully be set.
+ * @see #getKeyBinding
+ */
+ bool setKeyBinding( KeyBindingType /*item*/ , const OShortcut& cut );
+
+ /**
+ * Returns the key-binding used for the specified item.
+ *
+ * This methods returns the key-binding used to activate
+ * the feature feature given by @p item. If the binding
+ * contains modifier key(s), the SUM of the modifier key
+ * and the actual key code are returned.
+ *
+ * @return the key-binding used for the feature given by @p item.
+ * @see #setKeyBinding
+ */
+ const OShortcut& getKeyBinding( KeyBindingType item ) const {
+ return m_delegate ? m_delegate->getKeyBinding( item ) : m_keyMap[ item ];
+ }
+
+ /**
+ * Sets this object to use global values for key-bindings.
+ *
+ * This method changes the values of the key bindings for
+ * rotation and completion features to the default values
+ * provided in OGlobalSettings.
+ *
+ * NOTE: By default inheriting widgets should uses the
+ * global key-bindings so that there will be no need to
+ * call this method.
+ */
+ void useGlobalKeyBindings();
+
+ /**
+ * A pure virtual function that must be implemented by
+ * all inheriting classes.
+ *
+ * This function is intended to allow external completion
+ * implementations to set completed text appropriately. It
+ * is mostly relevant when the completion mode is set to
+ * CompletionAuto and CompletionManual modes. See
+ * @ref OCompletionBase::setCompletedText.
+ * Does nothing in CompletionPopup mode, as all available
+ * matches will be shown in the popup.
+ *
+ * @param text the completed text to be set in the widget.
+ */
+ virtual void setCompletedText( const QString& text ) = 0;
+
+ /**
+ * A pure virtual function that must be implemented by
+ * all inheriting classes.
+ *
+ */
+ virtual void setCompletedItems( const QStringList& items ) = 0;
+
+ /**
+ * Returns a pointer to the completion object.
+ *
+ * This method is only different from @ref completionObject()
+ * in that it does not create a new OCompletion object even if
+ * the internal pointer is @p NULL. Use this method to get the
+ * pointer to a completion object when inheriting so that you
+ * won't inadvertently create it!!
+ *
+ * @returns the completion object or NULL if one does not exist.
+ */
+ OCompletion* compObj() const { return m_delegate ? m_delegate->compObj() : (OCompletion*) m_pCompObj; }
+
+protected:
+ /**
+ * Returns a key-binding map
+ *
+ * This method is the same as @ref getKeyBinding() except it
+ * returns the whole keymap containing the key-bindings.
+ *
+ * @return the key-binding used for the feature given by @p item.
+ */
+ KeyBindingMap getKeyBindings() const { return m_delegate ? m_delegate->getKeyBindings() : m_keyMap; }
+
+ void setDelegate( OCompletionBase *delegate );
+ OCompletionBase *delegate() const { return m_delegate; }
+
+private:
+ // This method simply sets the autodelete boolean for
+ // the completion object, the emit signals and handle
+ // signals internally flags to the provided values.
+ void setup( bool, bool, bool );
+
+ // Flag that determined whether the completion object
+ // should be deleted when this object is destroyed.
+ bool m_bAutoDelCompObj;
+ // Determines whether this widget handles completion signals
+ // internally or not
+ bool m_bHandleSignals;
+ // Determines whether this widget fires rotation signals
+ bool m_bEmitSignals;
+ // Stores the completion mode locally.
+ OGlobalSettings::Completion m_iCompletionMode;
+ // Pointer to Completion object.
+ QGuardedPtr<OCompletion> m_pCompObj;
+ // Keybindings
+ KeyBindingMap m_keyMap;
+ // we may act as a proxy to another OCompletionBase object
+ OCompletionBase *m_delegate;
+
+ // FIXME: Revise this for Opie?
+ //protected:
+ // virtual void virtual_hook( int id, void* data );
+ private:
+ OCompletionBasePrivate *d;
+};
+
+#endif // OCOMPLETIONBASE_H
+
diff --git a/libopie2/qt3/opiecore/opair.h b/libopie2/qt3/opiecore/opair.h
new file mode 100644
index 0000000..26f617d
--- a/dev/null
+++ b/libopie2/qt3/opiecore/opair.h
@@ -0,0 +1,99 @@
+// QPair minus QT_INLINE_TEMPLATE (instead directly using 'inline' directive)
+//FIXME: remove and use qpair.h as soon as we're on Qt3
+
+/****************************************************************************
+**
+** Definition of QPair class
+**
+**
+** Copyright (C) 1992-2001 Trolltech AS. All rights reserved.
+**
+** This file is part of the tools module of the Qt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.QPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for QPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef QPAIR_H
+#define QPAIR_H
+
+#ifndef QT_H
+#include "qglobal.h"
+#include "qdatastream.h"
+#endif // QT_H
+
+template <class T1, class T2>
+struct QPair
+{
+ typedef T1 first_type;
+ typedef T2 second_type;
+
+ QPair()
+ : first( T1() ), second( T2() )
+ {}
+ QPair( const T1& t1, const T2& t2 )
+ : first( t1 ), second( t2 )
+ {}
+
+ T1 first;
+ T2 second;
+};
+
+template <class T1, class T2>
+inline bool operator==( const QPair<T1, T2>& x, const QPair<T1, T2>& y )
+{
+ return x.first == y.first && x.second == y.second;
+}
+
+template <class T1, class T2>
+inline bool operator<( const QPair<T1, T2>& x, const QPair<T1, T2>& y )
+{
+ return x.first < y.first ||
+ ( !( y.first < x.first ) && x.second < y.second );
+}
+
+template <class T1, class T2>
+inline QPair<T1, T2> qMakePair( const T1& x, const T2& y )
+{
+ return QPair<T1, T2>( x, y );
+}
+
+#ifndef QT_NO_DATASTREAM
+template <class T1, class T2>
+inline QDataStream& operator>>( QDataStream& s, QPair<T1, T2>& p )
+{
+ s >> p.first >> p.second;
+ return s;
+}
+
+template <class T1, class T2>
+inline QDataStream& operator<<( QDataStream& s, const QPair<T1, T2>& p )
+{
+ s << p.first << p.second;
+ return s;
+}
+#endif
+
+#endif
diff --git a/libopie2/qt3/opiecore/osortablevaluelist.h b/libopie2/qt3/opiecore/osortablevaluelist.h
new file mode 100644
index 0000000..f66cf25
--- a/dev/null
+++ b/libopie2/qt3/opiecore/osortablevaluelist.h
@@ -0,0 +1,117 @@
+/*
+                 This file is part of the Opie Project
+ Originally a part of the KDE Project
+ (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef OSORTABLEVALUELIST_H
+#define OSORTABLEVALUELIST_H
+
+#if QT_VERSION > 290
+#include <qtl.h>
+#include <qpair.h>
+#else
+#include <opie2/otl.h>
+#include <opie2/opair.h>
+#endif
+#include <qvaluelist.h>
+
+template<class T, class Key = int> class OSortableItem : public QPair<Key,T>
+{
+public:
+ OSortableItem( Key i, const T& t ) : QPair<Key, T>( i, t ) {}
+ OSortableItem( const OSortableItem<T, Key> &rhs )
+ : QPair<Key,T>( rhs.first, rhs.second ) {}
+
+ OSortableItem() {}
+
+ OSortableItem<T, Key> &operator=( const OSortableItem<T, Key>& i ) {
+ first = i.first;
+ second = i.second;
+ return *this;
+ }
+
+ // operators for sorting
+ bool operator> ( const OSortableItem<T, Key>& i2 ) const {
+ return (i2.first < first);
+ }
+ bool operator< ( const OSortableItem<T, Key>& i2 ) const {
+ return (first < i2.first);
+ }
+ bool operator>= ( const OSortableItem<T, Key>& i2 ) const {
+ return (first >= i2.first);
+ }
+ bool operator<= ( const OSortableItem<T, Key>& i2 ) const {
+ return !(i2.first < first);
+ }
+ bool operator== ( const OSortableItem<T, Key>& i2 ) const {
+ return (first == i2.first);
+ }
+ bool operator!= ( const OSortableItem<T, Key>& i2 ) const {
+ return (first != i2.first);
+ }
+
+ T& value() {
+ return second;
+ }
+ const T& value() const {
+ return second;
+ }
+
+ Key index() const {
+ return first;
+ }
+};
+
+
+// convenience
+template <class T, class Key = int>
+class OSortableValueList : public QValueList<OSortableItem<T, Key> >
+{
+public:
+ void insert( Key i, const T& t ) {
+ QValueList<OSortableItem<T, Key> >::append( OSortableItem<T, Key>( i, t ) );
+ }
+ // add more as you please...
+
+ T& operator[]( Key i ) {
+ return QValueList<OSortableItem<T, Key> >::operator[]( i ).value();
+ }
+ const T& operator[]( Key i ) const {
+ return QValueList<OSortableItem<T, Key> >::operator[]( i ).value();
+ }
+
+ void sort() {
+ qHeapSort( *this );
+ }
+};
+
+// template <class T> class OSortableValueListIterator : public QValueListIterator<OSortableItem<T> >
+// {
+// };
+
+#endif // OSORTABLEVALUELIST_H
diff --git a/libopie2/qt3/opiecore/otl.h b/libopie2/qt3/opiecore/otl.h
new file mode 100644
index 0000000..ee2a28e
--- a/dev/null
+++ b/libopie2/qt3/opiecore/otl.h
@@ -0,0 +1,325 @@
+// qtl minus QT_INLINE_TEMPLATE and QT_EXPLICIT (instead directly using 'inline' directive)
+//FIXME: remove and use qtl.h as soon as we're on Qt3
+
+/****************************************************************************
+** $Id$
+**
+** Definition of Qt template library classes
+**
+** Created : 990128
+**
+** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
+**
+** This file is part of the tools module of the Qt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.QPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for QPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef QTL_H
+#define QTL_H
+
+#ifndef QT_H
+#include "qglobal.h"
+#include "qtextstream.h"
+#include "qstring.h"
+#endif // QT_H
+
+#ifndef QT_NO_TEXTSTREAM
+template <class T>
+class QTextOStreamIterator
+{
+protected:
+ QTextOStream& stream;
+ QString separator;
+
+public:
+ QTextOStreamIterator( QTextOStream& s) : stream( s ) {}
+ QTextOStreamIterator( QTextOStream& s, const QString& sep )
+ : stream( s ), separator( sep ) {}
+ QTextOStreamIterator<T>& operator= ( const T& x ) {
+ stream << x;
+ if ( !separator.isEmpty() )
+ stream << separator;
+ return *this;
+ }
+ QTextOStreamIterator<T>& operator*() { return *this; }
+ QTextOStreamIterator<T>& operator++() { return *this; }
+ QTextOStreamIterator<T>& operator++(int) { return *this; }
+};
+#endif //QT_NO_TEXTSTREAM
+
+template <class InputIterator, class OutputIterator>
+inline OutputIterator qCopy( InputIterator _begin, InputIterator _end,
+ OutputIterator _dest )
+{
+ while( _begin != _end )
+ *_dest++ = *_begin++;
+ return _dest;
+}
+
+template <class BiIterator, class BiOutputIterator>
+inline BiOutputIterator qCopyBackward( BiIterator _begin, BiIterator _end,
+ BiOutputIterator _dest )
+{
+ while ( _begin != _end )
+ *--_dest = *--_end;
+ return _dest;
+}
+
+template <class InputIterator1, class InputIterator2>
+inline bool qEqual( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2 )
+{
+ // ### compare using !(*first1 == *first2) in Qt 4.0
+ for ( ; first1 != last1; ++first1, ++first2 )
+ if ( *first1 != *first2 )
+ return FALSE;
+ return TRUE;
+}
+
+template <class ForwardIterator, class T>
+inline void qFill( ForwardIterator first, ForwardIterator last, const T& val )
+{
+ for ( ; first != last; ++first )
+ *first = val;
+}
+
+#if 0
+template <class BiIterator, class OutputIterator>
+inline OutputIterator qReverseCopy( BiIterator _begin, BiIterator _end,
+ OutputIterator _dest )
+{
+ while ( _begin != _end ) {
+ --_end;
+ *_dest = *_end;
+ ++_dest;
+ }
+ return _dest;
+}
+#endif
+
+
+template <class InputIterator, class T>
+inline InputIterator qFind( InputIterator first, InputIterator last,
+ const T& val )
+{
+ while ( first != last && *first != val )
+ ++first;
+ return first;
+}
+
+template <class InputIterator, class T, class Size>
+inline void qCount( InputIterator first, InputIterator last, const T& value,
+ Size& n )
+{
+ for ( ; first != last; ++first )
+ if ( *first == value )
+ ++n;
+}
+
+template <class T>
+inline void qSwap( T& _value1, T& _value2 )
+{
+ T tmp = _value1;
+ _value1 = _value2;
+ _value2 = tmp;
+}
+
+
+template <class InputIterator>
+inline void qBubbleSort( InputIterator b, InputIterator e )
+{
+ // Goto last element;
+ InputIterator last = e;
+ --last;
+ // only one element or no elements ?
+ if ( last == b )
+ return;
+
+ // So we have at least two elements in here
+ while( b != last ) {
+ bool swapped = FALSE;
+ InputIterator swap_pos = b;
+ InputIterator x = e;
+ InputIterator y = x;
+ y--;
+ do {
+ --x;
+ --y;
+ if ( *x < *y ) {
+ swapped = TRUE;
+ qSwap( *x, *y );
+ swap_pos = y;
+ }
+ } while( y != b );
+ if ( !swapped )
+ return;
+ b = swap_pos;
+ b++;
+ }
+}
+
+
+template <class Container>
+inline void qBubbleSort( Container &c )
+{
+ qBubbleSort( c.begin(), c.end() );
+}
+
+
+template <class Value>
+inline void qHeapSortPushDown( Value* heap, int first, int last )
+{
+ int r = first;
+ while ( r <= last / 2 ) {
+ if ( last == 2 * r ) {
+ // node r has only one child
+ if ( heap[2 * r] < heap[r] )
+ qSwap( heap[r], heap[2 * r] );
+ r = last;
+ } else {
+ // node r has two children
+ if ( heap[2 * r] < heap[r] && !(heap[2 * r + 1] < heap[2 * r]) ) {
+ // swap with left child
+ qSwap( heap[r], heap[2 * r] );
+ r *= 2;
+ } else if ( heap[2 * r + 1] < heap[r]
+ && heap[2 * r + 1] < heap[2 * r] ) {
+ // swap with right child
+ qSwap( heap[r], heap[2 * r + 1] );
+ r = 2 * r + 1;
+ } else {
+ r = last;
+ }
+ }
+ }
+}
+
+
+template <class InputIterator, class Value>
+inline void qHeapSortHelper( InputIterator b, InputIterator e, Value, uint n )
+{
+ // Create the heap
+ InputIterator insert = b;
+ Value* realheap = new Value[n];
+ // Wow, what a fake. But I want the heap to be indexed as 1...n
+ Value* heap = realheap - 1;
+ int size = 0;
+ for( ; insert != e; ++insert ) {
+ heap[++size] = *insert;
+ int i = size;
+ while( i > 1 && heap[i] < heap[i / 2] ) {
+ qSwap( heap[i], heap[i / 2] );
+ i /= 2;
+ }
+ }
+
+ // Now do the sorting
+ for( uint i = n; i > 0; i-- ) {
+ *b++ = heap[1];
+ if ( i > 1 ) {
+ heap[1] = heap[i];
+ qHeapSortPushDown( heap, 1, (int)i - 1 );
+ }
+ }
+
+ delete[] realheap;
+}
+
+
+template <class InputIterator>
+inline void qHeapSort( InputIterator b, InputIterator e )
+{
+ // Empty ?
+ if ( b == e )
+ return;
+
+ // How many entries have to be sorted ?
+ InputIterator it = b;
+ uint n = 0;
+ while ( it != e ) {
+ ++n;
+ ++it;
+ }
+
+ // The second last parameter is a hack to retrieve the value type
+ // Do the real sorting here
+ qHeapSortHelper( b, e, *b, n );
+}
+
+
+template <class Container>
+inline void qHeapSort( Container &c )
+{
+ if ( c.begin() == c.end() )
+ return;
+
+ // The second last parameter is a hack to retrieve the value type
+ // Do the real sorting here
+ qHeapSortHelper( c.begin(), c.end(), *(c.begin()), (uint)c.count() );
+}
+
+template <class Container>
+class QBackInsertIterator
+{
+public:
+ QBackInsertIterator( Container &c )
+ : container( &c )
+ {
+ }
+
+ QBackInsertIterator<Container>&
+ operator=( const typename Container::value_type &value )
+ {
+ container->push_back( value );
+ return *this;
+ }
+
+ QBackInsertIterator<Container>& operator*()
+ {
+ return *this;
+ }
+
+ QBackInsertIterator<Container>& operator++()
+ {
+ return *this;
+ }
+
+ QBackInsertIterator<Container>& operator++(int)
+ {
+ return *this;
+ }
+
+protected:
+ Container *container;
+};
+
+template <class Container>
+inline QBackInsertIterator<Container> qBackInserter( Container &c )
+{
+ return QBackInsertIterator<Container>( c );
+}
+
+#endif
diff --git a/libopie2/qt3/opieui/ocombobox.cpp b/libopie2/qt3/opieui/ocombobox.cpp
new file mode 100644
index 0000000..a1dd5f5
--- a/dev/null
+++ b/libopie2/qt3/opieui/ocombobox.cpp
@@ -0,0 +1,666 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+ Opie Project Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
+
+ =. Originally part of the KDE Project
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* QT */
+
+#include <qclipboard.h>
+#include <qlistbox.h>
+#include <qpopupmenu.h>
+
+/* OPIE */
+
+#include <opie2/ocompletionbox.h>
+#include <opie2/olineedit.h>
+#include <opie2/opixmapprovider.h>
+#include <opie2/ocombobox.h>
+
+/*======================================================================================
+ * OComboBoxPrivate
+ *======================================================================================*/
+
+class OComboBox::OComboBoxPrivate
+{
+public:
+ OComboBoxPrivate()
+ {
+ olineEdit = 0L;
+ }
+ ~OComboBoxPrivate()
+ {
+ }
+
+ OLineEdit *olineEdit;
+};
+
+/*======================================================================================
+ * OComboBox
+ *======================================================================================*/
+
+OComboBox::OComboBox( QWidget *parent, const char *name )
+ : QComboBox( parent, name )
+{
+ init();
+}
+
+OComboBox::OComboBox( bool rw, QWidget *parent, const char *name )
+ : QComboBox( rw, parent, name )
+{
+ init();
+
+ if ( rw )
+ {
+ OLineEdit *edit = new OLineEdit( this, "combo lineedit" );
+ setLineEdit( edit );
+ }
+}
+
+OComboBox::~OComboBox()
+{
+ delete d;
+}
+
+void OComboBox::init()
+{
+ d = new OComboBoxPrivate;
+
+ // Permanently set some parameters in the parent object.
+ QComboBox::setAutoCompletion( false );
+
+ // Initialize enable popup menu to false.
+ // Below it will be enabled if the widget
+ // is editable.
+ m_bEnableMenu = false;
+
+ m_trapReturnKey = false;
+
+ // Enable context menu by default if widget
+ // is editable.
+ setContextMenuEnabled( true );
+
+ // for wheelscrolling
+ installEventFilter( this );
+ if ( lineEdit() )
+ lineEdit()->installEventFilter( this );
+}
+
+
+bool OComboBox::contains( const QString& _text ) const
+{
+ if ( _text.isEmpty() )
+ return false;
+
+ for (int i = 0; i < count(); i++ ) {
+ if ( text(i) == _text )
+ return true;
+ }
+ return false;
+}
+
+void OComboBox::setAutoCompletion( bool autocomplete )
+{
+ if ( d->olineEdit )
+ {
+ if ( autocomplete )
+ {
+ d->olineEdit->setCompletionMode( OGlobalSettings::CompletionAuto );
+ setCompletionMode( OGlobalSettings::CompletionAuto );
+ }
+ else
+ {
+ d->olineEdit->setCompletionMode( OGlobalSettings::completionMode() );
+ setCompletionMode( OGlobalSettings::completionMode() );
+ }
+ }
+}
+
+void OComboBox::setContextMenuEnabled( bool showMenu )
+{
+ if( d->olineEdit )
+ {
+ d->olineEdit->setContextMenuEnabled( showMenu );
+ m_bEnableMenu = showMenu;
+ }
+}
+
+/*
+void OComboBox::setURLDropsEnabled( bool enable )
+{
+ if ( d->olineEdit )
+ d->olineEdit->setURLDropsEnabled( enable );
+}
+
+bool OComboBox::isURLDropsEnabled() const
+{
+ return d->olineEdit && d->olineEdit->isURLDropsEnabled();
+}
+*/
+
+void OComboBox::setCompletedText( const QString& text, bool marked )
+{
+ if ( d->olineEdit )
+ d->olineEdit->setCompletedText( text, marked );
+}
+
+void OComboBox::setCompletedText( const QString& text )
+{
+ if ( d->olineEdit )
+ d->olineEdit->setCompletedText( text );
+}
+
+void OComboBox::makeCompletion( const QString& text )
+{
+ if( d->olineEdit )
+ d->olineEdit->makeCompletion( text );
+
+ else // read-only combo completion
+ {
+ if( text.isNull() || !listBox() )
+ return;
+
+ int index = listBox()->index( listBox()->findItem( text ) );
+ if( index >= 0 ) {
+ setCurrentItem( index );
+ }
+ }
+}
+
+void OComboBox::rotateText( OCompletionBase::KeyBindingType type )
+{
+ if ( d->olineEdit )
+ d->olineEdit->rotateText( type );
+}
+
+bool OComboBox::eventFilter( QObject* o, QEvent* ev )
+{
+ QLineEdit *edit = lineEdit();
+
+ int type = ev->type();
+
+ if ( o == edit )
+ {
+ //OCursor::autoHideEventFilter( edit, ev );
+
+ if ( type == QEvent::KeyPress )
+ {
+ QKeyEvent *e = static_cast<QKeyEvent *>( ev );
+
+ if ( e->key() == Key_Return || e->key() == Key_Enter)
+ {
+ // On Return pressed event, emit both
+ // returnPressed(const QString&) and returnPressed() signals
+ emit returnPressed();
+ emit returnPressed( currentText() );
+ if ( d->olineEdit && d->olineEdit->completionBox(false) &&
+ d->olineEdit->completionBox()->isVisible() )
+ d->olineEdit->completionBox()->hide();
+
+ return m_trapReturnKey;
+ }
+ }
+ }
+
+
+ // wheel-scrolling changes the current item
+ if ( type == QEvent::Wheel ) {
+ if ( !listBox() || listBox()->isHidden() ) {
+ QWheelEvent *e = static_cast<QWheelEvent*>( ev );
+ static const int WHEEL_DELTA = 120;
+ int skipItems = e->delta() / WHEEL_DELTA;
+ if ( e->state() & ControlButton ) // fast skipping
+ skipItems *= 10;
+
+ int newItem = currentItem() - skipItems;
+
+ if ( newItem < 0 )
+ newItem = 0;
+ else if ( newItem >= count() )
+ newItem = count() -1;
+
+ setCurrentItem( newItem );
+ if ( !text( newItem ).isNull() )
+ emit activated( text( newItem ) );
+ emit activated( newItem );
+ e->accept();
+ return true;
+ }
+ }
+
+ return QComboBox::eventFilter( o, ev );
+}
+
+void OComboBox::setTrapReturnKey( bool grab )
+{
+ m_trapReturnKey = grab;
+}
+
+bool OComboBox::trapReturnKey() const
+{
+ return m_trapReturnKey;
+}
+
+/*
+void OComboBox::setEditURL( const OURL& url )
+{
+ QComboBox::setEditText( url.prettyURL() );
+}
+
+void OComboBox::insertURL( const OURL& url, int index )
+{
+ QComboBox::insertItem( url.prettyURL(), index );
+}
+
+void OComboBox::insertURL( const QPixmap& pixmap, const OURL& url, int index )
+{
+ QComboBox::insertItem( pixmap, url.prettyURL(), index );
+}
+
+void OComboBox::changeURL( const OURL& url, int index )
+{
+ QComboBox::changeItem( url.prettyURL(), index );
+}
+
+void OComboBox::changeURL( const QPixmap& pixmap, const OURL& url, int index )
+{
+ QComboBox::changeItem( pixmap, url.prettyURL(), index );
+}
+*/
+
+
+void OComboBox::setCompletedItems( const QStringList& items )
+{
+ if ( d->olineEdit )
+ d->olineEdit->setCompletedItems( items );
+}
+
+
+OCompletionBox * OComboBox::completionBox( bool create )
+{
+ if ( d->olineEdit )
+ return d->olineEdit->completionBox( create );
+ return 0;
+}
+
+// QWidget::create() turns off mouse-Tracking which would break auto-hiding
+void OComboBox::create( WId id, bool initializeWindow, bool destroyOldWindow )
+{
+ QComboBox::create( id, initializeWindow, destroyOldWindow );
+ //OCursor::setAutoHideCursor( lineEdit(), true, true );
+}
+
+void OComboBox::setLineEdit( OLineEdit *edit )
+{
+ #if QT_VERSION > 290
+ QComboBox::setLineEdit( edit );
+ d->olineEdit = dynamic_cast<OLineEdit*>( edit );
+ setDelegate( d->olineEdit );
+
+ // forward some signals. We only emit returnPressed() ourselves.
+ if ( d->olineEdit ) {
+ connect( d->olineEdit, SIGNAL( completion( const QString& )),
+ SIGNAL( completion( const QString& )) );
+ connect( d->olineEdit, SIGNAL( substringCompletion( const QString& )),
+ SIGNAL( substringCompletion( const QString& )) );
+ connect( d->olineEdit,
+ SIGNAL( textRotation( OCompletionBase::KeyBindingType )),
+ SIGNAL( textRotation( OCompletionBase::KeyBindingType )) );
+ connect( d->olineEdit,
+ SIGNAL( completionModeChanged( OGlobalSettings::Completion )),
+ SIGNAL( completionModeChanged( OGlobalSettings::Completion)));
+
+ connect( d->olineEdit,
+ SIGNAL( aboutToShowContextMenu( QPopupMenu * )),
+ SIGNAL( aboutToShowContextMenu( QPopupMenu * )) );
+ }
+ #else
+ #warning OComboBox is not fully functional with Qt2
+ #endif
+}
+
+// Temporary functions until QT3 appears. - Seth Chaiklin 20 may 2001
+void OComboBox::deleteWordForward()
+{
+ lineEdit()->cursorWordForward(TRUE);
+ #if QT_VERSION > 290
+ if ( lineEdit()->hasSelectedText() )
+ #else
+ if ( lineEdit()->hasMarkedText() )
+ #endif
+ {
+ lineEdit()->del();
+ }
+}
+
+void OComboBox::deleteWordBack()
+{
+ lineEdit()->cursorWordBackward(TRUE);
+ #if QT_VERSION > 290
+ if ( lineEdit()->hasSelectedText() )
+ #else
+ if ( lineEdit()->hasMarkedText() )
+ #endif
+ {
+ lineEdit()->del();
+ }
+}
+
+void OComboBox::setCurrentItem( const QString& item, bool insert, int index )
+{
+ int sel = -1;
+ for (int i = 0; i < count(); ++i)
+ if (text(i) == item)
+ {
+ sel = i;
+ break;
+ }
+ if (sel == -1 && insert)
+ {
+ insertItem(item, index);
+ if (index >= 0)
+ sel = index;
+ else
+ sel = count() - 1;
+ }
+ setCurrentItem(sel);
+}
+
+void OComboBox::setCurrentItem(int index)
+{
+ QComboBox::setCurrentItem(index);
+}
+
+
+/*======================================================================================
+ * OHistoryCombo
+ *======================================================================================*/
+
+// we are always read-write
+OHistoryCombo::OHistoryCombo( QWidget *parent, const char *name )
+ : OComboBox( true, parent, name )
+{
+ init( true ); // using completion
+}
+
+// we are always read-write
+OHistoryCombo::OHistoryCombo( bool useCompletion,
+ QWidget *parent, const char *name )
+ : OComboBox( true, parent, name )
+{
+ init( useCompletion );
+}
+
+void OHistoryCombo::init( bool useCompletion )
+{
+ if ( useCompletion )
+ completionObject()->setOrder( OCompletion::Weighted );
+
+ setInsertionPolicy( NoInsertion );
+ myIterateIndex = -1;
+ myRotated = false;
+ myPixProvider = 0L;
+
+ connect( this, SIGNAL(aboutToShowContextMenu(QPopupMenu*)),
+ SLOT(addContextMenuItems(QPopupMenu*)) );
+ connect( this, SIGNAL( activated(int) ), SLOT( slotReset() ));
+ connect( this, SIGNAL( returnPressed(const QString&) ), SLOT(slotReset()));
+}
+
+OHistoryCombo::~OHistoryCombo()
+{
+ delete myPixProvider;
+}
+
+void OHistoryCombo::setHistoryItems( QStringList items,
+ bool setCompletionList )
+{
+ OComboBox::clear();
+
+ // limit to maxCount()
+ while ( (int) items.count() > maxCount() && !items.isEmpty() )
+ items.remove( items.begin() );
+
+ insertItems( items );
+
+ if ( setCompletionList && useCompletion() ) {
+ // we don't have any weighting information here ;(
+ OCompletion *comp = completionObject();
+ comp->setOrder( OCompletion::Insertion );
+ comp->setItems( items );
+ comp->setOrder( OCompletion::Weighted );
+ }
+
+ clearEdit();
+}
+
+QStringList OHistoryCombo::historyItems() const
+{
+ QStringList list;
+ for ( int i = 0; i < count(); i++ )
+ list.append( text( i ) );
+
+ return list;
+}
+
+void OHistoryCombo::clearHistory()
+{
+ OComboBox::clear();
+ if ( useCompletion() )
+ completionObject()->clear();
+}
+
+void OHistoryCombo::addContextMenuItems( QPopupMenu* menu )
+{
+ if ( menu &&!lineEdit()->text().isEmpty())
+ {
+ menu->insertSeparator();
+ menu->insertItem( tr("Empty Contents"), this, SLOT( slotClear()));
+ }
+}
+
+void OHistoryCombo::addToHistory( const QString& item )
+{
+ if ( item.isEmpty() || (count() > 0 && item == text(0) ))
+ return;
+
+ // remove all existing items before adding
+ if ( !duplicatesEnabled() ) {
+ for ( int i = 0; i < count(); i++ ) {
+ if ( text( i ) == item )
+ removeItem( i );
+ }
+ }
+
+ // now add the item
+ if ( myPixProvider )
+ //insertItem( myPixProvider->pixmapFor(item, KIcon::SizeSmall), item, 0);
+ insertItem( myPixProvider->pixmapFor(item, 16), item, 0);
+ else
+ insertItem( item, 0 );
+
+ int last;
+ QString rmItem;
+
+ bool useComp = useCompletion();
+ while ( count() > maxCount() && count() > 0 ) {
+ // remove the last item, as long as we are longer than maxCount()
+ // remove the removed item from the completionObject if it isn't
+ // anymore available at all in the combobox.
+ last = count() - 1;
+ rmItem = text( last );
+ removeItem( last );
+ if ( useComp && !contains( rmItem ) )
+ completionObject()->removeItem( rmItem );
+ }
+
+ if ( useComp )
+ completionObject()->addItem( item );
+}
+
+bool OHistoryCombo::removeFromHistory( const QString& item )
+{
+ if ( item.isEmpty() )
+ return false;
+
+ bool removed = false;
+ QString temp = currentText();
+ for ( int i = 0; i < count(); i++ ) {
+ while ( item == text( i ) ) {
+ removed = true;
+ removeItem( i );
+ }
+ }
+
+ if ( removed && useCompletion() )
+ completionObject()->removeItem( item );
+
+ setEditText( temp );
+ return removed;
+}
+
+void OHistoryCombo::keyPressEvent( QKeyEvent *e )
+{
+ // save the current text in the lineedit
+ if ( myIterateIndex == -1 )
+ myText = currentText();
+
+ // going up in the history, rotating when reaching QListBox::count()
+ //if ( OStdAccel::isEqual( e, OStdAccel::rotateUp() ) ) {
+ if ( e->key() == Qt::Key_Up ) {
+ myIterateIndex++;
+
+ // skip duplicates/empty items
+ while ( myIterateIndex < count()-1 &&
+ (currentText() == text( myIterateIndex ) ||
+ text( myIterateIndex ).isEmpty()) )
+ myIterateIndex++;
+
+ if ( myIterateIndex >= count() ) {
+ myRotated = true;
+ myIterateIndex = -1;
+
+ // if the typed text is the same as the first item, skip the first
+ if ( myText == text(0) )
+ myIterateIndex = 0;
+
+ setEditText( myText );
+ }
+ else
+ setEditText( text( myIterateIndex ));
+ }
+
+
+ // going down in the history, no rotation possible. Last item will be
+ // the text that was in the lineedit before Up was called.
+ //else if ( OStdAccel::isEqual( e, OStdAccel::rotateDown() ) ) {
+ else if ( e->key() == Qt::Key_Down ) {
+ myIterateIndex--;
+
+ // skip duplicates/empty items
+ while ( myIterateIndex >= 0 &&
+ (currentText() == text( myIterateIndex ) ||
+ text( myIterateIndex ).isEmpty()) )
+ myIterateIndex--;
+
+
+ if ( myIterateIndex < 0 ) {
+ if ( myRotated && myIterateIndex == -2 ) {
+ myRotated = false;
+ myIterateIndex = count() - 1;
+ setEditText( text(myIterateIndex) );
+ }
+ else { // bottom of history
+ if ( myIterateIndex == -2 ) {
+ qDebug( "ONotifyClient is not implemented yet." );
+ //ONotifyClient::event( ONotifyClient::notification,
+ // i18n("No further item in the history."));
+ }
+
+ myIterateIndex = -1;
+ if ( currentText() != myText )
+ setEditText( myText );
+ }
+ }
+ else
+ setEditText( text( myIterateIndex ));
+ }
+
+ else
+ OComboBox::keyPressEvent( e );
+}
+
+void OHistoryCombo::slotReset()
+{
+ myIterateIndex = -1;
+ myRotated = false;
+}
+
+
+void OHistoryCombo::setPixmapProvider( OPixmapProvider *prov )
+{
+ if ( myPixProvider == prov )
+ return;
+
+ delete myPixProvider;
+ myPixProvider = prov;
+
+ // re-insert all the items with/without pixmap
+ // I would prefer to use changeItem(), but that doesn't honour the pixmap
+ // when using an editable combobox (what we do)
+ if ( count() > 0 ) {
+ QStringList items( historyItems() );
+ clear();
+ insertItems( items );
+ }
+}
+
+void OHistoryCombo::insertItems( const QStringList& items )
+{
+ QStringList::ConstIterator it = items.begin();
+ QString item;
+ while ( it != items.end() ) {
+ item = *it;
+ if ( !item.isEmpty() ) { // only insert non-empty items
+ if ( myPixProvider )
+ // insertItem( myPixProvider->pixmapFor(item, OIcon::SizeSmall), item );
+ insertItem( myPixProvider->pixmapFor(item, 16), item );
+ else
+ insertItem( item );
+ }
+ ++it;
+ }
+}
+
+void OHistoryCombo::slotClear()
+{
+ clearHistory();
+ emit cleared();
+}
+
diff --git a/libopie2/qt3/opieui/ocombobox.h b/libopie2/qt3/opieui/ocombobox.h
new file mode 100644
index 0000000..4e35b61
--- a/dev/null
+++ b/libopie2/qt3/opieui/ocombobox.h
@@ -0,0 +1,790 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+ Opie Project Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
+
+ =. Originally part of the KDE projects
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OCOMBOBOX_H
+#define OCOMBOBOX_H
+
+/* QT */
+
+#include <qcombobox.h>
+
+/* OPIE */
+
+#include <opie2/olineedit.h>
+#include <opie2/ocompletion.h>
+#include <opie2/ocompletionbase.h>
+
+/* FORWARDS */
+
+class QListBoxItem;
+class QPopupMenu;
+class OCompletionBox;
+typedef QString OURL;
+
+/**
+ * A combined button, line-edit and a popup list widget.
+ *
+ * @sect Detail
+ *
+ * This widget inherits from @ref QComboBox and implements
+ * the following additional functionalities: a completion
+ * object that provides both automatic and manual text
+ * completion as well as text rotation features, configurable
+ * key-bindings to activate these features, and a popup-menu
+ * item that can be used to allow the user to set text completion
+ * modes on the fly based on their preference.
+ *
+ * To support these new features OComboBox also emits a few
+ * more additional signals as well. The main ones are the
+ * @ref completion( const QString& ) and @ref textRotation( KeyBindingType )
+ * signals. The completion signal is intended to be connected to a slot
+ * that will assist the user in filling out the remaining text while
+ * the rotation signals is intended to be used to traverse through all
+ * possible matches whenever text completion results in multiple matches.
+ * The @ref returnPressed() and @ref returnPressed( const QString& )
+ * signal is emitted when the user presses the Enter/Return key.
+ *
+ * This widget by default creates a completion object when you invoke
+ * the @ref completionObject( bool ) member function for the first time
+ * or use @ref setCompletionObject( OCompletion*, bool ) to assign your
+ * own completion object. Additionally, to make this widget more functional,
+ * OComboBox will by default handle the text rotation and completion
+ * events internally whenever a completion object is created through either
+ * one of the methods mentioned above. If you do not need this functionality,
+ * simply use @ref OCompletionBase::setHandleSignals( bool ) or alternatively
+ * set the boolean parameter in the above methods to FALSE.
+ *
+ * The default key-bindings for completion and rotation is determined
+ * from the global settings in @ref OStdAccel. These values, however,
+ * can be overriden locally by invoking @ref OCompletionBase::setKeyBinding().
+ * The values can easily be reverted back to the default setting, by simply
+ * calling @ref useGlobalSettings(). An alternate method would be to default
+ * individual key-bindings by usning @ref setKeyBinding() with the default
+ * second argument.
+ *
+ * Note that if this widget is not editable ( i.e. select-only ), then only
+ * one completion mode, @p CompletionAuto, will work. All the other modes are
+ * simply ignored. The @p CompletionAuto mode in this case allows you to
+ * automatically select an item from the list by trying to match the pressed
+ * keycode with the first letter of the enteries in the combo box.
+ *
+ * @sect Useage
+ *
+ * To enable the basic completion feature:
+ *
+ * <pre>
+ * OComboBox *combo = new OComboBox( true, this, "mywidget" );
+ * OCompletion *comp = combo->completionObject();
+ * // Connect to the return pressed signal - optional
+ * connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
+ * </pre>
+ *
+ * To use your own completion object:
+ *
+ * <pre>
+ * OComboBox *combo = new OComboBox( this,"mywidget" );
+ * OURLCompletion *comp = new OURLCompletion();
+ * combo->setCompletionObject( comp );
+ * // Connect to the return pressed signal - optional
+ * connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
+ * </pre>
+ *
+ * Note that you have to either delete the allocated completion object
+ * when you don't need it anymore, or call
+ * setAutoDeleteCompletionObject( true );
+ *
+ * Miscellaneous function calls:
+ *
+ * <pre>
+ * // Tell the widget not to handle completion and rotation
+ * combo->setHandleSignals( false );
+ * // Set your own completion key for manual completions.
+ * combo->setKeyBinding( OCompletionBase::TextCompletion, Qt::End );
+ * // Hide the context (popup) menu
+ * combo->setContextMenuEnabled( false );
+ * // Temporarly disable signal emition
+ * combo->disableSignals();
+ * // Default the all key-bindings to their system-wide settings.
+ * combo->useGlobalKeyBindings();
+ * </pre>
+ *
+ * @short An enhanced combo box.
+ * @author Dawit Alemayehu <adawit@kde.org>
+ */
+class OComboBox : public QComboBox, public OCompletionBase
+{
+ Q_OBJECT
+
+ //Q_PROPERTY( bool autoCompletion READ autoCompletion WRITE setAutoCompletion )
+ //Q_PROPERTY( bool contextMenuEnabled READ isContextMenuEnabled WRITE setContextMenuEnabled )
+ //Q_PROPERTY( bool urlDropsEnabled READ isURLDropsEnabled WRITE setURLDropsEnabled )
+
+public:
+
+ /**
+ * Constructs a read-only or rather select-only combo box with a
+ * parent object and a name.
+ *
+ * @param parent The parent object of this widget
+ * @param name The name of this widget
+ */
+ OComboBox( QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Constructs a "read-write" or "read-only" combo box depending on
+ * the value of the first argument( @p rw ) with a parent, a
+ * name.
+ *
+ * @param rw When @p true, widget will be editable.
+ * @param parent The parent object of this widget.
+ * @param name The name of this widget.
+ */
+ OComboBox( bool rw, QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Destructor.
+ */
+ virtual ~OComboBox();
+
+ /**
+ * Sets @p url into the edit field of the combobox. It uses
+ * @ref OURL::prettyURL() so that the url is properly decoded for
+ * displaying.
+ */
+ //void setEditURL( const OURL& url );
+
+ /**
+ * Inserts @p url at position @p index into the combobox. The item will
+ * be appended if @p index is negative. @ref OURL::prettyURL() is used
+ * so that the url is properly decoded for displaying.
+ */
+ //void insertURL( const OURL& url, int index = -1 );
+
+ /**
+ * Inserts @p url with the pixmap &p pixmap at position @p index into
+ * the combobox. The item will be appended if @p index is negative.
+ * @ref OURL::prettyURL() is used so that the url is properly decoded
+ * for displaying.
+ */
+ //void insertURL( const QPixmap& pixmap, const OURL& url, int index = -1 );
+
+ /**
+ * Replaces the item at position @p index with @p url.
+ * @ref OURL::prettyURL() is used so that the url is properly decoded
+ * for displaying.
+ */
+ //void changeURL( const OURL& url, int index );
+
+ /**
+ * Replaces the item at position @p index with @p url and pixmap @p pixmap.
+ * @ref OURL::prettyURL() is used so that the url is properly decoded
+ * for displaying.
+ */
+ //void changeURL( const QPixmap& pixmap, const OURL& url, int index );
+
+ /**
+ * Returns the current cursor position.
+ *
+ * This method always returns a -1 if the combo-box is @em not
+ * editable (read-write).
+ *
+ * @return Current cursor position.
+ */
+ int cursorPosition() const { return ( lineEdit() ) ? lineEdit()->cursorPosition() : -1; }
+
+ /**
+ * Re-implemented from @ref QComboBox.
+ *
+ * If @p true, the completion mode will be set to automatic.
+ * Otherwise, it is defaulted to the global setting. This
+ * method has been replaced by the more comprehensive
+ * @ref setCompletionMode().
+ *
+ * @param autocomplete Flag to enable/disable automatic completion mode.
+ */
+ virtual void setAutoCompletion( bool autocomplete );
+
+ /**
+ * Re-implemented from QComboBox.
+ *
+ * Returns @p true if the current completion mode is set
+ * to automatic. See its more comprehensive replacement
+ * @ref completionMode().
+ *
+ * @return @p true when completion mode is automatic.
+ */
+ bool autoCompletion() const {
+ return completionMode() == OGlobalSettings::CompletionAuto;
+ }
+
+ /**
+ * Enables or disable the popup (context) menu.
+ *
+ * This method only works if this widget is editable, i.e.
+ * read-write and allows you to enable/disable the context
+ * menu. It does nothing if invoked for a none-editable
+ * combo-box. Note that by default the mode changer item
+ * is made visiable whenever the context menu is enabled.
+ * Use @ref hideModechanger() if you want to hide this
+ * item. Also by default, the context menu is created if
+ * this widget is editable. Call this function with the
+ * argument set to false to disable the popup menu.
+ *
+ * @param showMenu If @p true, show the context menu.
+ * @param showMode If @p true, show the mode changer.
+ */
+ virtual void setContextMenuEnabled( bool showMenu );
+
+ /**
+ * Returns @p true when the context menu is enabled.
+ */
+ bool isContextMenuEnabled() const { return m_bEnableMenu; }
+
+ /**
+ * Enables/Disables handling of URL drops. If enabled and the user
+ * drops an URL, the decoded URL will be inserted. Otherwise the default
+ * behaviour of QComboBox is used, which inserts the encoded URL.
+ *
+ * @param enable If @p true, insert decoded URLs
+ */
+ //void setURLDropsEnabled( bool enable );
+
+ /**
+ * Returns @p true when decoded URL drops are enabled
+ */
+ //bool isURLDropsEnabled() const;
+
+ /**
+ * Convenience method which iterates over all items and checks if
+ * any of them is equal to @p text.
+ *
+ * If @p text is an empty string, @p false
+ * is returned.
+ *
+ * @return @p true if an item with the string @p text is in the combobox.
+ */
+ bool contains( const QString& text ) const;
+
+ /**
+ * By default, OComboBox recognizes Key_Return and Key_Enter
+ * and emits
+ * the @ref returnPressed() signals, but it also lets the event pass,
+ * for example causing a dialog's default-button to be called.
+ *
+ * Call this method with @p trap equal to true to make OComboBox
+ * stop these
+ * events. The signals will still be emitted of course.
+ *
+ * Only affects read-writable comboboxes.
+ *
+ * @see setTrapReturnKey()
+ */
+ void setTrapReturnKey( bool trap );
+
+ /**
+ * @return @p true if keyevents of Key_Return or Key_Enter will
+ * be stopped or if they will be propagated.
+ *
+ * @see setTrapReturnKey ()
+ */
+ bool trapReturnKey() const;
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * @reimplemented
+ */
+ virtual bool eventFilter( QObject *, QEvent * );
+
+ /**
+ * @returns the completion-box, that is used in completion mode
+ * @ref OGlobalSettings::CompletionPopup and @ref OGlobalSettings::CompletionPopupAuto.
+ * This method will create a completion-box by calling
+ * @ref OLineEdit::completionBox, if none is there, yet.
+ *
+ * @param create Set this to false if you don't want the box to be created
+ * i.e. to test if it is available.
+ */
+ OCompletionBox * completionBox( bool create = true );
+
+ virtual void setLineEdit( OLineEdit * );
+
+signals:
+ /**
+ * Emitted when the user presses the Enter key.
+ *
+ * Note that this signal is only
+ * emitted if this widget is editable.
+ */
+ void returnPressed();
+
+ /**
+ * Emitted when the user presses
+ * the Enter key.
+ *
+ * The argument is the current
+ * text being edited. This signal is just like
+ * @ref returnPressed() except it contains the
+ * current text as its argument.
+ *
+ * Note that this signal is only emitted if this
+ * widget is editable.
+ */
+ void returnPressed( const QString& );
+
+ /**
+ * This signal is emitted when the completion key
+ * is pressed.
+ *
+ * The argument is the current text
+ * being edited.
+ *
+ * Note that this signal is @em not available if this
+ * widget is non-editable or the completion mode is
+ * set to @p OGlobalSettings::CompletionNone.
+ */
+ void completion( const QString& );
+
+ /**
+ * Emitted when the shortcut for substring completion is pressed.
+ */
+ void substringCompletion( const QString& );
+
+ /**
+ * Emitted when the text rotation key-bindings are pressed.
+ *
+ * The argument indicates which key-binding was pressed.
+ * In this case this can be either one of four values:
+ * @p PrevCompletionMatch, @p NextCompletionMatch, @p RotateUp or
+ * @p RotateDown. See @ref OCompletionBase::setKeyBinding() for
+ * details.
+ *
+ * Note that this signal is @em NOT emitted if the completion
+ * mode is set to CompletionNone.
+ */
+ void textRotation( OCompletionBase::KeyBindingType );
+
+ /**
+ * Emitted when the user changed the completion mode by using the
+ * popupmenu.
+ */
+ void completionModeChanged( OGlobalSettings::Completion );
+
+ /**
+ * Emitted before the context menu is displayed.
+ *
+ * The signal allows you to add your own entries into the
+ * the context menu that is created on demand.
+ *
+ * NOTE: Do not store the pointer to the QPopupMenu
+ * provided through since it is created and deleted
+ * on demand.
+ *
+ * @param the context menu about to be displayed
+ */
+ void aboutToShowContextMenu( QPopupMenu * );
+
+public slots:
+
+ /**
+ * Iterates through all possible matches of the completed text
+ * or the history list.
+ *
+ * Depending on the value of the argument, this function either
+ * iterates through the history list of this widget or the all
+ * possible matches in whenever multiple matches result from a
+ * text completion request. Note that the all-possible-match
+ * iteration will not work if there are no previous matches, i.e.
+ * no text has been completed and the *nix shell history list
+ * rotation is only available if the insertion policy for this
+ * widget is set either @p QComobBox::AtTop or @p QComboBox::AtBottom.
+ * For other insertion modes whatever has been typed by the user
+ * when the rotation event was initiated will be lost.
+ *
+ * @param type The key-binding invoked.
+ */
+ void rotateText( OCompletionBase::KeyBindingType /* type */ );
+
+ /**
+ * Sets the completed text in the line-edit appropriately.
+ *
+ * This function is an implementation for
+ * @ref OCompletionBase::setCompletedText.
+ */
+ virtual void setCompletedText( const QString& );
+
+ /**
+ * Sets @p items into the completion-box if @ref completionMode() is
+ * CompletionPopup. The popup will be shown immediately.
+ */
+ void setCompletedItems( const QStringList& items );
+
+ public:
+ /**
+ * Selects the first item that matches @p item. If there is no such item,
+ * it is inserted at position @p index if @p insert is true. Otherwise,
+ * no item is selected.
+ */
+ void setCurrentItem( const QString& item, bool insert = false, int index = -1 );
+ void setCurrentItem(int index);
+
+protected slots:
+
+ /**
+ * @deprecated.
+ */
+ virtual void itemSelected( QListBoxItem* ) {};
+
+ /**
+ * Completes text according to the completion mode.
+ *
+ * Note: this method is @p not invoked if the completion mode is
+ * set to CompletionNone. Also if the mode is set to @p CompletionShell
+ * and multiple matches are found, this method will complete the
+ * text to the first match with a beep to inidicate that there are
+ * more matches. Then any successive completion key event iterates
+ * through the remaining matches. This way the rotation functionality
+ * is left to iterate through the list as usual.
+ */
+ virtual void makeCompletion( const QString& );
+
+protected:
+ /*
+ * This function simply sets the lineedit text and
+ * highlights the text appropriately if the boolean
+ * value is set to true.
+ *
+ * @param
+ * @param
+ */
+ virtual void setCompletedText( const QString& /* */, bool /*marked*/ );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void create( WId = 0, bool initializeWindow = true,
+ bool destroyOldWindow = true );
+
+private:
+ // Constants that represent the ID's of the popup menu.
+ // TODO: See if we can replace this mess with OActionMenu
+ // in the future though this is working lovely.
+ enum MenuID {
+ Default=0,
+ Cut,
+ Copy,
+ Paste,
+ Clear,
+ Unselect,
+ SelectAll,
+ NoCompletion,
+ AutoCompletion,
+ ShellCompletion,
+ PopupCompletion,
+ SemiAutoCompletion
+ };
+
+ /**
+ * Initializes the variables upon construction.
+ */
+ void init();
+ /**
+ * Temporary functions to delete words back and foward until
+ * alternatives are available in QT3 (Seth Chaiklin, 21 may 2001)
+ */
+ void deleteWordBack();
+ void deleteWordForward();
+
+ bool m_bEnableMenu;
+
+ // indicating if we should stop return-key events from propagating
+ bool m_trapReturnKey;
+
+//protected:
+// virtual void virtual_hook( int id, void* data );
+private:
+ class OComboBoxPrivate;
+ OComboBoxPrivate *d;
+};
+
+
+class OPixmapProvider;
+
+/**
+ * A combobox which implements a history like a unix shell. You can navigate
+ * through all the items by using the Up or Down arrows (configurable of
+ * course). Additionally, weighted completion is available. So you should
+ * load and save the completion list to preserve the weighting between
+ * sessions.
+ *
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ * @short A combobox for offering a history and completion
+ */
+class OHistoryCombo : public OComboBox
+{
+ Q_OBJECT
+ Q_PROPERTY( QStringList historyItems READ historyItems WRITE setHistoryItems )
+
+public:
+ /**
+ * Constructs a "read-write" combobox. A read-only history combobox
+ * doesn't make much sense, so it is only available as read-write.
+ * Completion will be used automatically for the items in the combo.
+ *
+ * The insertion-policy is set to NoInsertion, you have to add the items
+ * yourself via the slot @ref addToHistory. If you want every item added,
+ * use
+ *
+ * <pre>
+ * connect( combo, SIGNAL( activated( const QString& )),
+ * combo, SLOT( addToHistory( const QString& )));
+ * </pre>
+ *
+ * Use @ref QComboBox::setMaxCount() to limit the history.
+ *
+ * @p parent the parent object of this widget.
+ * @p name the name of this widget.
+ */
+ OHistoryCombo( QWidget *parent = 0L, const char *name = 0L );
+
+ // ### merge these two constructors
+ /**
+ * Same as the previous constructor, but additionally has the option
+ * to specify whether you want to let OHistoryCombo handle completion
+ * or not. If set to @p true, OHistoryCombo will sync the completion to the
+ * contents of the combobox.
+ */
+ OHistoryCombo( bool useCompletion,
+ QWidget *parent = 0L, const char *name = 0L );
+
+ /**
+ * Destructs the combo, the completion-object and the pixmap-provider
+ */
+ ~OHistoryCombo();
+
+ /**
+ * Inserts @p items into the combobox. @p items might get
+ * truncated if it is longer than @ref maxCount()
+ *
+ * @see #historyItems
+ */
+ inline void setHistoryItems( QStringList items ) {
+ setHistoryItems(items, false);
+ }
+
+ /**
+ * Inserts @p items into the combobox. @p items might get
+ * truncated if it is longer than @ref maxCount()
+ *
+ * Set @p setCompletionList to true, if you don't have a list of
+ * completions. This tells OHistoryCombo to use all the items for the
+ * completion object as well.
+ * You won't have the benefit of weighted completion though, so normally
+ * you should do something like
+ * <pre>
+ * OConfig *config = kapp->config();
+ * QStringList list;
+ *
+ * // load the history and completion list after creating the history combo
+ * list = config->readListEntry( "Completion list" );
+ * combo->completionObject()->setItems( list );
+ * list = config->readListEntry( "History list" );
+ * combo->setHistoryItems( list );
+ *
+ * [...]
+ *
+ * // save the history and completion list when the history combo is
+ * // destroyed
+ * list = combo->completionObject()->items()
+ * config->writeEntry( "Completion list", list );
+ * list = combo->historyItems();
+ * config->writeEntry( "History list", list );
+ * </pre>
+ *
+ * Be sure to use different names for saving with OConfig if you have more
+ * than one OHistoryCombo.
+ *
+ * Note: When @p setCompletionList is true, the items are inserted into the
+ * OCompletion object with mode OCompletion::Insertion and the mode is set
+ * to OCompletion::Weighted afterwards.
+ *
+ * @see #historyItems
+ * @see OComboBox::completionObject
+ * @see OCompletion::setItems
+ * @see OCompletion::items
+ */
+ void setHistoryItems( QStringList items, bool setCompletionList );
+
+ /**
+ * Returns the list of history items. Empty, when this is not a read-write
+ * combobox.
+ *
+ * @see #setHistoryItems
+ */
+ QStringList historyItems() const;
+
+ /**
+ * Removes all items named @p item.
+ *
+ * @return @p true if at least one item was removed.
+ *
+ * @see #addToHistory
+ */
+ bool removeFromHistory( const QString& item );
+
+ /**
+ * Sets a pixmap provider, so that items in the combobox can have a pixmap.
+ * @ref OPixmapProvider is just an abstract class with the one pure virtual
+ * method @ref OPixmapProvider::pixmapFor(). This method is called whenever
+ * an item is added to the OHistoryComboBox. Implement it to return your
+ * own custom pixmaps, or use the @ref OURLPixmapProvider from libkio,
+ * which uses @ref OMimeType::pixmapForURL to resolve icons.
+ *
+ * Set @p prov to 0L if you want to disable pixmaps. Default no pixmaps.
+ *
+ * @see #pixmapProvider
+ */
+ void setPixmapProvider( OPixmapProvider *prov );
+
+ /**
+ * @returns the current pixmap provider.
+ * @see #setPixmapProvider
+ * @see OPixmapProvider
+ */
+ OPixmapProvider * pixmapProvider() const { return myPixProvider; }
+
+ /**
+ * Resets the current position of the up/down history. Call this
+ * when you manually call @ref setCurrentItem() or @ref clearEdit().
+ */
+ void reset() { slotReset(); }
+
+public slots:
+ /**
+ * Adds an item to the end of the history list and to the completion list.
+ * If @ref maxCount() is reached, the first item of the list will be
+ * removed.
+ *
+ * If the last inserted item is the same as @p item, it will not be
+ * inserted again.
+ *
+ * If @ref duplicatesEnabled() is false, any equal existing item will be
+ * removed before @p item is added.
+ *
+ * Note: By using this method and not the Q and OComboBox insertItem()
+ * methods, you make sure that the combobox stays in sync with the
+ * completion. It would be annoying if completion would give an item
+ * not in the combobox, and vice versa.
+ *
+ * @see #removeFromHistory
+ * @see QComboBox::setDuplicatesEnabled
+ */
+ void addToHistory( const QString& item );
+
+ /**
+ * Clears the history and the completion list.
+ */
+ void clearHistory();
+
+signals:
+ /**
+ * Emitted when the history was cleared by the entry in the popup menu.
+ */
+ void cleared();
+
+protected:
+ /**
+ * Handling key-events, the shortcuts to rotate the items.
+ */
+ virtual void keyPressEvent( QKeyEvent * );
+
+
+ /**
+ * Inserts @p items into the combo, honouring @ref pixmapProvider()
+ * Does not update the completionObject.
+ *
+ * Note: @ref duplicatesEnabled() is not honored here.
+ *
+ * Called from @ref setHistoryItems() and @ref setPixmapProvider()
+ */
+ void insertItems( const QStringList& items );
+
+ /**
+ * @returns if we can modify the completion object or not.
+ */
+ bool useCompletion() const { return compObj() != 0L; }
+
+private slots:
+ /**
+ * Resets the iterate index to -1
+ */
+ void slotReset();
+
+ /**
+ * Called from the popupmenu,
+ * calls clearHistory() and emits cleared()
+ */
+ void slotClear();
+
+ /**
+ * Appends our own context menu entry.
+ */
+ void addContextMenuItems( QPopupMenu* );
+
+private:
+ void init( bool useCompletion );
+
+ /**
+ * The current position (index) in the combobox, used for Up and Down
+ */
+ int myIterateIndex;
+
+ /**
+ * The text typed before Up or Down was pressed.
+ */
+ QString myText;
+
+ /**
+ * Indicates that the user at least once rotated Up through the entire list
+ * Needed to allow going back after rotation.
+ */
+ bool myRotated;
+ OPixmapProvider *myPixProvider;
+
+private:
+ class OHistoryComboPrivate;
+ OHistoryComboPrivate *d;
+};
+
+
+#endif
+
diff --git a/libopie2/qt3/opieui/ocompletionbox.cpp b/libopie2/qt3/opieui/ocompletionbox.cpp
new file mode 100644
index 0000000..b594b8e
--- a/dev/null
+++ b/libopie2/qt3/opieui/ocompletionbox.cpp
@@ -0,0 +1,408 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
+ Opie Project Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de>
+ Copyright (C) 2000,2001 Dawit Alemayehu <adawit@kde.org>
+ =.
+ .=l. Originally part of the KDE Project
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include <qapplication.h>
+#include <qevent.h>
+#include <qstyle.h>
+
+#include <opie2/ocompletionbox.h>
+
+#define OListBox QListBox
+
+class OCompletionBox::OCompletionBoxPrivate
+{
+public:
+ QWidget *m_parent; // necessary to set the focus back
+ QString cancelText;
+ bool tabHandling;
+ bool down_workaround;
+};
+
+OCompletionBox::OCompletionBox( QWidget *parent, const char *name )
+ :OListBox( parent, name, WType_Popup )
+{
+ d = new OCompletionBoxPrivate;
+ d->m_parent = parent;
+ d->tabHandling = true;
+ d->down_workaround = false;
+
+ setColumnMode( 1 );
+ setLineWidth( 1 );
+ setFrameStyle( QFrame::Box | QFrame::Plain );
+
+ if ( parent )
+ setFocusProxy( parent );
+ else
+ setFocusPolicy( NoFocus );
+
+ setVScrollBarMode( Auto );
+ setHScrollBarMode( AlwaysOff );
+
+ connect( this, SIGNAL( doubleClicked( QListBoxItem * )),
+ SLOT( slotActivated( QListBoxItem * )) );
+
+ // grmbl, just QListBox workarounds :[ Thanks Volker.
+ connect( this, SIGNAL( currentChanged( QListBoxItem * )),
+ SLOT( slotCurrentChanged() ));
+ connect( this, SIGNAL( clicked( QListBoxItem * )),
+ SLOT( slotItemClicked( QListBoxItem * )) );
+}
+
+OCompletionBox::~OCompletionBox()
+{
+ d->m_parent = 0L;
+ delete d;
+}
+
+QStringList OCompletionBox::items() const
+{
+ QStringList list;
+ for ( uint i = 0; i < count(); i++ ) {
+ list.append( text( i ) );
+ }
+ return list;
+}
+
+void OCompletionBox::slotActivated( QListBoxItem *item )
+{
+ if ( !item )
+ return;
+
+ hide();
+ emit activated( item->text() );
+}
+
+bool OCompletionBox::eventFilter( QObject *o, QEvent *e )
+{
+ int type = e->type();
+
+ if ( o == d->m_parent ) {
+ if ( isVisible() ) {
+ if ( type == QEvent::KeyPress ) {
+ QKeyEvent *ev = static_cast<QKeyEvent *>( e );
+ switch ( ev->key() ) {
+ case Key_BackTab:
+ if ( d->tabHandling ) {
+ up();
+ ev->accept();
+ return true;
+ }
+ break;
+ case Key_Tab:
+ if ( d->tabHandling ) {
+ down(); // Only on TAB!!
+ ev->accept();
+ return true;
+ }
+ break;
+ case Key_Down:
+ down();
+ ev->accept();
+ return true;
+ case Key_Up:
+ up();
+ ev->accept();
+ return true;
+ case Key_Prior:
+ pageUp();
+ ev->accept();
+ return true;
+ case Key_Next:
+ pageDown();
+ ev->accept();
+ return true;
+ case Key_Escape:
+ cancelled();
+ ev->accept();
+ return true;
+ case Key_Enter:
+ case Key_Return:
+ if ( ev->state() & ShiftButton ) {
+ hide();
+ ev->accept(); // Consume the Enter event
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else if ( type == QEvent::AccelOverride ) {
+ // Override any acceleartors that match
+ // the key sequences we use here...
+ QKeyEvent *ev = static_cast<QKeyEvent *>( e );
+ switch ( ev->key() ) {
+ case Key_Tab:
+ case Key_BackTab:
+ case Key_Down:
+ case Key_Up:
+ case Key_Prior:
+ case Key_Next:
+ case Key_Escape:
+ case Key_Enter:
+ case Key_Return:
+ ev->accept();
+ return true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // parent loses focus or gets a click -> we hide
+ else if ( type == QEvent::FocusOut || type == QEvent::Resize ||
+ type == QEvent::Close || type == QEvent::Hide ||
+ type == QEvent::Move ) {
+ hide();
+ }
+ else if ( type == QEvent::Move )
+ move( d->m_parent->mapToGlobal(QPoint(0, d->m_parent->height())));
+ else if ( type == QEvent::Resize )
+ resize( sizeHint() );
+ }
+ }
+
+ // any mouse-click on something else than "this" makes us hide
+ else if ( type == QEvent::MouseButtonPress ) {
+ QMouseEvent *ev = static_cast<QMouseEvent *>( e );
+ if ( !rect().contains( ev->pos() )) // this widget
+ hide();
+ }
+
+ return OListBox::eventFilter( o, e );
+}
+
+
+void OCompletionBox::popup()
+{
+ if ( count() == 0 )
+ hide();
+ else {
+ ensureCurrentVisible();
+ bool block = signalsBlocked();
+ blockSignals( true );
+ setCurrentItem( 0 );
+ blockSignals( block );
+ clearSelection();
+ if ( !isVisible() )
+ show();
+ else if ( size().height() < sizeHint().height() )
+ resize( sizeHint() );
+ }
+}
+
+void OCompletionBox::show()
+{
+ resize( sizeHint() );
+
+ if ( d->m_parent )
+ {
+ //QDesktopWidget *screen = QApplication::desktop();
+ QWidget *screen = QApplication::desktop();
+
+ QPoint orig = d->m_parent->mapToGlobal( QPoint(0, d->m_parent->height()) );
+ int x = orig.x();
+ int y = orig.y();
+
+ if ( x + width() > screen->width() )
+ x = screen->width() - width();
+ if (y + height() > screen->height() )
+ y = y - height() - d->m_parent->height();
+
+ move( x, y);
+ qApp->installEventFilter( this );
+ }
+
+ // ### we shouldn't need to call this, but without this, the scrollbars
+ // are pretty b0rked.
+ //triggerUpdate( true );
+
+ OListBox::show();
+}
+
+void OCompletionBox::hide()
+{
+ if ( d->m_parent )
+ qApp->removeEventFilter( this );
+ d->cancelText = QString::null;
+ OListBox::hide();
+}
+
+QSize OCompletionBox::sizeHint() const
+{
+ int ih = itemHeight();
+ int h = QMIN( 15 * ih, (int) count() * ih ) +1;
+ h = QMAX( h, OListBox::minimumSizeHint().height() );
+
+ int w = (d->m_parent) ? d->m_parent->width() : OListBox::minimumSizeHint().width();
+ w = QMAX( OListBox::minimumSizeHint().width(), w );
+ return QSize( w, h );
+}
+
+void OCompletionBox::down()
+{
+ int i = currentItem();
+
+ if ( i == 0 && d->down_workaround ) {
+ d->down_workaround = false;
+ setCurrentItem( 0 );
+ setSelected( 0, true );
+ emit highlighted( currentText() );
+ }
+
+ else if ( i < (int) count() - 1 )
+ setCurrentItem( i + 1 );
+}
+
+void OCompletionBox::up()
+{
+ if ( currentItem() > 0 )
+ setCurrentItem( currentItem() - 1 );
+}
+
+void OCompletionBox::pageDown()
+{
+ int i = currentItem() + numItemsVisible();
+ i = i > (int)count() - 1 ? (int)count() - 1 : i;
+ setCurrentItem( i );
+}
+
+void OCompletionBox::pageUp()
+{
+ int i = currentItem() - numItemsVisible();
+ i = i < 0 ? 0 : i;
+ setCurrentItem( i );
+}
+
+void OCompletionBox::home()
+{
+ setCurrentItem( 0 );
+}
+
+void OCompletionBox::end()
+{
+ setCurrentItem( count() -1 );
+}
+
+void OCompletionBox::setTabHandling( bool enable )
+{
+ d->tabHandling = enable;
+}
+
+bool OCompletionBox::isTabHandling() const
+{
+ return d->tabHandling;
+}
+
+void OCompletionBox::setCancelledText( const QString& text )
+{
+ d->cancelText = text;
+}
+
+QString OCompletionBox::cancelledText() const
+{
+ return d->cancelText;
+}
+
+void OCompletionBox::cancelled()
+{
+ if ( !d->cancelText.isNull() )
+ emit userCancelled( d->cancelText );
+ if ( isVisible() )
+ hide();
+}
+
+class OCompletionBoxItem : public QListBoxItem
+{
+public:
+ void reuse( const QString &text ) { setText( text ); }
+};
+
+
+void OCompletionBox::insertItems( const QStringList& items, int index )
+{
+ bool block = signalsBlocked();
+ blockSignals( true );
+ insertStringList( items, index );
+ blockSignals( block );
+ d->down_workaround = true;
+}
+
+void OCompletionBox::setItems( const QStringList& items )
+{
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ QListBoxItem* item = firstItem();
+ if ( !item ) {
+ insertStringList( items );
+ }
+ else {
+ for ( QStringList::ConstIterator it = items.begin(); it != items.end(); it++) {
+ if ( item ) {
+ ((OCompletionBoxItem*)item)->reuse( *it );
+ item = item->next();
+ }
+ else {
+ insertItem( new QListBoxText( *it ) );
+ }
+ }
+ QListBoxItem* tmp = item;
+ while ( (item = tmp ) ) {
+ tmp = item->next();
+ delete item;
+ }
+ triggerUpdate( false );
+ }
+
+ blockSignals( block );
+ d->down_workaround = true;
+}
+
+void OCompletionBox::slotCurrentChanged()
+{
+ d->down_workaround = false;
+}
+
+void OCompletionBox::slotItemClicked( QListBoxItem *item )
+{
+ if ( item )
+ {
+ if ( d->down_workaround ) {
+ d->down_workaround = false;
+ emit highlighted( item->text() );
+ }
+
+ hide();
+ emit activated( item->text() );
+ }
+}
diff --git a/libopie2/qt3/opieui/ocompletionbox.h b/libopie2/qt3/opieui/ocompletionbox.h
new file mode 100644
index 0000000..54d9ef5
--- a/dev/null
+++ b/libopie2/qt3/opieui/ocompletionbox.h
@@ -0,0 +1,232 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+ Opie Project Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de>
+
+ =. Originally part of the KDE Project
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OCOMPLETIONBOX_H
+#define OCOMPLETIONBOX_H
+
+class QEvent;
+#include <qstringlist.h>
+#include <qlistbox.h>
+
+// ML: Until we don't have an own OListBox, we use the QListBox
+#define OListBox QListBox
+
+/**
+ * A little utility class for "completion-widgets", like @ref OLineEdit or
+ * @ref OComboBox. OCompletionBox is a listbox, displayed as a rectangle without
+ * any window decoration, usually directly under the lineedit or combobox.
+ * It is filled with all possible matches for a completion, so the user
+ * can select the one he wants.
+ *
+ * It is used when OGlobalSettings::Completion == CompletionPopup or CompletionPopupAuto.
+ *
+ * @short A helper widget for "completion-widgets" (OLineEdit, OComboBox))
+ * @short Adapted for the Opie project by Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ *
+ */
+class OCompletionBox : public OListBox
+{
+ Q_OBJECT
+ Q_PROPERTY( bool isTabHandling READ isTabHandling WRITE setTabHandling )
+ Q_PROPERTY(QString cancelledText READ cancelledText WRITE setCancelledText)
+
+public:
+ /**
+ * Constructs a OCompletionBox.
+ *
+ * Notice: the parent needs to be always 0L,
+ * so you can't specify it in the constructor. Because of that, Qt's
+ * auto-deletion does not take place, so you have to explicitly delete
+ * this widget when you don't need it anymore.
+ *
+ * The parent widget is used to give the focus back when pressing the
+ * up-button on the very first item.
+ */
+ OCompletionBox( QWidget *parent, const char *name = 0 );
+
+ /**
+ * Destroys the box
+ */
+ ~OCompletionBox();
+
+ virtual QSize sizeHint() const;
+
+public slots:
+ /**
+ * Returns a list of all items currently in the box.
+ */
+ QStringList items() const;
+
+ /**
+ * Inserts @p items into the box. Does not clear the items before.
+ * @p index determines at which position @p items will be inserted.
+ * (defaults to appending them at the end)
+ */
+ void insertItems( const QStringList& items, int index = -1 );
+
+ /**
+ * Clears the box and inserts @p items.
+ */
+ void setItems( const QStringList& items );
+
+ /**
+ * Adjusts the size of the box to fit the width of the parent given in the
+ * constructor and pops it up at the most appropriate place, relative to
+ * the parent.
+ *
+ * Depending on the screensize and the position of the parent, this may
+ * be a different place, however the default is to pop it up and the
+ * lower left corner of the parent.
+ *
+ * Make sure to hide() the box when appropriate.
+ */
+ virtual void popup();
+
+ /**
+ * Makes this widget (when visible) capture Tab-key events to traverse the
+ * items in the dropdown list.
+ *
+ * Default off, as it conflicts with the usual behavior of Tab to traverse
+ * widgets. It is useful for cases like Konqueror's Location Bar, though.
+ *
+ * @see #isTabHandling
+ */
+ void setTabHandling( bool enable );
+
+ /**
+ * @returns true if this widget is handling Tab-key events to traverse the
+ * items in the dropdown list, otherwise false.
+ *
+ * Default is false.
+ *
+ * @see #setTabHandling
+ */
+ bool isTabHandling() const;
+
+ /**
+ * Sets the text to be emitted if the user chooses not to
+ * pick from the available matches.
+ *
+ * If the cancelled text is not set through this function, the
+ * @ref userCancelled signal will not be emitted.
+ *
+ * @see userCancelled( const QString& )
+ * @param txt the text to be emitted if the user cancels this box
+ */
+ void setCancelledText( const QString& );
+
+ /**
+ * @returns the text set via @ref setCancelledText() or QString::null.
+ */
+ QString cancelledText() const;
+
+ /**
+ * Moves the selection one line down or select the first item if nothing is selected yet.
+ */
+ void down();
+
+ /**
+ * Moves the selection one line up or select the first item if nothing is selected yet.
+ */
+ void up();
+
+ /**
+ * Moves the selection one page down.
+ */
+ void pageDown();
+
+ /**
+ * Moves the selection one page up.
+ */
+ void pageUp();
+
+ /**
+ * Moves the selection up to the first item.
+ */
+ void home();
+
+ /**
+ * Moves the selection down to the last item.
+ */
+ void end();
+
+ /**
+ * Re-implemented for internal reasons. API is unaffected.
+ */
+ virtual void show();
+
+ /**
+ * Re-implemented for internal reasons. API is unaffected.
+ */
+ virtual void hide();
+
+signals:
+ /**
+ * Emitted when an item was selected, contains the text of
+ * the selected item.
+ */
+ void activated( const QString& );
+
+ /**
+ * Emitted whenever the user chooses to ignore the available
+ * selections and close the this box.
+ */
+ void userCancelled( const QString& );
+
+protected:
+ /**
+ * Reimplemented from OListBox to get events from the viewport (to hide
+ * this widget on mouse-click, Escape-presses, etc.
+ */
+ virtual bool eventFilter( QObject *, QEvent * );
+
+protected slots:
+ /**
+ * Called when an item was activated. Emits
+ * @ref activated() with the item.
+ */
+ virtual void slotActivated( QListBoxItem * );
+
+private slots:
+ void slotSetCurrentItem( QListBoxItem *i ) { setCurrentItem( i ); } // grrr
+ void slotCurrentChanged();
+ void cancelled();
+ void slotItemClicked( QListBoxItem * );
+
+private:
+ class OCompletionBoxPrivate;
+ OCompletionBoxPrivate* d;
+};
+
+
+#endif // OCOMPLETIONBOX_H
diff --git a/libopie2/qt3/opieui/oeditlistbox.cpp b/libopie2/qt3/opieui/oeditlistbox.cpp
new file mode 100644
index 0000000..3c53552
--- a/dev/null
+++ b/libopie2/qt3/opieui/oeditlistbox.cpp
@@ -0,0 +1,416 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org>
+ 2000, 2002 Carsten Pfeiffer <pfeiffer@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/* QT */
+
+#include <qstringlist.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qlistbox.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+
+/* OPIE */
+
+#include <opie2/ocombobox.h>
+#include <opie2/odialog.h>
+#include <opie2/olineedit.h>
+#include <opie2/oeditlistbox.h>
+
+/* UNIX */
+
+#include <assert.h>
+
+/*======================================================================================
+ * OEditListBoxPrivate
+ *======================================================================================*/
+
+class OEditListBoxPrivate
+{
+public:
+ bool m_checkAtEntering;
+ int buttons;
+};
+
+/*======================================================================================
+ * OEditListBox
+ *======================================================================================*/
+
+OEditListBox::OEditListBox(QWidget *parent, const char *name,
+ bool checkAtEntering, int buttons )
+ :QGroupBox(parent, name )
+{
+ init( checkAtEntering, buttons );
+}
+
+OEditListBox::OEditListBox(const QString& title, QWidget *parent,
+ const char *name, bool checkAtEntering, int buttons)
+ :QGroupBox(title, parent, name )
+{
+ init( checkAtEntering, buttons );
+}
+
+OEditListBox::OEditListBox(const QString& title, const CustomEditor& custom,
+ QWidget *parent, const char *name,
+ bool checkAtEntering, int buttons)
+ :QGroupBox(title, parent, name )
+{
+ m_lineEdit = custom.lineEdit();
+ init( checkAtEntering, buttons, custom.representationWidget() );
+}
+
+OEditListBox::~OEditListBox()
+{
+ delete d;
+ d=0;
+}
+
+void OEditListBox::init( bool checkAtEntering, int buttons,
+ QWidget *representationWidget )
+{
+ d=new OEditListBoxPrivate;
+ d->m_checkAtEntering=checkAtEntering;
+ d->buttons = buttons;
+
+ int lostButtons = 0;
+ if ( (buttons & Add) == 0 )
+ lostButtons++;
+ if ( (buttons & Remove) == 0 )
+ lostButtons++;
+ if ( (buttons & UpDown) == 0 )
+ lostButtons += 2;
+
+
+ servNewButton = servRemoveButton = servUpButton = servDownButton = 0L;
+ setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,
+ QSizePolicy::MinimumExpanding));
+
+ QWidget * gb = this;
+ QGridLayout * grid = new QGridLayout(gb, 7 - lostButtons, 2,
+ ODialog::marginHint(),
+ ODialog::spacingHint());
+ grid->addRowSpacing(0, fontMetrics().lineSpacing());
+ for ( int i = 1; i < 7 - lostButtons; i++ )
+ grid->setRowStretch(i, 1);
+
+ grid->setMargin(15);
+
+ if ( representationWidget )
+ representationWidget->reparent( gb, QPoint(0,0) );
+ else
+ m_lineEdit=new OLineEdit(gb);
+
+ m_listBox = new QListBox(gb);
+
+ QWidget *editingWidget = representationWidget ?
+ representationWidget : m_lineEdit;
+ grid->addMultiCellWidget(editingWidget,1,1,0,1);
+ grid->addMultiCellWidget(m_listBox, 2, 6 - lostButtons, 0, 0);
+ int row = 2;
+ if ( buttons & Add ) {
+ servNewButton = new QPushButton(tr("&Add"), gb);
+ servNewButton->setEnabled(false);
+ connect(servNewButton, SIGNAL(clicked()), SLOT(addItem()));
+
+ grid->addWidget(servNewButton, row++, 1);
+ }
+
+ if ( buttons & Remove ) {
+ servRemoveButton = new QPushButton(tr("&Remove"), gb);
+ servRemoveButton->setEnabled(false);
+ connect(servRemoveButton, SIGNAL(clicked()), SLOT(removeItem()));
+
+ grid->addWidget(servRemoveButton, row++, 1);
+ }
+
+ if ( buttons & UpDown ) {
+ servUpButton = new QPushButton(tr("Move &Up"), gb);
+ servUpButton->setEnabled(false);
+ connect(servUpButton, SIGNAL(clicked()), SLOT(moveItemUp()));
+
+ servDownButton = new QPushButton(tr("Move &Down"), gb);
+ servDownButton->setEnabled(false);
+ connect(servDownButton, SIGNAL(clicked()), SLOT(moveItemDown()));
+
+ grid->addWidget(servUpButton, row++, 1);
+ grid->addWidget(servDownButton, row++, 1);
+ }
+
+ connect(m_lineEdit,SIGNAL(textChanged(const QString&)),this,SLOT(typedSomething(const QString&)));
+ m_lineEdit->setTrapReturnKey(true);
+ connect(m_lineEdit,SIGNAL(returnPressed()),this,SLOT(addItem()));
+ connect(m_listBox, SIGNAL(highlighted(int)), SLOT(enableMoveButtons(int)));
+
+ // maybe supplied lineedit has some text already
+ typedSomething( m_lineEdit->text() );
+}
+
+void OEditListBox::typedSomething(const QString& text)
+{
+ if(currentItem() >= 0) {
+ if(currentText() != m_lineEdit->text())
+ {
+ // IMHO changeItem() shouldn't do anything with the value
+ // of currentItem() ... like changing it or emitting signals ...
+ // but TT disagree with me on this one (it's been that way since ages ... grrr)
+ bool block = m_listBox->signalsBlocked();
+ m_listBox->blockSignals( true );
+ m_listBox->changeItem(text, currentItem());
+ m_listBox->blockSignals( block );
+ emit changed();
+ }
+ }
+
+ if ( !servNewButton )
+ return;
+
+ if (!d->m_checkAtEntering)
+ servNewButton->setEnabled(!text.isEmpty());
+ else
+ {
+ if (text.isEmpty())
+ {
+ servNewButton->setEnabled(false);
+ }
+ else
+ {
+ #if QT_VERSION > 290
+ StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive );
+ bool enable = (m_listBox->findItem( text, mode ) == 0L);
+ #else
+ bool enable = (m_listBox->findItem( text ) == 0L);
+ #endif
+ servNewButton->setEnabled( enable );
+ }
+ }
+}
+
+void OEditListBox::moveItemUp()
+{
+ if (!m_listBox->isEnabled())
+ {
+ //ONotifyClient::beep();
+ return;
+ }
+
+ unsigned int selIndex = m_listBox->currentItem();
+ if (selIndex == 0)
+ {
+ //ONotifyClient::beep();
+ return;
+ }
+
+ QListBoxItem *selItem = m_listBox->item(selIndex);
+ m_listBox->takeItem(selItem);
+ m_listBox->insertItem(selItem, selIndex-1);
+ m_listBox->setCurrentItem(selIndex - 1);
+
+ emit changed();
+}
+
+void OEditListBox::moveItemDown()
+{
+ if (!m_listBox->isEnabled())
+ {
+ //ONotifyClient::beep();
+ return;
+ }
+
+ unsigned int selIndex = m_listBox->currentItem();
+ if (selIndex == m_listBox->count() - 1)
+ {
+ //ONotifyClient::beep();
+ return;
+ }
+
+ QListBoxItem *selItem = m_listBox->item(selIndex);
+ m_listBox->takeItem(selItem);
+ m_listBox->insertItem(selItem, selIndex+1);
+ m_listBox->setCurrentItem(selIndex + 1);
+
+ emit changed();
+}
+
+void OEditListBox::addItem()
+{
+ // when m_checkAtEntering is true, the add-button is disabled, but this
+ // slot can still be called through Key_Return/Key_Enter. So we guard
+ // against this.
+ if ( !servNewButton || !servNewButton->isEnabled() )
+ return;
+
+ const QString& currentTextLE=m_lineEdit->text();
+ bool alreadyInList(false);
+ //if we didn't check for dupes at the inserting we have to do it now
+ if (!d->m_checkAtEntering)
+ {
+ // first check current item instead of dumb iterating the entire list
+ if ( m_listBox->currentText() == currentTextLE )
+ alreadyInList = true;
+ else
+ {
+ #if QT_VERSION > 290
+ StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive );
+ alreadyInList =(m_listBox->findItem(currentTextLE, mode) != 0);
+ #else
+ alreadyInList =(m_listBox->findItem(currentTextLE) != 0);
+ #endif
+ }
+ }
+
+ if ( servNewButton )
+ servNewButton->setEnabled(false);
+
+ bool block = m_lineEdit->signalsBlocked();
+ m_lineEdit->blockSignals(true);
+ m_lineEdit->clear();
+ m_lineEdit->blockSignals(block);
+
+ m_listBox->setSelected(currentItem(), false);
+
+ if (!alreadyInList)
+ {
+ block = m_listBox->signalsBlocked();
+ m_listBox->blockSignals( true );
+ m_listBox->insertItem(currentTextLE);
+ m_listBox->blockSignals( block );
+ emit changed();
+ emit added( currentTextLE );
+ }
+}
+
+int OEditListBox::currentItem() const
+{
+ int nr = m_listBox->currentItem();
+ #if QT_VERSION > 290
+ if(nr >= 0 && !m_listBox->item(nr)->isSelected()) return -1;
+ #else
+ if(nr >= 0 && !m_listBox->isSelected(m_listBox->item(nr))) return -1;
+ #endif
+ return nr;
+}
+
+void OEditListBox::removeItem()
+{
+ int selected = m_listBox->currentItem();
+
+ if ( selected >= 0 )
+ {
+ QString removedText = m_listBox->currentText();
+
+ m_listBox->removeItem( selected );
+ if ( count() > 0 )
+ m_listBox->setSelected( QMIN( selected, count() - 1 ), true );
+
+ emit changed();
+ emit removed( removedText );
+ }
+
+ if ( servRemoveButton && m_listBox->currentItem() == -1 )
+ servRemoveButton->setEnabled(false);
+}
+
+void OEditListBox::enableMoveButtons(int index)
+{
+ // Update the lineEdit when we select a different line.
+ if(currentText() != m_lineEdit->text())
+ m_lineEdit->setText(currentText());
+
+ bool moveEnabled = servUpButton && servDownButton;
+
+ if (moveEnabled )
+ {
+ if (m_listBox->count() <= 1)
+ {
+ servUpButton->setEnabled(false);
+ servDownButton->setEnabled(false);
+ }
+ else if ((uint) index == (m_listBox->count() - 1))
+ {
+ servUpButton->setEnabled(true);
+ servDownButton->setEnabled(false);
+ }
+ else if (index == 0)
+ {
+ servUpButton->setEnabled(false);
+ servDownButton->setEnabled(true);
+ }
+ else
+ {
+ servUpButton->setEnabled(true);
+ servDownButton->setEnabled(true);
+ }
+ }
+
+ if ( servRemoveButton )
+ servRemoveButton->setEnabled(true);
+}
+
+void OEditListBox::clear()
+{
+ m_lineEdit->clear();
+ m_listBox->clear();
+ emit changed();
+}
+
+void OEditListBox::insertStringList(const QStringList& list, int index)
+{
+ m_listBox->insertStringList(list,index);
+}
+
+void OEditListBox::insertStrList(const QStrList* list, int index)
+{
+ m_listBox->insertStrList(list,index);
+}
+
+void OEditListBox::insertStrList(const QStrList& list, int index)
+{
+ m_listBox->insertStrList(list,index);
+}
+
+void OEditListBox::insertStrList(const char ** list, int numStrings, int index)
+{
+ m_listBox->insertStrList(list,numStrings,index);
+}
+
+QStringList OEditListBox::items() const
+{
+ QStringList list;
+ for ( uint i = 0; i < m_listBox->count(); i++ )
+ list.append( m_listBox->text( i ));
+
+ return list;
+}
+
+void OEditListBox::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+
+/*======================================================================================
+ * CustomEditor
+ *======================================================================================*/
+
+OEditListBox::CustomEditor::CustomEditor( OComboBox *combo )
+{
+ m_representationWidget = combo;
+ m_lineEdit = dynamic_cast<OLineEdit*>( combo->lineEdit() );
+ assert( m_lineEdit );
+}
diff --git a/libopie2/qt3/opieui/oeditlistbox.h b/libopie2/qt3/opieui/oeditlistbox.h
new file mode 100644
index 0000000..63fab11
--- a/dev/null
+++ b/libopie2/qt3/opieui/oeditlistbox.h
@@ -0,0 +1,250 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef OEDITLISTBOX_H
+#define OEDITLISTBOX_H
+
+#include <qgroupbox.h>
+#include <qlistbox.h>
+
+class OLineEdit;
+class OComboBox;
+class QPushButton;
+
+#if QT_VERSION < 300
+ enum StringComparisonMode {
+ CaseSensitive = 0x00001, // 0 0001
+ BeginsWith = 0x00002, // 0 0010
+ EndsWith = 0x00004, // 0 0100
+ Contains = 0x00008, // 0 1000
+ ExactMatch = 0x00010 // 1 0000
+ };
+#endif
+
+class OEditListBoxPrivate;
+/**
+ * An editable listbox
+ *
+ * This class provides a editable listbox ;-), this means
+ * a listbox which is accompanied by a line edit to enter new
+ * items into the listbox and pushbuttons to add and remove
+ * items from the listbox and two buttons to move items up and down.
+ */
+class OEditListBox : public QGroupBox
+{
+ Q_OBJECT
+
+public:
+ /// @since 3.1
+ class CustomEditor
+ {
+ public:
+ CustomEditor()
+ : m_representationWidget( 0L ),
+ m_lineEdit( 0L ) {}
+ CustomEditor( QWidget *repWidget, OLineEdit *edit )
+ : m_representationWidget( repWidget ),
+ m_lineEdit( edit ) {}
+ CustomEditor( OComboBox *combo );
+
+ void setRepresentationWidget( QWidget *repWidget ) {
+ m_representationWidget = repWidget;
+ }
+ void setLineEdit( OLineEdit *edit ) {
+ m_lineEdit = edit;
+ }
+
+ virtual QWidget *representationWidget() const {
+ return m_representationWidget;
+ }
+ virtual OLineEdit *lineEdit() const {
+ return m_lineEdit;
+ }
+
+ protected:
+ QWidget *m_representationWidget;
+ OLineEdit *m_lineEdit;
+ };
+
+ public:
+
+ /**
+ * Enumeration of the buttons, the listbox offers. Specify them in the
+ * constructor in the buttons parameter.
+ */
+ enum Button { Add = 1, Remove = 2, UpDown = 4, All = Add|Remove|UpDown };
+
+ /**
+ * Create an editable listbox.
+ *
+ * If @p checkAtEntering is true, after every character you type
+ * in the line edit OEditListBox will enable or disable
+ * the Add-button, depending whether the current content of the
+ * line edit is already in the listbox. Maybe this can become a
+ * performance hit with large lists on slow machines.
+ * If @p checkAtEntering is false,
+ * it will be checked if you press the Add-button. It is not
+ * possible to enter items twice into the listbox.
+ */
+ OEditListBox(QWidget *parent = 0, const char *name = 0,
+ bool checkAtEntering=false, int buttons = All );
+ /**
+ * Create an editable listbox.
+ *
+ * The same as the other constructor, additionally it takes
+ * @title, which will be the title of the frame around the listbox.
+ */
+ OEditListBox(const QString& title, QWidget *parent = 0,
+ const char *name = 0, bool checkAtEntering=false,
+ int buttons = All );
+
+ /**
+ * Another constructor, which allows to use a custom editing widget
+ * instead of the standard OLineEdit widget. E.g. you can use a
+ * @ref OURLRequester or a @ref OComboBox as input widget. The custom
+ * editor must consist of a lineedit and optionally another widget that
+ * is used as representation. A OComboBox or a OURLRequester have a
+ * OLineEdit as child-widget for example, so the OComboBox is used as
+ * the representation widget.
+ *
+ * @see OURLRequester::customEditor()
+ * @since 3.1
+ */
+ OEditListBox( const QString& title,
+ const CustomEditor &customEditor,
+ QWidget *parent = 0, const char *name = 0,
+ bool checkAtEntering = false, int buttons = All );
+
+ virtual ~OEditListBox();
+
+ /**
+ * Return a pointer to the embedded QListBox.
+ */
+ QListBox* listBox() const { return m_listBox; }
+ /**
+ * Return a pointer to the embedded QLineEdit.
+ */
+ OLineEdit* lineEdit() const { return m_lineEdit; }
+ /**
+ * Return a pointer to the Add button
+ */
+ QPushButton* addButton() const { return servNewButton; }
+ /**
+ * Return a pointer to the Remove button
+ */
+ QPushButton* removeButton() const { return servRemoveButton; }
+ /**
+ * Return a pointer to the Up button
+ */
+ QPushButton* upButton() const { return servUpButton; }
+ /**
+ * Return a pointer to the Down button
+ */
+ QPushButton* downButton() const { return servDownButton; }
+
+ /**
+ * See @ref QListBox::count()
+ */
+ int count() const { return int(m_listBox->count()); }
+ /**
+ * See @ref QListBox::insertStringList()
+ */
+ void insertStringList(const QStringList& list, int index=-1);
+ /**
+ * See @ref QListBox::insertStringList()
+ */
+ void insertStrList(const QStrList* list, int index=-1);
+ /**
+ * See @ref QListBox::insertStrList()
+ */
+ void insertStrList(const QStrList& list, int index=-1);
+ /**
+ * See @ref QListBox::insertStrList()
+ */
+ void insertStrList(const char ** list, int numStrings=-1, int index=-1);
+ /**
+ * See @ref QListBox::insertItem()
+ */
+ void insertItem(const QString& text, int index=-1) {m_listBox->insertItem(text,index);}
+ /**
+ * Clears both the listbox and the line edit.
+ */
+ void clear();
+ /**
+ * See @ref QListBox::text()
+ */
+ QString text(int index) const { return m_listBox->text(index); }
+ /**
+ * See @ref QListBox::currentItem()
+ */
+ int currentItem() const;
+ /**
+ * See @ref QListBox::currentText()
+ */
+ QString currentText() const { return m_listBox->currentText(); }
+
+ /**
+ * @returns a stringlist of all items in the listbox
+ */
+ QStringList items() const;
+
+ signals:
+ void changed();
+
+ /**
+ * This signal is emitted when the user adds a new string to the list,
+ * the parameter is the added string.
+ * @since 3.2
+ */
+ void added( const QString & text );
+
+ /**
+ * This signal is emitted when the user removes a string from the list,
+ * the parameter is the removed string.
+ * @since 3.2
+ */
+ void removed( const QString & text );
+
+ protected slots:
+ //the names should be self-explaining
+ void moveItemUp();
+ void moveItemDown();
+ void addItem();
+ void removeItem();
+ void enableMoveButtons(int index);
+ void typedSomething(const QString& text);
+
+ private:
+ QListBox *m_listBox;
+ QPushButton *servUpButton, *servDownButton;
+ QPushButton *servNewButton, *servRemoveButton;
+ OLineEdit *m_lineEdit;
+
+ //this is called in both ctors, to avoid code duplication
+ void init( bool checkAtEntering, int buttons,
+ QWidget *representationWidget = 0L );
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ //our lovely private d-pointer
+ OEditListBoxPrivate *d;
+};
+
+#endif // OEDITLISTBOX
diff --git a/libopie2/qt3/opieui/ojanuswidget.cpp b/libopie2/qt3/opieui/ojanuswidget.cpp
new file mode 100644
index 0000000..0a037ff
--- a/dev/null
+++ b/libopie2/qt3/opieui/ojanuswidget.cpp
@@ -0,0 +1,1116 @@
+/*
+                 This file is part of the Opie Project
+
+ Originally part of the KDE project
+ (C) 1999-2000 Espen Sand (espensa@online.no)
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* QT */
+
+#include <qbitmap.h>
+#include <qgrid.h>
+#include <qhbox.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qobjectlist.h>
+#include <qpixmap.h>
+#include <qlistview.h>
+#include <qsplitter.h>
+#include <qtabwidget.h>
+#include <qvbox.h>
+#include <qwidgetstack.h>
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qstyle.h>
+
+/* OPIE */
+
+#include <opie2/odialog.h>
+#include <opie2/oseparator.h>
+#include <opie2/ojanuswidget.h>
+
+/*======================================================================================
+ * IconListItem
+ *======================================================================================*/
+
+class OJanusWidget::IconListItem : public QListBoxItem
+{
+ public:
+ IconListItem( QListBox *listbox, const QPixmap &pixmap,
+ const QString &text );
+ virtual int height( const QListBox *lb ) const;
+ virtual int width( const QListBox *lb ) const;
+ int expandMinimumWidth( int width );
+
+ protected:
+ const QPixmap &defaultPixmap();
+ void paint( QPainter *painter );
+
+ private:
+ QPixmap mPixmap;
+ int mMinimumWidth;
+};
+
+template class QPtrList<QListViewItem>;
+
+/*======================================================================================
+ * OJanusWidget
+ *======================================================================================*/
+
+OJanusWidget::OJanusWidget( QWidget *parent, const char *name, int face )
+ : QWidget( parent, name, 0 ),
+ mValid(false), mPageList(0),
+ mTitleList(0), mFace(face), mTitleLabel(0), mActivePageWidget(0),
+ mShowIconsInTreeList(false), d(0)
+{
+ QVBoxLayout *topLayout = new QVBoxLayout( this );
+
+ if( mFace == TreeList || mFace == IconList )
+ {
+ mPageList = new QPtrList<QWidget>;
+ mTitleList = new QStringList();
+
+ QFrame *page;
+ if( mFace == TreeList )
+ {
+ QSplitter *splitter = new QSplitter( this );
+ topLayout->addWidget( splitter, 10 );
+ mTreeListResizeMode = QSplitter::KeepSize;
+
+ mTreeList = new QListView( splitter );
+ mTreeList->addColumn( QString::fromLatin1("") );
+ mTreeList->header()->hide();
+ mTreeList->setRootIsDecorated(true);
+ mTreeList->setSorting( -1 );
+ connect( mTreeList, SIGNAL(selectionChanged()), SLOT(slotShowPage()) );
+ connect( mTreeList, SIGNAL(clicked(QListViewItem *)), SLOT(slotItemClicked(QListViewItem *)));
+
+ //
+ // Page area. Title at top with a separator below and a pagestack using
+ // all available space at bottom.
+ //
+ QFrame *p = new QFrame( splitter );
+
+ QHBoxLayout *hbox = new QHBoxLayout( p, 0, 0 );
+ hbox->addSpacing( ODialog::spacingHint() );
+
+ page = new QFrame( p );
+ hbox->addWidget( page, 10 );
+ }
+ else
+ {
+ QHBoxLayout *hbox = new QHBoxLayout( topLayout );
+ mIconList = new IconListBox( this );
+
+ QFont listFont( mIconList->font() );
+ listFont.setBold( true );
+ mIconList->setFont( listFont );
+
+ mIconList->verticalScrollBar()->installEventFilter( this );
+ hbox->addWidget( mIconList );
+ connect( mIconList, SIGNAL(selectionChanged()), SLOT(slotShowPage()));
+ hbox->addSpacing( ODialog::spacingHint() );
+ page = new QFrame( this );
+ hbox->addWidget( page, 10 );
+ }
+
+ //
+ // Rest of page area. Title at top with a separator below and a
+ // pagestack using all available space at bottom.
+ //
+
+ QVBoxLayout *vbox = new QVBoxLayout( page, 0, ODialog::spacingHint() );
+
+ mTitleLabel = new QLabel( QString::fromLatin1("Empty page"), page, "OJanusWidgetTitleLabel" );
+ vbox->addWidget( mTitleLabel );
+
+ QFont titleFont( mTitleLabel->font() );
+ titleFont.setBold( true );
+ mTitleLabel->setFont( titleFont );
+
+ mTitleSep = new OSeparator( page );
+ mTitleSep->setFrameStyle( QFrame::HLine|QFrame::Plain );
+ vbox->addWidget( mTitleSep );
+
+ mPageStack = new QWidgetStack( page );
+ connect(mPageStack, SIGNAL(aboutToShow(QWidget *)),
+ this, SIGNAL(aboutToShowPage(QWidget *)));
+ vbox->addWidget( mPageStack, 10 );
+ }
+ else if( mFace == Tabbed )
+ {
+ mPageList = new QPtrList<QWidget>;
+
+ mTabControl = new QTabWidget( this );
+ mTabControl->setMargin (ODialog::marginHint());
+ topLayout->addWidget( mTabControl, 10 );
+ }
+ else if( mFace == Swallow )
+ {
+ mSwallowPage = new QWidget( this );
+ topLayout->addWidget( mSwallowPage, 10 );
+ }
+ else
+ {
+ mFace = Plain;
+ mPlainPage = new QFrame( this );
+ topLayout->addWidget( mPlainPage, 10 );
+ }
+
+ /* FIXME: Revise for Opie
+ if ( kapp )
+ connect(kapp,SIGNAL(kdisplayFontChanged()),SLOT(slotFontChanged()));
+ */
+
+ mValid = true;
+
+ setSwallowedWidget(0); // Set default size if 'mFace' is Swallow.
+}
+
+
+OJanusWidget::~OJanusWidget()
+{
+ delete mPageList;
+ mPageList = 0;
+ delete mTitleList;
+ mTitleList = 0;
+}
+
+
+bool OJanusWidget::isValid() const
+{
+ return( mValid );
+}
+
+
+QFrame *OJanusWidget::plainPage()
+{
+ return( mPlainPage );
+}
+
+
+int OJanusWidget::face() const
+{
+ return( mFace );
+}
+
+QWidget *OJanusWidget::FindParent()
+{
+ if( mFace == Tabbed ) {
+ return mTabControl;
+ }
+ else {
+ return this;
+ }
+}
+
+QFrame *OJanusWidget::addPage( const QStringList &items, const QString &header,
+ const QPixmap &pixmap )
+{
+ if( mValid == false )
+ {
+ qDebug( "addPage: Invalid object" );
+ return( 0 );
+ }
+
+ QFrame *page = new QFrame( FindParent(), "page" );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+void OJanusWidget::pageGone( QObject *obj )
+{
+ removePage( static_cast<QWidget*>( obj ) );
+}
+
+void OJanusWidget::slotReopen( QListViewItem * item )
+{
+ if( item )
+ item->setOpen( true );
+}
+
+QFrame *OJanusWidget::addPage( const QString &itemName, const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addPage(items, header, pixmap);
+}
+
+
+
+QVBox *OJanusWidget::addVBoxPage( const QStringList &items,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ if( mValid == false )
+ {
+ qDebug( "addPage: Invalid object" );
+ return( 0 );
+ }
+
+ QVBox *page = new QVBox(FindParent() , "page" );
+ page->setSpacing( ODialog::spacingHint() );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+QVBox *OJanusWidget::addVBoxPage( const QString &itemName,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addVBoxPage(items, header, pixmap);
+}
+
+QHBox *OJanusWidget::addHBoxPage( const QStringList &items,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ if( mValid == false ) {
+ qDebug( "addPage: Invalid object" );
+ return( 0 );
+ }
+
+ QHBox *page = new QHBox(FindParent(), "page");
+ page->setSpacing( ODialog::spacingHint() );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+QHBox *OJanusWidget::addHBoxPage( const QString &itemName,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addHBoxPage(items, header, pixmap);
+}
+
+QGrid *OJanusWidget::addGridPage( int n, Orientation dir,
+ const QStringList &items,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ if( mValid == false )
+ {
+ qDebug( "addPage: Invalid object" );
+ return( 0 );
+ }
+
+ QGrid *page = new QGrid( n, dir, FindParent(), "page" );
+ page->setSpacing( ODialog::spacingHint() );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+
+QGrid *OJanusWidget::addGridPage( int n, Orientation dir,
+ const QString &itemName,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addGridPage(n, dir, items, header, pixmap);
+}
+
+void OJanusWidget::InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page)
+{
+ bool isTop = true;
+ QListViewItem *curTop = 0, *child, *last, *newChild;
+ unsigned int index = 1;
+ QStringList curPath;
+
+ for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it, index++ ) {
+ QString name = (*it);
+ bool isPath = ( index != items.count() );
+
+ // Find the first child.
+ if (isTop) {
+ child = mTreeList->firstChild();
+ }
+ else {
+ child = curTop->firstChild();
+ }
+
+ // Now search for a child with the current Name, and if it we doesn't
+ // find it, then remember the location of the last child.
+ for (last = 0; child && child->text(0) != name ; last = child, child = child->nextSibling());
+
+ if (last == 0 && child == 0) {
+ // This node didn't have any children at all, lets just insert the
+ // new child.
+ if (isTop)
+ newChild = new QListViewItem(mTreeList, name);
+ else
+ newChild = new QListViewItem(curTop, name);
+
+ }
+ else if (child != 0) {
+ // we found the given name in this child.
+ if (!isPath) {
+ qDebug( "The element inserted was already in the TreeList box!" );
+ return;
+ }
+ else {
+ // Ok we found the folder
+ newChild = child;
+ }
+ }
+ else {
+ // the node had some children, but we didn't find the given name
+ if (isTop)
+ newChild = new QListViewItem(mTreeList, last, name);
+ else
+ newChild = new QListViewItem(curTop, last, name);
+ }
+
+ // Now make the element expandable if it is a path component, and make
+ // ready for next loop
+ if (isPath) {
+ newChild->setExpandable(true);
+ curTop = newChild;
+ isTop = false;
+ curPath << name;
+
+ QString key = curPath.join("_/_");
+ if (mFolderIconMap.contains(key)) {
+ QPixmap p = mFolderIconMap[key];
+ newChild->setPixmap(0,p);
+ }
+ }
+ else {
+ if (mShowIconsInTreeList) {
+ newChild->setPixmap(0, pixmap);
+ }
+ mTreeListToPageStack.insert(newChild, page);
+ }
+ }
+}
+
+void OJanusWidget::addPageWidget( QFrame *page, const QStringList &items,
+ const QString &header,const QPixmap &pixmap )
+{
+ connect(page, SIGNAL(destroyed(QObject*)), SLOT(pageGone(QObject*)));
+
+ if( mFace == Tabbed )
+ {
+ mTabControl->addTab (page, items.last());
+ mPageList->append (page);
+ }
+ else if( mFace == TreeList || mFace == IconList )
+ {
+ mPageList->append( page );
+ mPageStack->addWidget( page, 0 );
+
+ if (items.count() == 0) {
+ qDebug( "Invalid QStringList, with zero items" );
+ return;
+ }
+
+ if( mFace == TreeList )
+ {
+ InsertTreeListItem(items, pixmap, page);
+ }
+ else // mFace == IconList
+ {
+ QString itemName = items.last();
+ IconListItem *item = new IconListItem( mIconList, pixmap, itemName );
+ //
+ // 2000-06-01 Espen Sand: If I do this with Qt 2.1.1 all sorts of
+ // strange things happen. With Qt <= 2.1 it worked but now I must
+ // either specify the listbox in the constructor on the item
+ // or as below, not both.
+ // mIconList->insertItem( item );
+ //
+ mIconListToPageStack.insert(item, page);
+ mIconList->invalidateHeight();
+ mIconList->invalidateWidth();
+
+ if (mIconList->isVisible())
+ mIconList->updateWidth();
+ }
+
+ //
+ // Make sure the title label is sufficiently wide
+ //
+ QString lastName = items.last();
+ const QString &title = (header != QString::null ? header : lastName);
+ QRect r = mTitleLabel->fontMetrics().boundingRect( title );
+ if( mTitleLabel->minimumWidth() < r.width() )
+ {
+ mTitleLabel->setMinimumWidth( r.width() );
+ }
+ mTitleList->append( title );
+
+ if( mTitleList->count() == 1 )
+ {
+ showPage(0);
+ }
+ }
+ else
+ {
+ qDebug( "OJanusWidget::addPageWidget: can only add a page in Tabbed, TreeList or IconList modes" );
+ }
+
+}
+
+void OJanusWidget::setFolderIcon(const QStringList &path, const QPixmap &pixmap)
+{
+ QString key = path.join("_/_");
+ mFolderIconMap.insert(key,pixmap);
+}
+
+
+
+bool OJanusWidget::setSwallowedWidget( QWidget *widget )
+{
+ if( mFace != Swallow || mValid == false )
+ {
+ return( false );
+ }
+
+ //
+ // Remove current layout and make a new.
+ //
+ if( mSwallowPage->layout() != 0 )
+ {
+ delete mSwallowPage->layout();
+ }
+ QGridLayout *gbox = new QGridLayout( mSwallowPage, 1, 1, 0 );
+
+ //
+ // Hide old children
+ //
+ QObjectList *l = (QObjectList*)mSwallowPage->children(); // silence please
+ for( uint i=0; i < l->count(); i++ )
+ {
+ QObject *o = l->at(i);
+ if( o->isWidgetType() )
+ {
+ ((QWidget*)o)->hide();
+ }
+ }
+
+ //
+ // Add new child or make default size
+ //
+ if( widget == 0 )
+ {
+ gbox->addRowSpacing(0,100);
+ gbox->addColSpacing(0,100);
+ mSwallowPage->setMinimumSize(100,100);
+ }
+ else
+ {
+ if( widget->parent() != mSwallowPage )
+ {
+ widget->reparent( mSwallowPage, 0, QPoint(0,0) );
+ }
+ gbox->addWidget(widget, 0, 0 );
+ gbox->activate();
+ mSwallowPage->setMinimumSize( widget->minimumSize() );
+ }
+
+ return( true );
+}
+
+bool OJanusWidget::slotShowPage()
+{
+ if( mValid == false )
+ {
+ return( false );
+ }
+
+ if( mFace == TreeList )
+ {
+ QListViewItem *node = mTreeList->selectedItem();
+ if( node == 0 ) { return( false ); }
+
+ QWidget *stackItem = mTreeListToPageStack[node];
+ return showPage(stackItem);
+ }
+ else if( mFace == IconList )
+ {
+ QListBoxItem *node = mIconList->item( mIconList->currentItem() );
+ if( node == 0 ) { return( false ); }
+ QWidget *stackItem = mIconListToPageStack[node];
+ return showPage(stackItem);
+ }
+
+ return( false );
+}
+
+
+bool OJanusWidget::showPage( int index )
+{
+ if( mPageList == 0 || mValid == false )
+ {
+ return( false );
+ }
+ else
+ {
+ return showPage(mPageList->at(index));
+ }
+}
+
+
+bool OJanusWidget::showPage( QWidget *w )
+{
+ if( w == 0 || mValid == false )
+ {
+ return( false );
+ }
+
+ if( mFace == TreeList || mFace == IconList )
+ {
+ mPageStack->raiseWidget( w );
+ mActivePageWidget = w;
+
+ int index = mPageList->findRef( w );
+ mTitleLabel->setText( *mTitleList->at(index) );
+ if( mFace == TreeList )
+ {
+ QMap<QListViewItem *, QWidget *>::Iterator it;
+ for (it = mTreeListToPageStack.begin(); it != mTreeListToPageStack.end(); ++it){
+ QListViewItem *key = it.key();
+ QWidget *val = it.data();
+ if (val == w) {
+ mTreeList->setSelected(key, true );
+ break;
+ }
+ }
+ }
+ else
+ {
+ QMap<QListBoxItem *, QWidget *>::Iterator it;
+ for (it = mIconListToPageStack.begin(); it != mIconListToPageStack.end(); ++it){
+ QListBoxItem *key = it.key();
+ QWidget *val = it.data();
+ if (val == w) {
+ mIconList->setSelected( key, true );
+ break;
+ }
+ }
+
+ //
+ // 2000-02-13 Espen Sand
+ // Don't ask me why (because I don't know). If I select a page
+ // with the mouse the page is not updated until it receives an
+ // event. It seems this event get lost if the mouse is not moved
+ // when released. The timer ensures the update
+ //
+ QTimer::singleShot( 0, mActivePageWidget, SLOT(update()) );
+ }
+ }
+ else if( mFace == Tabbed )
+ {
+ mTabControl->showPage(w);
+ mActivePageWidget = w;
+ }
+ else
+ {
+ return( false );
+ }
+
+ return( true );
+}
+
+
+int OJanusWidget::activePageIndex() const
+{
+ if( mFace == TreeList) {
+ QListViewItem *node = mTreeList->selectedItem();
+ if( node == 0 ) { return -1; }
+ QWidget *stackItem = mTreeListToPageStack[node];
+ return mPageList->findRef(stackItem);
+ }
+ else if (mFace == IconList) {
+ QListBoxItem *node = mIconList->item( mIconList->currentItem() );
+ if( node == 0 ) { return( false ); }
+ QWidget *stackItem = mIconListToPageStack[node];
+ return mPageList->findRef(stackItem);
+ }
+ else if( mFace == Tabbed ) {
+ QWidget *widget = mTabControl->currentPage();
+ return( widget == 0 ? -1 : mPageList->findRef( widget ) );
+ }
+ else {
+ return( -1 );
+ }
+}
+
+
+int OJanusWidget::pageIndex( QWidget *widget ) const
+{
+ if( widget == 0 )
+ {
+ return( -1 );
+ }
+ else if( mFace == TreeList || mFace == IconList )
+ {
+ return( mPageList->findRef( widget ) );
+ }
+ else if( mFace == Tabbed )
+ {
+ //
+ // The user gets the real page widget with addVBoxPage(), addHBoxPage()
+ // and addGridPage() but not with addPage() which returns a child of
+ // the toplevel page. addPage() returns a QFrame so I check for that.
+ //
+ if( widget->isA("QFrame") )
+ {
+ return( mPageList->findRef( widget->parentWidget() ) );
+ }
+ else
+ {
+ return( mPageList->findRef( widget ) );
+ }
+ }
+ else
+ {
+ return( -1 );
+ }
+}
+
+void OJanusWidget::slotFontChanged()
+{
+#ifdef FIXME
+
+ if ( mTitleLabel != 0 )
+ {
+ mTitleLabel->setFont( KGlobalSettings::generalFont() );
+ QFont titleFont( mTitleLabel->font() );
+ titleFont.setBold( true );
+ mTitleLabel->setFont( titleFont );
+ }
+#endif
+
+ if( mFace == IconList )
+ {
+ QFont listFont( mIconList->font() );
+ listFont.setBold( true );
+ mIconList->setFont( listFont );
+ mIconList->invalidateHeight();
+ mIconList->invalidateWidth();
+ }
+}
+
+// makes the treelist behave like the list of kcontrol
+void OJanusWidget::slotItemClicked(QListViewItem *it)
+{
+ if(it && (it->childCount()>0))
+ it->setOpen(!it->isOpen());
+}
+
+void OJanusWidget::setFocus()
+{
+ if( mValid == false ) { return; }
+ if( mFace == TreeList )
+ {
+ mTreeList->setFocus();
+ }
+ if( mFace == IconList )
+ {
+ mIconList->setFocus();
+ }
+ else if( mFace == Tabbed )
+ {
+ mTabControl->setFocus();
+ }
+ else if( mFace == Swallow )
+ {
+ mSwallowPage->setFocus();
+ }
+ else if( mFace == Plain )
+ {
+ mPlainPage->setFocus();
+ }
+}
+
+
+QSize OJanusWidget::minimumSizeHint() const
+{
+ if( mFace == TreeList || mFace == IconList )
+ {
+ QSize s1( ODialog::spacingHint(), ODialog::spacingHint()*2 );
+ QSize s2(0,0);
+ QSize s3(0,0);
+ QSize s4( mPageStack->sizeHint() );
+
+ if( mFace == TreeList )
+ {
+#if QT_VERSION < 300
+ s1.rwidth() += style().splitterWidth();
+#else
+ s1.rwidth() += style().pixelMetric( QStyle::PM_SplitterWidth );
+#endif
+ s2 = mTreeList->minimumSize();
+ }
+ else
+ {
+ mIconList->updateMinimumHeight();
+ mIconList->updateWidth();
+ s2 = mIconList->minimumSize();
+ }
+
+ if( mTitleLabel->isVisible() == true )
+ {
+ s3 += mTitleLabel->sizeHint();
+ s3.rheight() += mTitleSep->minimumSize().height();
+ }
+
+ //
+ // Select the tallest item. It has only effect in IconList mode
+ //
+ int h1 = s1.rheight() + s3.rheight() + s4.height();
+ int h2 = QMAX( h1, s2.rheight() );
+
+ return( QSize( s1.width()+s2.width()+QMAX(s3.width(),s4.width()), h2 ) );
+ }
+ else if( mFace == Tabbed )
+ {
+ return( mTabControl->sizeHint() );
+ }
+ else if( mFace == Swallow )
+ {
+ return( mSwallowPage->minimumSize() );
+ }
+ else if( mFace == Plain )
+ {
+ return( mPlainPage->sizeHint() );
+ }
+ else
+ {
+ return( QSize( 100, 100 ) ); // Should never happen though.
+ }
+
+}
+
+
+QSize OJanusWidget::sizeHint() const
+{
+ return( minimumSizeHint() );
+}
+
+
+void OJanusWidget::setTreeListAutoResize( bool state )
+{
+ if( mFace == TreeList )
+ {
+ mTreeListResizeMode = state == false ?
+ QSplitter::KeepSize : QSplitter::Stretch;
+ QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget());
+ splitter->setResizeMode( mTreeList, mTreeListResizeMode );
+ }
+}
+
+
+void OJanusWidget::setIconListAllVisible( bool state )
+{
+ if( mFace == IconList )
+ {
+ mIconList->setShowAll( state );
+ }
+}
+
+void OJanusWidget::setShowIconsInTreeList( bool state )
+{
+ mShowIconsInTreeList = state;
+}
+
+void OJanusWidget::setRootIsDecorated( bool state )
+{
+ if( mFace == TreeList ) {
+ mTreeList->setRootIsDecorated(state);
+ }
+}
+
+void OJanusWidget::unfoldTreeList( bool persist )
+{
+ if( mFace == TreeList )
+ {
+ if( persist )
+ connect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
+ else
+ disconnect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
+
+ for( QListViewItem * item = mTreeList->firstChild(); item; item = item->itemBelow() )
+ item->setOpen( true );
+ }
+}
+
+void OJanusWidget::showEvent( QShowEvent * )
+{
+ if( mFace == TreeList )
+ {
+ QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget());
+ splitter->setResizeMode( mTreeList, mTreeListResizeMode );
+ }
+}
+
+
+//
+// 2000-13-02 Espen Sand
+// It should be obvious that this eventfilter must only be
+// be installed on the vertical scrollbar of the mIconList.
+//
+bool OJanusWidget::eventFilter( QObject *o, QEvent *e )
+{
+ if( e->type() == QEvent::Show )
+ {
+ IconListItem *item = (IconListItem*)mIconList->item(0);
+ if( item != 0 )
+ {
+ int lw = item->width( mIconList );
+ int sw = mIconList->verticalScrollBar()->sizeHint().width();
+ mIconList->setFixedWidth( lw+sw+mIconList->frameWidth()*2 );
+ }
+ }
+ else if( e->type() == QEvent::Hide )
+ {
+ IconListItem *item = (IconListItem*)mIconList->item(0);
+ if( item != 0 )
+ {
+ int lw = item->width( mIconList );
+ mIconList->setFixedWidth( lw+mIconList->frameWidth()*2 );
+ }
+ }
+ return QWidget::eventFilter( o, e );
+}
+
+
+
+//
+// Code for the icon list box
+//
+
+
+OJanusWidget::IconListBox::IconListBox( QWidget *parent, const char *name,
+ WFlags f )
+ :QListBox( parent, name, f ), mShowAll(false), mHeightValid(false),
+ mWidthValid(false)
+{
+}
+
+
+void OJanusWidget::IconListBox::updateMinimumHeight()
+{
+ if( mShowAll == true && mHeightValid == false )
+ {
+ int h = frameWidth()*2;
+ for( QListBoxItem *i = item(0); i != 0; i = i->next() )
+ {
+ h += i->height( this );
+ }
+ setMinimumHeight( h );
+ mHeightValid = true;
+ }
+}
+
+
+void OJanusWidget::IconListBox::updateWidth()
+{
+ if( mWidthValid == false )
+ {
+ int maxWidth = 10;
+ for( QListBoxItem *i = item(0); i != 0; i = i->next() )
+ {
+ int w = ((IconListItem *)i)->width(this);
+ maxWidth = QMAX( w, maxWidth );
+ }
+
+ for( QListBoxItem *i = item(0); i != 0; i = i->next() )
+ {
+ ((IconListItem *)i)->expandMinimumWidth( maxWidth );
+ }
+
+ if( verticalScrollBar()->isVisible() )
+ {
+ maxWidth += verticalScrollBar()->sizeHint().width();
+ }
+
+ setFixedWidth( maxWidth + frameWidth()*2 );
+ mWidthValid = true;
+ }
+}
+
+
+void OJanusWidget::IconListBox::invalidateHeight()
+{
+ mHeightValid = false;
+}
+
+
+void OJanusWidget::IconListBox::invalidateWidth()
+{
+ mWidthValid = false;
+}
+
+
+void OJanusWidget::IconListBox::setShowAll( bool showAll )
+{
+ mShowAll = showAll;
+ mHeightValid = false;
+}
+
+
+
+OJanusWidget::IconListItem::IconListItem( QListBox *listbox, const QPixmap &pixmap,
+ const QString &text )
+ : QListBoxItem( listbox )
+{
+ mPixmap = pixmap;
+ if( mPixmap.isNull() == true )
+ {
+ mPixmap = defaultPixmap();
+ }
+ setText( text );
+ mMinimumWidth = 0;
+}
+
+
+int OJanusWidget::IconListItem::expandMinimumWidth( int width )
+{
+ mMinimumWidth = QMAX( mMinimumWidth, width );
+ return( mMinimumWidth );
+}
+
+
+const QPixmap &OJanusWidget::IconListItem::defaultPixmap()
+{
+ static QPixmap *pix=0;
+ if( pix == 0 )
+ {
+ pix = new QPixmap( 32, 32 );
+ QPainter p( pix );
+ p.eraseRect( 0, 0, pix->width(), pix->height() );
+ p.setPen( Qt::red );
+ p.drawRect ( 0, 0, pix->width(), pix->height() );
+ p.end();
+
+ QBitmap mask( pix->width(), pix->height(), true );
+ mask.fill( Qt::black );
+ p.begin( &mask );
+ p.setPen( Qt::white );
+ p.drawRect ( 0, 0, pix->width(), pix->height() );
+ p.end();
+
+ pix->setMask( mask );
+ }
+ return( *pix );
+}
+
+
+void OJanusWidget::IconListItem::paint( QPainter *painter )
+{
+ QFontMetrics fm = painter->fontMetrics();
+ //int wt = fm.boundingRect(text()).width();
+ int wp = mPixmap.width();
+ int ht = fm.lineSpacing();
+ int hp = mPixmap.height();
+
+ painter->drawPixmap( (mMinimumWidth-wp)/2, 5, mPixmap );
+ if( text().isEmpty() == false )
+ {
+ painter->drawText( 0, hp+7, mMinimumWidth, ht, Qt::AlignCenter, text() );
+ }
+}
+
+int OJanusWidget::IconListItem::height( const QListBox *lb ) const
+{
+ if( text().isEmpty() == true )
+ {
+ return( mPixmap.height() );
+ }
+ else
+ {
+ return( mPixmap.height() + lb->fontMetrics().lineSpacing()+10 );
+ }
+}
+
+
+int OJanusWidget::IconListItem::width( const QListBox *lb ) const
+{
+ int wt = lb->fontMetrics().boundingRect(text()).width()+10;
+ int wp = mPixmap.width() + 10;
+ int w = QMAX( wt, wp );
+ return( QMAX( w, mMinimumWidth ) );
+}
+
+// Just remove the page from our stack of widgets. Do not modify the given widget in
+// any way. No memory leak occurs as parent is not changed.
+// Make this virtual in KDE 4.0.
+// Ravikiran Rajagopal <ravi@ee.eng.ohio-state.edu>
+void OJanusWidget::removePage( QWidget *page )
+{
+ if (!mPageList || !mPageList->containsRef(page))
+ return;
+
+ int index = mPageList->findRef( page );
+ if ( mTitleList )
+ mTitleList->remove(mTitleList->at(index));
+
+ mPageList->removeRef(page);
+
+ if ( mFace == TreeList )
+ {
+ QMap<QListViewItem*, QWidget *>::Iterator i;
+ for( i = mTreeListToPageStack.begin(); i != mTreeListToPageStack.end(); ++i )
+ if (i.data()==page)
+ {
+ delete i.key();
+ mPageStack->removeWidget(page);
+ mTreeListToPageStack.remove(i);
+ break;
+ }
+ }
+ else if ( mFace == IconList )
+ {
+ QMap<QListBoxItem*, QWidget *>::Iterator i;
+ for( i = mIconListToPageStack.begin(); i != mIconListToPageStack.end(); ++i )
+ if (i.data()==page)
+ {
+ delete i.key();
+ mPageStack->removeWidget(page);
+ mIconListToPageStack.remove(i);
+ break;
+ }
+ }
+ else // Tabbed
+ {
+ mTabControl->removePage(page);
+ }
+}
diff --git a/libopie2/qt3/opieui/ojanuswidget.h b/libopie2/qt3/opieui/ojanuswidget.h
new file mode 100644
index 0000000..b601b8c
--- a/dev/null
+++ b/libopie2/qt3/opieui/ojanuswidget.h
@@ -0,0 +1,551 @@
+/*
+                 This file is part of the Opie Project
+
+              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ Copyright (C) 1999-2000 Espen Sand (espen@kde.org)
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OJANUSWIDGET_H
+#define OJANUSWIDGET_H
+
+#include <qptrlist.h>
+#include <qpixmap.h>
+#include <qlistbox.h>
+#include <qmap.h>
+#include <qsplitter.h>
+#include <qstringlist.h>
+
+class QGrid;
+class QHBox;
+class QLabel;
+class QTabWidget;
+class QVBox;
+class QWidgetStack;
+class OSeparator;
+class QListView;
+class QListViewItem;
+
+/**
+ * Provides a number of ready to use layouts (faces). It is used
+ * as an internal widget in @ref KDialogBase, but can also used as a
+ * widget of its own.
+ *
+ * It provides TreeList, IconList, Tabbed, Plain and Swallow layouts.
+ *
+ * The TreeList face provides a list in the left area and pages in the
+ * right. The area are separated by a movable splitter. The style is somewhat
+ * similar to the layout in the Control Center. A page is raised by
+ * selecting the corresponding tree list item.
+ *
+ * The IconList face provides an icon list in the left area and pages in the
+ * right. For each entry the Icon is on top with the text below. The style
+ * is somewhat similar to the layout of the Eudora configuation dialog box.
+ * A page is raised by selecting the corresponding icon list item. The
+ * preferred icon size is 32x32 pixels.
+ *
+ * The Tabbed face is a common tabbed widget. The procedure for creating a
+ * page is similar for creating a TreeList. This has the advantage that if
+ * your widget contain too many pages it is trivial to convert it into a
+ * TreeList. Just change the face in the KJanusWidget constructor to
+ * KJanusWidget::TreeList and you have a tree list layout instead.
+ *
+ * The Plain face provides an empty widget (QFrame) where you can place your
+ * widgets. The KJanusWidget makes no assumptions regarding the contents so
+ * you are free to add whatever you want.
+ *
+ * The Swallow face is provided in order to simplify the usage of existing
+ * widgets and to allow changing the visible widget. You specify the widget
+ * to be displayed by @ref #setSwallowedWidget(). Your widget will be
+ * reparented inside the widget. You can specify a Null (0) widget. A empty
+ * space is then displayed.
+ *
+ * For all modes it is important that you specify the @ref QWidget::minimumSize()
+ * on the page, plain widget or the swallowed widget. If you use a QLayout
+ * on the page, plain widget or the swallowed widget this will be taken care
+ * of automatically. The size is used when the KJanusWidget determines its
+ * own minimum size. You get the minimum size by using the
+ * @ref #minimumSizeHint() or @ref #sizeHint() methods.
+ *
+ * Pages that have been added in TreeList, IconList or Tabbed mode can be
+ * removed by simply deleting the page.
+ *
+ * @short Easy to use widget with many layouts
+ * @author Espen Sand (espen@kde.org)
+ */
+class OJanusWidget : public QWidget
+{
+ Q_OBJECT
+
+ private:
+
+ class IconListBox : public QListBox
+ {
+ public:
+ IconListBox( QWidget *parent=0, const char *name=0, WFlags f=0 );
+ void updateMinimumHeight();
+ void updateWidth();
+ void invalidateHeight();
+ void invalidateWidth();
+ void setShowAll( bool showAll );
+
+ private:
+ bool mShowAll;
+ bool mHeightValid;
+ bool mWidthValid;
+ };
+
+ public:
+
+ enum Face
+ {
+ TreeList = 0,
+ Tabbed,
+ Plain,
+ Swallow,
+ IconList
+ };
+
+ public:
+
+ /**
+ * Constructor where you specify the face.
+ *
+ * @param parent Parent of the widget.
+ * @param name Widget name.
+ * @param int face The kind of dialog, Use TreeList, Tabbed, Plain or
+ * Swallow.
+ */
+ OJanusWidget( QWidget *parent=0, const char *name=0, int face=Plain );
+
+ /**
+ * Destructor.
+ */
+ ~OJanusWidget();
+
+ /**
+ * Raises the page which was added by @ref addPage().
+ *
+ * @param index The index of the page you want to raise.
+ */
+ virtual bool showPage( int index );
+
+ /**
+ * Returns the index of the page that are currently displayed.
+ *
+ * @return The index or -1 if the face is not Tabbed, TreeList or
+ * IconList.
+ */
+ virtual int activePageIndex() const;
+
+ /**
+ * Use this to verify
+ * that no memory allocation failed.
+ *
+ * @return true if the widget was properly created.
+ */
+ virtual bool isValid() const;
+
+ /**
+ * Returns the face type.
+ *
+ * @return The face type.
+ */
+ virtual int face() const;
+
+ /**
+ * Returns the minimum size that must be made available for the widget
+ * so that UIs can be displayed properly
+ *
+ * @return The minimum size.
+ */
+ virtual QSize minimumSizeHint() const;
+
+ /**
+ * Returns the recommended size for the widget in order to be displayed
+ * properly.
+ *
+ * @return The recommended size.
+ */
+ virtual QSize sizeHint() const;
+
+ /**
+ * Returns the empty widget that is available in Plain mode.
+ *
+ * @return The widget or 0 if the face in not Plain.
+ */
+ virtual QFrame *plainPage();
+
+ /**
+ * Add a new page when the class is used in TreeList, IconList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. In most cases you must create a layout
+ * manager and associate it with this widget as well.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param item String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed.
+ */
+ virtual QFrame *addPage(const QString &item,const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QFrame *addPage(const QStringList &items, const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a new page when the class is used in TreeList, IconList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. The returned widget is a @ref QVBox
+ * so it contains a QVBoxLayout layout that lines up the child widgets
+ * are vertically.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param item String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed. */
+ virtual QVBox *addVBoxPage( const QString &item,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addVBoxPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QVBox *addVBoxPage( const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a new page when the class is used in TreeList, IconList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. The returned widget is a @ref QHBox
+ * so it contains a QHBoxLayout layout that lines up the child widgets
+ * are horizontally.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param item String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed.
+ */
+ virtual QHBox *addHBoxPage( const QString &itemName,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addHBoxPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QHBox *addHBoxPage( const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a new page when the class is used in either TreeList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. The returned widget is a @ref QGrid
+ * so it contains a QGridLayout layout that places up the child widgets
+ * in a grid.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param n Specifies the number of columns if 'dir' is QGrid::Horizontal
+ * or the number of rows if 'dir' is QGrid::Vertical.
+ * @param dir Can be QGrid::Horizontal or QGrid::Vertical.
+ * @param item String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed.
+ */
+ virtual QGrid *addGridPage( int n, Orientation dir,
+ const QString &itemName,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addGridPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QGrid *addGridPage( int n, Orientation dir,
+ const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * @short Removes a page created with @ref addPage, @ref addVBoxPage,
+ * @ref addHBoxPage or @ref addGridPage. If the page has already
+ * been deleted or has already been removed, nothing happens. The widget
+ * itself is not deleted.
+ *
+ * @param page The widget returned by @ref addPage , @ref addVBoxPage ,
+ * @ref addHBoxPage or @ref addGridPage .
+ */
+ void removePage( QWidget *page );
+
+
+ /**
+ * Returns the index of a page created with @ref addPage ,
+ * @ref addVBoxPage , @ref addHBoxPage or @ref addGridPage .
+ * You can can compare this index with the value returned from
+ * @ref activePageIndex if you need to do some page specific actions
+ * in your code.
+ *
+ * The returned index will never change so you can safely use this
+ * function once and save the value.
+ *
+ * @param widget The widget returned by @ref addPage , @ref addVBoxPage ,
+ * @ref addHBoxPage or @ref addGridPage .
+ *
+ * @return The index or -1 if the face is not Tabbed, TreeList or
+ * IconList
+ */
+ virtual int pageIndex( QWidget *widget ) const;
+
+ /**
+ * Defines the widget to be swallowed.
+ *
+ * This method can be used several
+ * times. Only the latest defined widget will be shown.
+ *
+ * @param widget The widget to be swallowed. If 0, then an empty rectangle
+ * is displayed.
+ */
+ virtual bool setSwallowedWidget( QWidget *widget );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * Defines how the tree list is resized when the widget is resized
+ * horizontally. By default the tree list keeps its width when the
+ * widget becomes wider.
+ *
+ * @param state The resize mode. If false (default) the TreeList keeps
+ * its current width when the widget becomes wider.
+ */
+ virtual void setTreeListAutoResize( bool state );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the widgets whether the icons given in the @ref addPage,
+ * @ref addVBoxPage, @ref addHBoxPage, or @ref addGridPage methods should
+ * be shown in the TreeList.
+ *
+ * Note: This method must be called before calling any of the methods
+ * which add icons to the page.
+ *
+ * @param state If true the icons are shown.
+ **/
+ virtual void setShowIconsInTreeList(bool state);
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the widgets whether the root should be decorated.
+ * For details see @ref QListView::setRootIsDecorated
+ *
+ * @param state Root will be decorated if true.
+ **/
+ virtual void setRootIsDecorated( bool state );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the TreeList to unfold the whole tree so that all entries
+ * are visible.
+ *
+ * If the list is empty when you call this method newly created entries
+ * will not automatically be opened. If the @p persist flag is set opened
+ * entries cannot be closed again, though.
+ *
+ * @param persist If true the tree always stays unfolded.
+ * @since 3.2
+ */
+ /*virtual*/ void unfoldTreeList( bool persist = false ); //### KDE4 BIC add virtual
+
+ /**
+ * This function has only effect in IconList mode.
+ *
+ * Defines how the icon list widget is displayed. By default it is
+ * the widgets in the pages that decide the minimum height
+ * of the toplevel widget. A vertical scrollbar can be used in
+ * the icon list area.
+ *
+ * @param state The visibility mode. If true, the minimum height is
+ * adjusted so that every icon in the list is visible at the
+ * same time. The vertical scrollbar will never be visible.
+ */
+ virtual void setIconListAllVisible( bool state );
+
+ /**
+ * Sets the icon used in TreeList Mode for the given path.
+ * @param path The path for which this icon should be shown.
+ * @param pixmap The icon used.
+ **/
+ virtual void setFolderIcon(const QStringList &path, const QPixmap &pixmap);
+
+ signals:
+ void aboutToShowPage(QWidget *page);
+
+ public slots:
+ /**
+ * Give the keyboard input focus to the widget.
+ */
+ virtual void setFocus();
+
+ protected:
+ /**
+ * Reimplemented to handle the splitter width when the the face
+ * is TreeList
+ */
+ virtual void showEvent( QShowEvent * );
+
+ /**
+ * This function is used internally when in IconList mode. If you
+ * reimplement this class a make your own event filter, make sure to
+ * call this function from your filter.
+ *
+ * @param o Object that has received an event.
+ * @param e The event.
+ */
+ virtual bool eventFilter( QObject *o, QEvent *e );
+
+ private slots:
+ bool slotShowPage();
+ void slotFontChanged();
+ void slotItemClicked(QListViewItem *it);
+ void pageGone(QObject *obj); // signal from the added page's "destroyed" signal
+ void slotReopen(QListViewItem *item);
+
+ protected:
+ bool showPage( QWidget *w );
+ void addPageWidget( QFrame *page, const QStringList &items,
+ const QString &header, const QPixmap &pixmap );
+ void InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page);
+ QWidget *FindParent();
+
+ private:
+ bool mValid;
+
+ QPtrList<QWidget> *mPageList;
+ QStringList *mTitleList;
+
+ int mFace;
+ QListView *mTreeList;
+ IconListBox *mIconList;
+ QWidgetStack *mPageStack;
+ QLabel *mTitleLabel;
+ QTabWidget *mTabControl;
+ QFrame *mPlainPage;
+ QWidget *mSwallowPage;
+ QWidget *mActivePageWidget;
+ OSeparator *mTitleSep;
+ QSplitter::ResizeMode mTreeListResizeMode;
+ bool mShowIconsInTreeList;
+ QMap<QListViewItem *, QWidget *> mTreeListToPageStack;
+ QMap<QListBoxItem *, QWidget *> mIconListToPageStack;
+ QMap<QString, QPixmap> mFolderIconMap;
+ QMap<QString, QStringList> mChildrenNames;
+ QMap<QString, QWidget *> mChildPages;
+
+ public:
+ class IconListItem;
+
+ private:
+ class OJanusWidgetPrivate;
+ OJanusWidgetPrivate *d;
+};
+
+#endif
diff --git a/libopie2/qt3/opieui/olineedit.cpp b/libopie2/qt3/opieui/olineedit.cpp
new file mode 100644
index 0000000..9cb0cff
--- a/dev/null
+++ b/libopie2/qt3/opieui/olineedit.cpp
@@ -0,0 +1,729 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>, Dawit Alemayehu <adawit@kde.org>
+ Opie Project Copyright (C) 1999 Preston Brown <pbrown@kde.org>, Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
+ Copyright (C) 1997 Sven Radej (sven.radej@iname.com)
+ =.
+ .=l. Originally part of the KDE Project
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* QT */
+
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qtimer.h>
+#include <qpopupmenu.h>
+
+/* OPIE */
+
+#include <opie2/ocompletionbox.h>
+#include <opie2/olineedit.h>
+#include <opie2/oglobalsettings.h>
+
+typedef QString KURL; //FIXME: Revise for Opie
+
+/*======================================================================================
+ * OLineEditPrivate
+ *======================================================================================*/
+
+class OLineEdit::OLineEditPrivate
+{
+public:
+ OLineEditPrivate()
+ {
+ grabReturnKeyEvents = false;
+ handleURLDrops = true;
+ completionBox = 0L;
+ }
+ ~OLineEditPrivate()
+ {
+ delete completionBox;
+ }
+
+ bool grabReturnKeyEvents;
+ bool handleURLDrops;
+ OCompletionBox *completionBox;
+};
+
+
+/*======================================================================================
+ * OLineEdit
+ *======================================================================================*/
+
+OLineEdit::OLineEdit( const QString &string, QWidget *parent, const char *name )
+ : QLineEdit( string, parent, name )
+{
+ init();
+}
+
+OLineEdit::OLineEdit( QWidget *parent, const char *name )
+ : QLineEdit( parent, name )
+{
+ init();
+}
+
+OLineEdit::~OLineEdit ()
+{
+ delete d;
+}
+
+void OLineEdit::init()
+{
+ d = new OLineEditPrivate;
+ possibleTripleClick = false;
+ // Enable the context menu by default.
+ setContextMenuEnabled( true );
+ //OCursor::setAutoHideCursor( this, true, true );
+ installEventFilter( this );
+}
+
+void OLineEdit::setCompletionMode( OGlobalSettings::Completion mode )
+{
+ OGlobalSettings::Completion oldMode = completionMode();
+ if ( oldMode != mode && oldMode == OGlobalSettings::CompletionPopup &&
+ d->completionBox && d->completionBox->isVisible() )
+ d->completionBox->hide();
+
+ // If the widgets echo mode is not Normal, no completion
+ // feature will be enabled even if one is requested.
+ if ( echoMode() != QLineEdit::Normal )
+ mode = OGlobalSettings::CompletionNone; // Override the request.
+
+ OCompletionBase::setCompletionMode( mode );
+}
+
+void OLineEdit::setCompletedText( const QString& t, bool marked )
+{
+ QString txt = text();
+ if ( t != txt )
+ {
+ int curpos = marked ? txt.length() : t.length();
+ validateAndSet( t, curpos, curpos, t.length() );
+ }
+}
+
+void OLineEdit::setCompletedText( const QString& text )
+{
+ OGlobalSettings::Completion mode = completionMode();
+ bool marked = ( mode == OGlobalSettings::CompletionAuto ||
+ mode == OGlobalSettings::CompletionMan ||
+ mode == OGlobalSettings::CompletionPopup );
+ setCompletedText( text, marked );
+}
+
+void OLineEdit::rotateText( OCompletionBase::KeyBindingType type )
+{
+ OCompletion* comp = compObj();
+ if ( comp &&
+ (type == OCompletionBase::PrevCompletionMatch ||
+ type == OCompletionBase::NextCompletionMatch ) )
+ {
+ QString input = (type == OCompletionBase::PrevCompletionMatch) ? comp->previousMatch() : comp->nextMatch();
+ // Skip rotation if previous/next match is null or the same text
+ if ( input.isNull() || input == displayText() )
+ return;
+ #if QT_VERSION > 290
+ setCompletedText( input, hasSelectedText() );
+ #else
+ setCompletedText( input, hasMarkedText() );
+ #endif
+ }
+}
+
+void OLineEdit::makeCompletion( const QString& text )
+{
+ OCompletion *comp = compObj();
+ if ( !comp )
+ return; // No completion object...
+
+ QString match = comp->makeCompletion( text );
+ OGlobalSettings::Completion mode = completionMode();
+ if ( mode == OGlobalSettings::CompletionPopup )
+ {
+ if ( match.isNull() )
+ {
+ if ( d->completionBox ) {
+ d->completionBox->hide();
+ d->completionBox->clear();
+ }
+ }
+ else
+ setCompletedItems( comp->allMatches() );
+ }
+ else
+ {
+ // all other completion modes
+ // If no match or the same match, simply return without completing.
+ if ( match.isNull() || match == text )
+ return;
+
+ setCompletedText( match );
+ }
+}
+
+void OLineEdit::setReadOnly(bool readOnly)
+{
+ QPalette p = palette();
+ if (readOnly)
+ {
+ QColor color = p.color(QPalette::Disabled, QColorGroup::Background);
+ p.setColor(QColorGroup::Base, color);
+ p.setColor(QColorGroup::Background, color);
+ }
+ else
+ {
+ QColor color = p.color(QPalette::Normal, QColorGroup::Base);
+ p.setColor(QColorGroup::Base, color);
+ p.setColor(QColorGroup::Background, color);
+ }
+ setPalette(p);
+
+ QLineEdit::setReadOnly (readOnly);
+}
+
+void OLineEdit::keyPressEvent( QKeyEvent *e )
+{
+ qDebug( "OLineEdit::keyPressEvent()" );
+
+ /*
+
+ KKey key( e );
+
+ if ( KStdAccel::copy().contains( key ) ) {
+ copy();
+ return;
+ }
+ else if ( KStdAccel::paste().contains( key ) ) {
+ paste();
+ return;
+ }
+ else if ( KStdAccel::cut().contains( key ) ) {
+ cut();
+ return;
+ }
+ else if ( KStdAccel::undo().contains( key ) ) {
+ undo();
+ return;
+ }
+ else if ( KStdAccel::redo().contains( key ) ) {
+ redo();
+ return;
+ }
+ else if ( KStdAccel::deleteWordBack().contains( key ) )
+ {
+ cursorWordBackward(TRUE);
+ if ( hasSelectedText() )
+ del();
+
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::deleteWordForward().contains( key ) )
+ {
+ // Workaround for QT bug where
+ cursorWordForward(TRUE);
+ if ( hasSelectedText() )
+ del();
+
+ e->accept();
+ return;
+ }
+ */
+
+ // Filter key-events if EchoMode is normal &
+ // completion mode is not set to CompletionNone
+ if ( echoMode() == QLineEdit::Normal &&
+ completionMode() != OGlobalSettings::CompletionNone )
+ {
+ KeyBindingMap keys = getKeyBindings();
+ OGlobalSettings::Completion mode = completionMode();
+ bool noModifier = (e->state() == NoButton || e->state()== ShiftButton);
+
+ if ( (mode == OGlobalSettings::CompletionAuto ||
+ mode == OGlobalSettings::CompletionMan) && noModifier )
+ {
+ QString keycode = e->text();
+ if ( !keycode.isNull() && keycode.unicode()->isPrint() )
+ {
+ QLineEdit::keyPressEvent ( e );
+ QString txt = text();
+ int len = txt.length();
+ #if QT_VERSION > 290
+ if ( !hasSelectedText() && len && cursorPosition() == len )
+ #else
+ if ( !hasMarkedText() && len && cursorPosition() == len )
+ #endif
+ {
+ if ( emitSignals() )
+ emit completion( txt );
+ if ( handleSignals() )
+ makeCompletion( txt );
+ e->accept();
+ }
+ return;
+ }
+ }
+
+ else if ( mode == OGlobalSettings::CompletionPopup && noModifier )
+ {
+ qDebug( "OLineEdit::keyPressEvent() - global settings = CompletionPopup & noModifier" );
+
+ QString old_txt = text();
+ QLineEdit::keyPressEvent ( e );
+ QString txt = text();
+ int len = txt.length();
+ QString keycode = e->text();
+
+
+ if ( txt != old_txt && len && cursorPosition() == len &&
+ ( (!keycode.isNull() && keycode.unicode()->isPrint()) ||
+ e->key() == Key_Backspace ) )
+ {
+ if ( emitSignals() )
+ emit completion( txt ); // emit when requested...
+ if ( handleSignals() )
+ makeCompletion( txt ); // handle when requested...
+ e->accept();
+ }
+ else if (!len && d->completionBox && d->completionBox->isVisible())
+ d->completionBox->hide();
+
+ return;
+ }
+
+ /*else if ( mode == OGlobalSettings::CompletionShell )
+ {
+ // Handles completion.
+ KShortcut cut;
+ if ( keys[TextCompletion].isNull() )
+ cut = KStdAccel::shortcut(KStdAccel::TextCompletion);
+ else
+ cut = keys[TextCompletion];
+
+ if ( cut.contains( key ) )
+ {
+ // Emit completion if the completion mode is CompletionShell
+ // and the cursor is at the end of the string.
+ QString txt = text();
+ int len = txt.length();
+ if ( cursorPosition() == len && len != 0 )
+ {
+ if ( emitSignals() )
+ emit completion( txt );
+ if ( handleSignals() )
+ makeCompletion( txt );
+ return;
+ }
+ }
+ else if ( d->completionBox )
+ d->completionBox->hide();
+ }
+
+ // handle rotation
+ if ( mode != OGlobalSettings::CompletionNone )
+ {
+ // Handles previous match
+ KShortcut cut;
+ if ( keys[PrevCompletionMatch].isNull() )
+ cut = KStdAccel::shortcut(KStdAccel::PrevCompletion);
+ else
+ cut = keys[PrevCompletionMatch];
+
+ if ( cut.contains( key ) )
+ {
+ if ( emitSignals() )
+ emit textRotation( OCompletionBase::PrevCompletionMatch );
+ if ( handleSignals() )
+ rotateText( OCompletionBase::PrevCompletionMatch );
+ return;
+ }
+
+ // Handles next match
+ if ( keys[NextCompletionMatch].isNull() )
+ cut = KStdAccel::key(KStdAccel::NextCompletion);
+ else
+ cut = keys[NextCompletionMatch];
+
+ if ( cut.contains( key ) )
+ {
+ if ( emitSignals() )
+ emit textRotation( OCompletionBase::NextCompletionMatch );
+ if ( handleSignals() )
+ rotateText( OCompletionBase::NextCompletionMatch );
+ return;
+ }
+ }
+
+ // substring completion
+ if ( compObj() )
+ {
+ KShortcut cut;
+ if ( keys[SubstringCompletion].isNull() )
+ cut = KStdAccel::shortcut(KStdAccel::SubstringCompletion);
+ else
+ cut = keys[SubstringCompletion];
+
+ if ( cut.contains( key ) )
+ {
+ if ( emitSignals() )
+ emit substringCompletion( text() );
+ if ( handleSignals() )
+ {
+ setCompletedItems( compObj()->substringCompletion(text()));
+ e->accept();
+ }
+ return;
+ }
+ } */
+ }
+
+ // Let QLineEdit handle any other keys events.
+ QLineEdit::keyPressEvent ( e );
+}
+
+void OLineEdit::mouseDoubleClickEvent( QMouseEvent* e )
+{
+ if ( e->button() == Qt::LeftButton )
+ {
+ possibleTripleClick=true;
+ QTimer::singleShot( QApplication::doubleClickInterval(),this,
+ SLOT(tripleClickTimeout()) );
+ }
+ QLineEdit::mouseDoubleClickEvent( e );
+}
+
+void OLineEdit::mousePressEvent( QMouseEvent* e )
+{
+ if ( possibleTripleClick && e->button() == Qt::LeftButton )
+ {
+ selectAll();
+ return;
+ }
+ QLineEdit::mousePressEvent( e );
+}
+
+void OLineEdit::tripleClickTimeout()
+{
+ possibleTripleClick=false;
+}
+
+QPopupMenu *OLineEdit::createPopupMenu()
+{
+ // Return if popup menu is not enabled !!
+ if ( !m_bEnableMenu )
+ return 0;
+
+ #if QT_VERSION > 290
+ QPopupMenu *popup = QLineEdit::createPopupMenu();
+ #else
+ QPopupMenu *popup = new QPopupMenu();
+ #warning OLineEdit is not fully functional on Qt2
+ #endif
+
+ // completion object is present.
+ if ( compObj() )
+ {
+ QPopupMenu *subMenu = new QPopupMenu( popup );
+ connect( subMenu, SIGNAL( activated( int ) ),
+ this, SLOT( completionMenuActivated( int ) ) );
+
+ popup->insertSeparator();
+ //popup->insertItem( SmallIconSet("completion"), i18n("Text Completion"),
+ // subMenu );
+
+ popup->insertItem( tr("Text Completion"), subMenu );
+
+ subMenu->insertItem( tr("None"), NoCompletion );
+ subMenu->insertItem( tr("Manual"), ShellCompletion );
+ subMenu->insertItem( tr("Automatic"), AutoCompletion );
+ subMenu->insertItem( tr("Dropdown List"), PopupCompletion );
+ subMenu->insertItem( tr("Short Automatic"), SemiAutoCompletion );
+
+ //subMenu->setAccel( KStdAccel::completion(), ShellCompletion );
+ subMenu->setAccel( Key_Tab, ShellCompletion );
+
+ OGlobalSettings::Completion mode = completionMode();
+ subMenu->setItemChecked( NoCompletion,
+ mode == OGlobalSettings::CompletionNone );
+ subMenu->setItemChecked( ShellCompletion,
+ mode == OGlobalSettings::CompletionShell );
+ subMenu->setItemChecked( PopupCompletion,
+ mode == OGlobalSettings::CompletionPopup );
+ subMenu->setItemChecked( AutoCompletion,
+ mode == OGlobalSettings::CompletionAuto );
+ subMenu->setItemChecked( SemiAutoCompletion,
+ mode == OGlobalSettings::CompletionMan );
+ if ( mode != OGlobalSettings::completionMode() )
+ {
+ subMenu->insertSeparator();
+ subMenu->insertItem( tr("Default"), Default );
+ }
+ }
+ // ### do we really need this? Yes, Please do not remove! This
+ // allows applications to extend the popup menu without having to
+ // inherit from this class! (DA)
+ emit aboutToShowContextMenu( popup );
+
+ return popup;
+}
+
+void OLineEdit::completionMenuActivated( int id )
+{
+ OGlobalSettings::Completion oldMode = completionMode();
+
+ switch ( id )
+ {
+ case Default:
+ setCompletionMode( OGlobalSettings::completionMode() ); break;
+ case NoCompletion:
+ setCompletionMode( OGlobalSettings::CompletionNone ); break;
+ case AutoCompletion:
+ setCompletionMode( OGlobalSettings::CompletionAuto ); break;
+ case SemiAutoCompletion:
+ setCompletionMode( OGlobalSettings::CompletionMan ); break;
+ case ShellCompletion:
+ setCompletionMode( OGlobalSettings::CompletionShell ); break;
+ case PopupCompletion:
+ setCompletionMode( OGlobalSettings::CompletionPopup ); break;
+ default: return;
+ }
+
+ if ( oldMode != completionMode() )
+ {
+ if ( oldMode == OGlobalSettings::CompletionPopup &&
+ d->completionBox && d->completionBox->isVisible() )
+ d->completionBox->hide();
+ emit completionModeChanged( completionMode() );
+ }
+}
+
+/*void OLineEdit::dropEvent(QDropEvent *e)
+{
+ KURL::List urlList;
+ if( d->handleURLDrops && KURLDrag::decode( e, urlList ) )
+ {
+ QString dropText = text();
+ KURL::List::ConstIterator it;
+ for( it = urlList.begin() ; it != urlList.end() ; ++it )
+ {
+ if(!dropText.isEmpty())
+ dropText+=' ';
+
+ dropText += (*it).prettyURL();
+ }
+
+ validateAndSet( dropText, dropText.length(), 0, 0);
+
+ e->accept();
+ }
+ else
+ QLineEdit::dropEvent(e);
+}*/
+
+bool OLineEdit::eventFilter( QObject* o, QEvent* ev )
+{
+ if( o == this )
+ {
+ //OCursor::autoHideEventFilter( this, ev );
+ if ( ev->type() == QEvent::AccelOverride )
+ {
+ QKeyEvent *e = static_cast<QKeyEvent *>( ev );
+ // if (overrideAccel (e))
+ // {
+ // e->accept();
+ // return true;
+ // }
+ }
+ else if( ev->type() == QEvent::KeyPress )
+ {
+ QKeyEvent *e = static_cast<QKeyEvent *>( ev );
+
+ if( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
+ {
+ bool trap = d->completionBox && d->completionBox->isVisible();
+
+ // Qt will emit returnPressed() itself if we return false
+ if ( d->grabReturnKeyEvents || trap )
+ emit QLineEdit::returnPressed();
+
+ emit returnPressed( displayText() );
+
+ if ( trap )
+ d->completionBox->hide();
+
+ // Eat the event if the user asked for it, or if a completionbox was visible
+ return d->grabReturnKeyEvents || trap;
+ }
+ }
+ }
+ return QLineEdit::eventFilter( o, ev );
+}
+
+
+void OLineEdit::setURLDropsEnabled(bool enable)
+{
+ d->handleURLDrops=enable;
+}
+
+bool OLineEdit::isURLDropsEnabled() const
+{
+ return d->handleURLDrops;
+}
+
+void OLineEdit::setTrapReturnKey( bool grab )
+{
+ d->grabReturnKeyEvents = grab;
+}
+
+bool OLineEdit::trapReturnKey() const
+{
+ return d->grabReturnKeyEvents;
+}
+
+/*void OLineEdit::setURL( const KURL& url )
+{
+ QLineEdit::setText( url.prettyURL() );
+}*/
+
+void OLineEdit::makeCompletionBox()
+{
+ if ( d->completionBox )
+ return;
+
+ d->completionBox = new OCompletionBox( this, "completion box" );
+ if ( handleSignals() )
+ {
+ connect( d->completionBox, SIGNAL(highlighted( const QString& )),
+ SLOT(setText( const QString& )) );
+ connect( d->completionBox, SIGNAL(userCancelled( const QString& )),
+ SLOT(setText( const QString& )) );
+
+ // Nice lil' hacklet ;) KComboBox doesn't know when the completionbox
+ // is created (childEvent() is even more hacky, IMHO), so we simply
+ // forward the completionbox' activated signal from here.
+ if ( parentWidget() && parentWidget()->inherits("KComboBox") )
+ connect( d->completionBox, SIGNAL( activated( const QString& )),
+ parentWidget(), SIGNAL( activated( const QString & )));
+ }
+}
+
+/*bool OLineEdit::overrideAccel (const QKeyEvent* e)
+{
+ KShortcut scKey;
+
+ KKey key( e );
+ KeyBindingMap keys = getKeyBindings();
+
+ if (keys[TextCompletion].isNull())
+ scKey = KStdAccel::shortcut(KStdAccel::TextCompletion);
+ else
+ scKey = keys[TextCompletion];
+
+ if (scKey.contains( key ))
+ return true;
+
+ if (keys[NextCompletionMatch].isNull())
+ scKey = KStdAccel::shortcut(KStdAccel::NextCompletion);
+ else
+ scKey = keys[NextCompletionMatch];
+
+ if (scKey.contains( key ))
+ return true;
+
+ if (keys[PrevCompletionMatch].isNull())
+ scKey = KStdAccel::shortcut(KStdAccel::PrevCompletion);
+ else
+ scKey = keys[PrevCompletionMatch];
+
+ if (scKey.contains( key ))
+ return true;
+
+ if (KStdAccel::deleteWordBack().contains( key ))
+ return true;
+ if (KStdAccel::deleteWordForward().contains( key ))
+ return true;
+
+ if (d->completionBox && d->completionBox->isVisible ())
+ if (e->key () == Key_Backtab)
+ return true;
+
+ return false;
+}*/
+
+void OLineEdit::setCompletedItems( const QStringList& items )
+{
+ QString txt = text();
+ if ( !items.isEmpty() &&
+ !(items.count() == 1 && txt == items.first()) )
+ {
+ if ( !d->completionBox )
+ makeCompletionBox();
+
+ if ( !txt.isEmpty() )
+ d->completionBox->setCancelledText( txt );
+ d->completionBox->setItems( items );
+ d->completionBox->popup();
+ }
+ else
+ {
+ if ( d->completionBox && d->completionBox->isVisible() )
+ d->completionBox->hide();
+ }
+}
+
+OCompletionBox * OLineEdit::completionBox( bool create )
+{
+ if ( create )
+ makeCompletionBox();
+
+ return d->completionBox;
+}
+
+void OLineEdit::setCompletionObject( OCompletion* comp, bool hsig )
+{
+ OCompletion *oldComp = compObj();
+ if ( oldComp && handleSignals() )
+ disconnect( oldComp, SIGNAL( matches( const QStringList& )),
+ this, SLOT( setCompletedItems( const QStringList& )));
+
+ if ( comp && hsig )
+ connect( comp, SIGNAL( matches( const QStringList& )),
+ this, SLOT( setCompletedItems( const QStringList& )));
+
+ OCompletionBase::setCompletionObject( comp, hsig );
+}
+
+// QWidget::create() turns off mouse-Tracking which would break auto-hiding
+void OLineEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
+{
+ QLineEdit::create( id, initializeWindow, destroyOldWindow );
+ //OCursor::setAutoHideCursor( this, true, true );
+}
+
+void OLineEdit::clear()
+{
+ setText( QString::null );
+}
diff --git a/libopie2/qt3/opieui/olineedit.h b/libopie2/qt3/opieui/olineedit.h
new file mode 100644
index 0000000..ecfca27
--- a/dev/null
+++ b/libopie2/qt3/opieui/olineedit.h
@@ -0,0 +1,498 @@
+/*
+ This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ is part of the Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>, Dawit Alemayehu <adawit@kde.org>
+ Opie Project Copyright (C) 1999 Preston Brown <pbrown@kde.org>, Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
+ Copyright (C) 1997 Sven Radej (sven.radej@iname.com)
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OLINEEDIT_H
+#define OLINEEDIT_H
+
+/* QT */
+
+#include <qlineedit.h>
+
+/* OPIE */
+
+#include <opie2/ocompletion.h>
+#include <opie2/ocompletionbase.h>
+
+class QPopupMenu;
+
+class OCompletionBox;
+typedef QString KURL; //class KURL;
+
+/**
+ * An enhanced QLineEdit widget for inputting text.
+ *
+ * @sect Detail
+ *
+ * This widget inherits from @ref QLineEdit and implements the following
+ * additional functionalities: q completion object that provides both
+ * automatic and manual text completion as well as multiple match iteration
+ * features, configurable key-bindings to activate these features and a
+ * popup-menu item that can be used to allow the user to set text completion
+ * modes on the fly based on their preference.
+ *
+ * To support these new features OLineEdit also emits a few more
+ * additional signals. These are: @ref completion( const QString& ),
+ * textRotation( KeyBindingType ), and @ref returnPressed( const QString& ).
+ * The completion signal can be connected to a slot that will assist the
+ * user in filling out the remaining text. The text rotation signal is
+ * intended to be used to iterate through the list of all possible matches
+ * whenever there is more than one match for the entered text. The
+ * @p returnPressed( const QString& ) signals are the same as QLineEdit's
+ * except it provides the current text in the widget as its argument whenever
+ * appropriate.
+ *
+ * This widget by default creates a completion object when you invoke
+ * the @ref completionObject( bool ) member function for the first time or
+ * use @ref setCompletionObject( OCompletion*, bool ) to assign your own
+ * completion object. Additionally, to make this widget more functional,
+ * OLineEdit will by default handle the text rotation and completion
+ * events internally when a completion object is created through either one
+ * of the methods mentioned above. If you do not need this functionality,
+ * simply use @ref OCompletionBase::setHandleSignals( bool ) or set the
+ * boolean parameter in the above functions to FALSE.
+ *
+ * The default key-bindings for completion and rotation is determined
+ * from the global settings in @ref OStdAccel. These values, however,
+ * can be overriden locally by invoking @ref OCompletionBase::setKeyBinding().
+ * The values can easily be reverted back to the default setting, by simply
+ * calling @ref useGlobalSettings(). An alternate method would be to default
+ * individual key-bindings by usning @ref setKeyBinding() with the default
+ * second argument.
+ *
+ * NOTE that if the @p EchoMode for this widget is set to something other
+ * than @p QLineEdit::Normal, the completion mode will always be defaulted
+ * to @ref PGlobalSettings::CompletionNone. This is done purposefully to guard
+ * against protected entries such as passwords being cached in @ref OCompletion's
+ * list. Hence, if the @p EchoMode is not @ref QLineEdit::Normal, the completion
+ * mode is automatically disabled.
+ *
+ * @sect Useage
+ *
+ * To enable the basic completion feature :
+ *
+ * <pre>
+ * OLineEdit *edit = new OLineEdit( this, "mywidget" );
+ * OCompletion *comp = edit->completionObject();
+ * // Fill the completion object with a list of possible matches
+ * QStringList list;
+ * list << "mickeyl@handhelds.org" << "mickey@tm.informatik.uni-frankfurt.de>" << "mickey@Vanille.de";
+ * comp->setItems( list );
+ * // Connect to the return pressed signal (optional)
+ * connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
+ * </pre>
+ *
+ * To use a customized completion objects or your
+ * own completion object :
+ *
+ * <pre>
+ * OLineEdit *edit = new OLineEdit( this,"mywidget" );
+ * KURLCompletion *comp = new KURLCompletion();
+ * edit->setCompletionObject( comp );
+ * // Connect to the return pressed signal - optional
+ * connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
+ * </pre>
+ *
+ * Note that you have to either delete the allocated completion object
+ * when you don't need it anymore, or call
+ * setAutoDeleteCompletionObject( true );
+ *
+ * @sect Miscellaneous function calls :
+ *
+ * <pre>
+ * // Tell the widget not to handle completion and
+ * // iteration internally.
+ * edit->setHandleSignals( false );
+ * // Set your own completion key for manual completions.
+ * edit->setKeyBinding( OCompletionBase::TextCompletion, Qt::End );
+ * // Hide the context (popup) menu
+ * edit->setContextMenuEnabled( false );
+ * // Temporarly disable signal emitions
+ * // (both completion & iteration signals)
+ * edit->disableSignals();
+ * // Default the key-bindings to system settings.
+ * edit->useGlobalKeyBindings();
+ * </pre>
+ *
+ * @short An enhanced single line input widget.
+ * @author Dawit Alemayehu <adawit@kde.org>
+ * @author Opie adaption by Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ */
+
+class OLineEdit : public QLineEdit, public OCompletionBase
+{
+ friend class OComboBox;
+
+ Q_OBJECT
+ Q_PROPERTY( bool contextMenuEnabled READ isContextMenuEnabled WRITE setContextMenuEnabled )
+ Q_PROPERTY( bool urlDropsEnabled READ isURLDropsEnabled WRITE setURLDropsEnabled )
+
+public:
+
+ /**
+ * Constructs a OLineEdit object with a default text, a parent,
+ * and a name.
+ *
+ * @param string Text to be shown in the edit widget.
+ * @param parent The parent object of this widget.
+ * @param name the name of this widget
+ */
+ OLineEdit( const QString &string, QWidget *parent, const char *name = 0 );
+
+ /**
+ * Constructs a OLineEdit object with a parent and a name.
+ *
+ * @param string Text to be shown in the edit widget.
+ * @param parent The parent object of this widget.
+ * @param name The name of this widget.
+ */
+ OLineEdit ( QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Destructor.
+ */
+ virtual ~OLineEdit ();
+
+ /**
+ * Sets @p url into the lineedit. It uses @ref KURL::prettyURL() so
+ * that the url is properly decoded for displaying.
+ */
+ void setURL( const KURL& url );
+
+ /**
+ * Puts the text cursor at the end of the string.
+ *
+ * This method is deprecated. Use @ref QLineEdit::end()
+ * instead.
+ *
+ * @deprecated
+ * @ref QLineEdit::end()
+ */
+ void cursorAtEnd() { end( false ); }
+
+ /**
+ * Re-implemented from @ref OCompletionBase for internal reasons.
+ *
+ * This function is re-implemented in order to make sure that
+ * the EchoMode is acceptable before we set the completion mode.
+ *
+ * See @ref OCompletionBase::setCompletionMode
+ */
+ virtual void setCompletionMode( OGlobalSettings::Completion mode );
+
+ /**
+ * Enables/disables the popup (context) menu.
+ *
+ * Note that when this function is invoked with its argument
+ * set to @p true, then both the context menu and the completion
+ * menu item are enabled. If you do not want to the completion
+ * item to be visible simply invoke @ref hideModechanger() right
+ * after calling this method. Also by default, the context
+ * menu is automatically created if this widget is editable. Thus
+ * you need to call this function with the argument set to false
+ * if you do not want this behaviour.
+ *
+ * @param showMenu If @p true, show the context menu.
+ */
+ virtual void setContextMenuEnabled( bool showMenu ) { m_bEnableMenu = showMenu; }
+
+ /**
+ * Returns @p true when the context menu is enabled.
+ */
+ bool isContextMenuEnabled() const { return m_bEnableMenu; }
+
+ /**
+ * Enables/Disables handling of URL drops. If enabled and the user
+ * drops an URL, the decoded URL will be inserted. Otherwise the default
+ * behaviour of QLineEdit is used, which inserts the encoded URL.
+ *
+ * @param enable If @p true, insert decoded URLs
+ */
+ void setURLDropsEnabled( bool enable );
+
+ /**
+ * Returns @p true when decoded URL drops are enabled
+ */
+ bool isURLDropsEnabled() const;
+
+ /**
+ * By default, OLineEdit recognizes @p Key_Return and @p Key_Enter and emits
+ * the @ref returnPressed() signals, but it also lets the event pass,
+ * for example causing a dialog's default-button to be called.
+ *
+ * Call this method with @p trap = @p true to make @p OLineEdit stop these
+ * events. The signals will still be emitted of course.
+ *
+ * @see trapReturnKey()
+ */
+ void setTrapReturnKey( bool trap );
+
+ /**
+ * @returns @p true if keyevents of @p Key_Return or
+ * @p Key_Enter will be stopped or if they will be propagated.
+ *
+ * @see setTrapReturnKey ()
+ */
+ bool trapReturnKey() const;
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * @reimplemented
+ */
+ virtual bool eventFilter( QObject *, QEvent * );
+
+ /**
+ * @returns the completion-box, that is used in completion mode
+ * @ref KGlobalSettings::CompletionPopup.
+ * This method will create a completion-box if none is there, yet.
+ *
+ * @param create Set this to false if you don't want the box to be created
+ * i.e. to test if it is available.
+ */
+ OCompletionBox * completionBox( bool create = true );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void setCompletionObject( OCompletion *, bool hsig = true );
+
+
+signals:
+
+ /**
+ * Emitted when the user presses the return key.
+ *
+ * The argument is the current text. Note that this
+ * signal is @em not emitted if the widget's @p EchoMode is set to
+ * @ref QLineEdit::EchoMode.
+ */
+ void returnPressed( const QString& );
+
+ /**
+ * Emitted when the completion key is pressed.
+ *
+ * Please note that this signal is @em not emitted if the
+ * completion mode is set to @p CompletionNone or @p EchoMode is
+ * @em normal.
+ */
+ void completion( const QString& );
+
+ /**
+ * Emitted when the shortcut for substring completion is pressed.
+ */
+ void substringCompletion( const QString& );
+
+ /**
+ * Emitted when the text rotation key-bindings are pressed.
+ *
+ * The argument indicates which key-binding was pressed.
+ * In OLineEdit's case this can be either one of two values:
+ * @ref PrevCompletionMatch or @ref NextCompletionMatch. See
+ * @ref OCompletionBase::setKeyBinding for details.
+ *
+ * Note that this signal is @em not emitted if the completion
+ * mode is set to @p KGlobalSettings::CompletionNone or @p echoMode() is @em not normal.
+ */
+ void textRotation( OCompletionBase::KeyBindingType );
+
+ /**
+ * Emitted when the user changed the completion mode by using the
+ * popupmenu.
+ */
+ void completionModeChanged( OGlobalSettings::Completion );
+
+ /**
+ * Emitted before the context menu is displayed.
+ *
+ * The signal allows you to add your own entries into the
+ * the context menu that is created on demand.
+ *
+ * NOTE: Do not store the pointer to the QPopupMenu
+ * provided through since it is created and deleted
+ * on demand.
+ *
+ * @param the context menu about to be displayed
+ */
+ void aboutToShowContextMenu( QPopupMenu* );
+
+public slots:
+
+ /**
+ * Re-implemented for internal reasons. API not changed.
+ */
+ virtual void setReadOnly(bool);
+
+ /**
+ * Iterates through all possible matches of the completed text or
+ * the history list.
+ *
+ * This function simply iterates over all possible matches in case
+ * multimple matches are found as a result of a text completion request.
+ * It will have no effect if only a single match is found.
+ *
+ * @param type The key-binding invoked.
+ */
+ void rotateText( OCompletionBase::KeyBindingType /* type */ );
+
+ /**
+ * See @ref OCompletionBase::setCompletedText.
+ */
+ virtual void setCompletedText( const QString& );
+
+ /**
+ * Sets @p items into the completion-box if @ref completionMode() is
+ * CompletionPopup. The popup will be shown immediately.
+ */
+ void setCompletedItems( const QStringList& items );
+
+ /**
+ * Reimplemented to workaround a buggy QLineEdit::clear()
+ * (changing the clipboard to the text we just had in the lineedit)
+ */
+ virtual void clear();
+
+protected slots:
+
+ /**
+ * Completes the remaining text with a matching one from
+ * a given list.
+ */
+ virtual void makeCompletion( const QString& );
+
+ /**
+ * @deprecated. Will be removed in the next major release!
+ */
+ void slotAboutToShow() {}
+
+ /**
+ * @deprecated. Will be removed in the next major release!
+ */
+ void slotCancelled() {}
+
+protected:
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See @ref QLineEdit::keyPressEvent().
+ */
+ virtual void keyPressEvent( QKeyEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See @ref QLineEdit::mousePressEvent().
+ */
+ virtual void mousePressEvent( QMouseEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See @ref QWidget::mouseDoubleClickEvent().
+ */
+ virtual void mouseDoubleClickEvent( QMouseEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See @ref QLineEdit::createPopupMenu().
+ */
+ virtual QPopupMenu *createPopupMenu();
+
+ /**
+ * Re-implemented to handle URI drops.
+ *
+ * See @ref QLineEdit::dropEvent().
+ */
+ //virtual void dropEvent( QDropEvent * );
+
+ /*
+ * This function simply sets the lineedit text and
+ * highlights the text appropriately if the boolean
+ * value is set to true.
+ *
+ * @param text
+ * @param marked
+ */
+ virtual void setCompletedText( const QString& /*text*/, bool /*marked*/ );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void create( WId = 0, bool initializeWindow = true,
+ bool destroyOldWindow = true );
+
+private slots:
+ void completionMenuActivated( int id );
+ void tripleClickTimeout(); // resets possibleTripleClick
+
+private:
+ // Constants that represent the ID's of the popup menu.
+ // TODO: See if we can replace this mess with KActionMenu
+ // in the future though it's working lovely.
+ enum MenuID {
+ Default = 42,
+ NoCompletion,
+ AutoCompletion,
+ ShellCompletion,
+ PopupCompletion,
+ SemiAutoCompletion
+ };
+
+ /**
+ * Initializes variables. Called from the constructors.
+ */
+ void init();
+
+ /**
+ * Creates the completion box
+ */
+ void makeCompletionBox();
+
+ /**
+ * Checks whether we should/should not consume a key used as
+ * an accelerator.
+ */
+ //bool overrideAccel (const QKeyEvent* e);
+
+ bool m_bEnableMenu;
+
+ bool possibleTripleClick; // set in mousePressEvent, deleted in tripleClickTimeout
+
+protected:
+ //virtual void virtual_hook( int id, void* data );
+private:
+ class OLineEditPrivate;
+ OLineEditPrivate *d;
+};
+
+#endif