summaryrefslogtreecommitdiff
authormickeyl <mickeyl>2003-03-28 15:11:52 (UTC)
committer mickeyl <mickeyl>2003-03-28 15:11:52 (UTC)
commit11304d02942e9fa493e4e80943a828f9c65f6772 (patch) (unidiff)
treea0223c10c067e1afc70d15c2b82be3f3c15e41ae
parentb271d575fa05cf570a1a829136517761bd47e69b (diff)
downloadopie-11304d02942e9fa493e4e80943a828f9c65f6772.zip
opie-11304d02942e9fa493e4e80943a828f9c65f6772.tar.gz
opie-11304d02942e9fa493e4e80943a828f9c65f6772.tar.bz2
skeleton and the start of libopie2, please read README, ROADMAP and STATUS and comment...
Diffstat (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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1/********************************************************************
2/* This is an overview of the opielibs2 project
3/********************************************************************/
4
5 Origin: opielibs is about creating classes to
6 * optimize Qt classes for the embedded environment
7 * provide sophisticated abstractions for developers
8 * provide complete documentation and working examples
9 * provide end users with a common look and feel
10 * reduce memory footprint through sharing code
11 * reduce possible bugs through reusing tested code
12
13--------------------------------------------------------
141. General Overview
15--------------------------------------------------------
16
17libopie is functionally seperated into the following libraries:
18 - libopiecore
19 - libopieui
20 - libopiepim
21 - libopiedb
22 - libopienet
23
241.1 Contents of libopiecore [ opiecore ]
25--------------------------------------------------------
26
27 - odbgstream
28 - ondbgstream
29
30 - oprocctrl
31 - oprocess
32 - odevice
33 - odevicebutton
34
35 - oconfig
36 - oconfiggroupsaver
37
38 - ocompletionbase
39 - ocompletion
40 - ocomptreenodelist
41 - ocomptreenode
42 - ocompletionwrapper
43
44 - oglobal
45 - oglobalsettings
46
47 - osortableitem
48 - osortablevaluelist
49
501.2 Contents of libopieui [ opieui ]
51--------------------------------------------------------
52
53 - oapplication
54
55 - ofiledialog
56 - colordialog
57 - oclickablelabel
58 - ocolorbutton
59 - colorpopupmenu
60 - otabinfo
61 - otabbar
62 - otabwidget
63 - ofontmenu
64 - ofontselector
65 - ofileview
66 - oticker
67
68 - olistview
69 - olistviewitem
70 - oversatileview
71 - oversatileviewitem
72 - ocompletionbox
73 - olineedit
74 - ocombobox
75 - ohistorycombo
76
77 - omessagebox
78 - odialogbase
79
80 - todayconfigwidget (rather into opiepim?)
81 - orecurrancewidget (rather into opiepim?)
82 - otimepicker (rather into opiepim?)
83
841.3 Contents of libopiepim [ opiepim ]
85--------------------------------------------------------
86
87 - ocheckitem
88 - todoevent
89 - todoresource
90 - todayplugininterface
91 - todovcalresource
92
931.4 Contents of libopiedb [ opiedb ]
94--------------------------------------------------------
95
96 - tododb
97 - xmltree
98
991.5 Contents of libopienet [ opienet ]
100--------------------------------------------------------
101
102 - onetwork
103 - onetworkinterface
104 - owirelessnetworkinterface
105 - ochannelhopper
106
107 - omonitoring
108 - ociscomonitoring
109 - owlanngmonitoring
110 - ohostapmonitoring
111 - oorinocomonitoring
112
113 - opacketcapturer
114 - opacket
115 - oethernetpacket
116 - owavelanpacket
117 - ollcpacket
118 - oippacket
119 - oudppacket
120 - otcppacket
121
122 <libmail stuff>
123 <libbend stuff>
124 <libftp stuff>
125
126
127--------------------------------------------------------
1282.0 Feature Description
129--------------------------------------------------------
130
1312.1 libopiecore
132
133...
134
1352.2 libopieui
136
137...
138
1392.3 libopiepim
140
141...
142
1432.4 libopiedb
144
145...
146
1472.5 libopienet
148
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 @@
1 [done] * import current status of opiecore, opienet and opieui
2 * add contents of libopie1 to libopie2 and functionally split it
3 * make libopie2 a drop-in-replacement for libopie1
4 * add doxygen documentation to all classes
5 * backport qt3-only stuff (?)
6
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 @@
1
2==================================================================
3March 2003 - Initial checkin into the Opie CVS:
4==================================================================
5
6So, this is what I have been working on over the last months.
7It's a part of what I think could migrate into our next generation
8opielibs.
9Of course this won't happen after we released Opie 1.0 and switched
10to Qt3-Embedded and gcc 3.
11
12Right now, there is content only in opiecore, opienet and opieui.
13A good part of code has been adapted from the kdelibs, which overall
14are pretty good however in details of heterogenous quality. I'm also
15not sure if all I ported should be kept, e.g. the pixmapeffect stuff
16seems unnecesary to me. However, we should not forget that Opie will
17make its debut on more powerful devices with greater display
18resolution, e.g. the Sharp C700, so we shouldn't limit ourselves in
19what should go into the libraries.
20
21Generally spoken, a lot of things are still very rough and messy,
22but I will keep improving this. Some details about what is usable
23and what is not follows:
24(everything compiles of course, otherwise I wouldn't have checked in :-)
25
26[-----------]
27[ opiecore ]
28[-----------]
29oapplication, oconfig, oglobal seem to be usable yet, oglobalsettings
30is still very messy and should be revised. A lot more thinking about how
31we should keep opie preferences, especially when moving to multi-user, has to be made.
32This will affect what goes into oglobalsettings and what configuration data
33format we will use. If we switch to Qt3 we will have to decide if we stay
34with OConfig deriving from Config or rewrite it using QSettings.
35
36[-----------]
37[ opiedb ]
38[-----------]
39There is nothing here yet. The sqlite stuff should be here.
40
41[-----------]
42[ opienet ]
43[-----------]
44onetwork*, omonitoring* and the opacket stuff are pretty usable and not
45very far from being complete. documentation for these will come...
46Over the next days, opie-wellenreiter, opie-wirelessapplet and the
47forthcoming new opie-networkapplet will be using the
48new network classes.
49I think all the other network libraries spread throught opie, e.g.
50libbend, libmail, ftplib should be revised and become part of
51opienet eventually.
52
53[-----------]
54[ opiepim ]
55[-----------]
56Nothing here yet. The stuff currently in libopie/pim should be here.
57
58[-----------]
59[ opieui ]
60[-----------]
61Pretty messy yet, but some things are usable. Unfortunately, the UI
62stuff is very hard to backport to Qt2, so some things only work
63if compiled against Qt3, especially all the popupcompletion stuff.
64OListView however works nice and is currently used in opie-wellenreiter.
65
66==================================================================
67October 2002 - Started work on cornucopia aka opielib2
68================================================================== \ 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 @@
1menu "libopie2"
2 source libopie2/opiecore/config.in
3 source libopie2/opiedb/config.in
4 source libopie2/opienet/config.in
5 source libopie2/opiepim/config.in
6 source libopie2/opieui/config.in
7 comment ""
8 source libopie2/examples/config.in
9endmenu
10
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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1 config LIBOPIE2EXAMPLES
2 boolean "libopie2 examples"
3 default "n"
4 depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE && LIBOPIE2NET && LIBOPIE2UI && LIBOPIE2PIM && LIBOPIE2UI
5 comment "the examples need a libqpe, libopie2core, libopie2db, libopie2net, libopie2pim and libopie2ui"
6 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 @@
1TEMPLATE = subdirs
2unix:SUBDIRS = opieui opienet opiecore
3
4#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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1#include <opie2/oapplication.h>
2#include <opie2/oconfig.h>
3#include <qpe/config.h>
4
5int main( int argc, char** argv )
6{
7 OApplication* app = new OApplication( argc, argv, "MyConfigDemoApplication" );
8
9 OConfigGroupSaver c1( app->config(), "MyGroup" );
10 app->config()->writeEntry( "AnEntry", "InMyGroup" );
11 {
12 OConfigGroupSaver c2( c1.config(), "AnotherGroup" );
13 app->config()->writeEntry( "AnEntry", "InAnotherGroup" );
14 } // closing the scope returns to the last group
15
16 app->config()->writeEntry( "AnotherEntry", "InMyGroup" );
17
18 // do more stuff ...
19
20 // in this (special) case it is necessary to manually call OConfig::write() (see below)
21 app->config()->write();
22
23 // can't delete the app when using the OConfigGroupSaver on top level scope,
24 // because the destructor of the OConfigGroupSaver needs an application object
25 //delete app; // destructor deletes config which writes changes back to disk
26
27 return 0;
28
29}
30
31//#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 @@
1TEMPLATE = app
2CONFIG = qt warn_on debug
3HEADERS =
4SOURCES = oconfigdemo.cpp
5
6INCLUDEPATH += $(OPIEDIR)/include
7DEPENDPATH += $(OPIEDIR)/include
8LIBS += -lopiecore2
9TARGET = oconfigdemo
10MOC_DIR = moc
11OBJECTS_DIR = obj
12
13include ( $(OPIEDIR)/include.pro )
14
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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1/* QT */
2
3#include <qvbox.h>
4#include <qhbox.h>
5#include <qvbuttongroup.h>
6#include <qhbuttongroup.h>
7#include <qlineedit.h>
8#include <qradiobutton.h>
9#include <qpushbutton.h>
10
11/* OPIE */
12
13#include <qpe/config.h>
14
15#include <opie2/odebug.h>
16#include <opie2/oapplication.h>
17#include <opie2/oglobal.h>
18#include <opie2/oglobalsettings.h>
19
20class DemoApp : public OApplication
21{
22Q_OBJECT
23public:
24 DemoApp( int argc, char** argv ) : OApplication( argc, argv, "libopie2 debug demo" )
25 {
26 // you have access to your OApplication object via oApp
27 qDebug( "Process-wide OApplication object @ %0x", oApp );
28
29 // you have access to global settings via OGlobalSettings
30 int mode = OGlobalSettings::debugMode();
31
32 QVBox* vbox = new QVBox();
33 setMainWidget( vbox );
34
35 g = new QVButtonGroup( "Output Strategy", vbox );
36 QRadioButton* r0 = new QRadioButton( "file", g );
37 QRadioButton* r1 = new QRadioButton( "messagebox", g );
38 QRadioButton* r2 = new QRadioButton( "stderr", g );
39 QRadioButton* r3 = new QRadioButton( "syslog", g );
40 QRadioButton* r4 = new QRadioButton( "socket", g );
41 g->insert( r0, 0 );
42 g->insert( r1, 1 );
43 g->insert( r2, 2 );
44 g->insert( r3, 3 );
45 g->insert( r4, 4 );
46 g->setRadioButtonExclusive( true );
47 connect( g, SIGNAL( clicked(int) ), this, SLOT( chooseMethod(int) ) );
48
49 if ( mode != -1 ) g->setButton( mode );
50
51 QHButtonGroup* hbox = new QHButtonGroup( "Extra Output Information", vbox );
52 e = new QLineEdit( hbox );
53 QPushButton* pb = new QPushButton( hbox );
54
55 connect( e, SIGNAL( returnPressed() ), this, SLOT( updateDebugOutput() ) );
56 connect( pb, SIGNAL( clicked() ), this, SLOT( updateDebugOutput() ) );
57
58 // show the additional debug mode dependent output information
59 e->setText( OGlobalSettings::debugOutput() );
60
61 // buttos
62 QPushButton* info = new QPushButton( "Emit Debug(Info) Output!", vbox );
63 connect( info, SIGNAL( clicked() ), this, SLOT( emitInfoOutput() ) );
64 QPushButton* warn = new QPushButton( "Emit a Warning Output!", vbox );
65 connect( warn, SIGNAL( clicked() ), this, SLOT( emitWarningOutput() ) );
66 QPushButton* error = new QPushButton( "Emit an Error Output!", vbox );
67 connect( error, SIGNAL( clicked() ), this, SLOT( emitErrorOutput() ) );
68 QPushButton* fatal = new QPushButton( "Emit a Fatal Output!", vbox );
69 connect( fatal, SIGNAL( clicked() ), this, SLOT( emitFatalOutput() ) );
70
71 QPushButton* tb = new QPushButton( "Emit a Fatal Backtrace!", vbox );
72 connect( tb, SIGNAL( clicked() ), this, SLOT( emitTBOutput() ) );
73
74 info->show();
75 warn->show();
76 error->show();
77 fatal->show();
78 tb->show();
79 g->show();
80 hbox->show();
81 e->show();
82 vbox->show();
83 showMainWidget( vbox );
84 }
85
86public slots:
87 void chooseMethod(int method)
88 {
89 m = method;
90 qDebug( "choosing method: %d", method );
91 OConfig* g = OGlobal::config();
92 g->setGroup( "General" );
93 g->writeEntry( "debugMode", m );
94 e->setText( OGlobalSettings::debugOutput() );
95 }
96 void updateDebugOutput()
97 {
98 OConfig* g = OGlobal::config();
99 g->setGroup( "General" );
100 g->writeEntry( "debugOutput"+QString::number(OGlobalSettings::debugMode()), e->text() );
101 }
102 void emitInfoOutput()
103 {
104 odebug << "This is a debug message" << oendl;
105 }
106 void emitWarningOutput()
107 {
108 owarn << "This is a warning message" << oendl;
109 }
110 void emitErrorOutput()
111 {
112 oerr << "This is an errror message" << oendl;
113 }
114 void emitFatalOutput()
115 {
116 ofatal << "This is a fatal message" << oendl;
117 }
118 void emitTBOutput()
119 {
120 ofatal << "This is a fatal message + backtrace\n" + odBacktrace(); // odBacktrace includes \n
121 }
122
123private:
124 QButtonGroup* g;
125 int m;
126 QLineEdit* e;
127};
128
129int main( int argc, char** argv )
130{
131 DemoApp* app = new DemoApp( argc, argv );
132 app->exec();
133
134 return 0;
135
136}
137
138#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 @@
1TEMPLATE = app
2CONFIG = qt warn_on debug
3HEADERS =
4SOURCES = odebugdemo.cpp
5INCLUDEPATH += $(OPIEDIR)/include
6DEPENDPATH += $(OPIEDIR)/include
7LIBS += -lopiecore2
8TARGET = odebugdemo
9MOC_DIR = moc
10OBJECTS_DIR = obj
11
12include ( $(OPIEDIR)/include.pro )
13
14
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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1#include <opie2/oglobalsettings.h>
2#include <iostream.h>
3
4int main( int argc, char** argv )
5{
6 printf( "current debugmode seems to be '%d'\n", OGlobalSettings::debugMode() );
7 printf( "output information for this mode is '%s'\n", (const char*) OGlobalSettings::debugOutput() );
8
9 return 0;
10
11}
12
13//#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 @@
1TEMPLATE = app
2CONFIG = qt warn_on debug
3HEADERS =
4SOURCES = oglobalsettingsdemo.cpp
5INCLUDEPATH += $(OPIEDIR)/include
6DEPENDPATH += $(OPIEDIR)/include
7LIBS += -lopiecore2
8TARGET = oglobalsettingsdemo
9MOC_DIR = moc
10OBJECTS_DIR = obj
11
12include ( $(OPIEDIR)/include.pro )
13
14
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 @@
1TEMPLATE = subdirs
2unix:SUBDIRS = odebugdemo oconfigdemo oglobalsettingsdemo
3
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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1#include <qdict.h>
2#include <qsocketnotifier.h>
3#include <qstring.h>
4#include <opie2/onetwork.h>
5#include <qapplication.h>
6#include <opie2/opcap.h>
7#include <cerrno>
8#include <cstdio>
9#include <cstdlib>
10#include <cstring>
11
12//======================== Station help class ===============================
13
14class Station
15{
16 public:
17 Station( QString t, int c, bool w ) : type(t), channel(c), wep(w), beacons(1) {};
18 ~Station() {};
19
20 QString type;
21 int channel;
22 bool wep;
23 int beacons;
24};
25
26QDict<Station> stations;
27
28//======================== Application class ===============================
29
30class Wellenreiter : public QApplication
31{
32Q_OBJECT
33public:
34 Wellenreiter( int argc, char** argv ) : QApplication( argc, argv )
35 {
36
37 ONetwork* net = ONetwork::instance();
38
39 if ( argc < 3 )
40 {
41 printf( "Usage: ./%s <interface> <driver> <interval>\n", argv[0] );
42 printf( "\n" );
43 printf( "Valid wireless interfaces (detected) are:\n" );
44
45 ONetwork::InterfaceIterator it = net->iterator();
46 while ( it.current() )
47 {
48 if ( it.current()->isWireless() )
49 {
50 printf( " - '%s' (MAC=%s) (IPv4=%s)\n", (const char*) it.current()->name(),
51 (const char*) it.current()->macAddress().toString(),
52 (const char*) it.current()->ipV4Address() );
53 }
54 ++it;
55 }
56 exit( -1 );
57 }
58
59 printf( "****************************************************\n" );
60 printf( "* Wellenreiter mini edition 1.0 (C) 2003 M-M-M *\n" );
61 printf( "****************************************************\n" );
62 printf( "\n\n" );
63
64 QString interface( argv[1] );
65 QString driver( argv[2] );
66
67 printf( "Trying to use '%s' as %s-controlled device...\n", (const char*) interface, (const char*) driver );
68
69 // sanity checks before downcasting
70 ONetworkInterface* iface = net->interface( interface );
71 if ( !iface )
72 {
73 printf( "Interface '%s' doesn't exist. Exiting.\n", (const char*) interface );
74 exit( -1 );
75 }
76 if ( !iface->isWireless() )
77 {
78 printf( "Interface '%s' doesn't support wireless extensions. Exiting.\n", (const char*) interface );
79 exit( -1 );
80 }
81
82 // downcast should be safe now
83 wiface = (OWirelessNetworkInterface*) iface;
84 printf( "Using wireless interface '%s' for scanning (current SSID is '%s')...\n", (const char*) interface, (const char*) wiface->SSID() );
85
86 /*
87
88 // ifconfig down the interface - this enable more crash-proof
89 // scanning with drivers like spectrum_cs...
90 if ( wiface->isUp() )
91 {
92 printf( "Interface status is up... switching to down... " );
93 wiface->setUp( false );
94 if ( wiface->isUp() )
95 {
96 printf( "failed (%s). Exiting.\n", strerror( errno ) );
97 exit( -1 );
98 }
99 else
100 {
101 printf( "ok.\n" );
102 }
103 }
104 else
105 printf( "Interface status is already down - good.\n" );
106
107 */
108
109 // ifconfig +promisc the interface to receive all packets
110 if ( !wiface->promiscuousMode() )
111 {
112 printf( "Interface status is not promisc... switching to promisc... " );
113 wiface->setPromiscuousMode( true );
114 if ( !wiface->promiscuousMode() )
115 {
116 printf( "failed (%s). Exiting.\n", strerror( errno ) );
117 exit( -1 );
118 }
119 else
120 {
121 printf( "ok.\n" );
122 }
123 }
124 else
125 printf( "Interface status is already promisc - good.\n" );
126
127 // connect a monitoring strategy to the interface
128 if ( driver == "orinoco" )
129 new OOrinocoMonitoringInterface( wiface );
130 else
131 {
132 printf( "Unknown driver. Exiting\n" );
133 exit( -1 );
134 }
135
136 // enable monitoring mode
137 printf( "Enabling monitor mode...\n" );
138 wiface->setMonitorMode( true );
139
140 // open a packet capturer
141 cap = new OPacketCapturer();
142 cap->open( interface );
143 if ( !cap->isOpen() )
144 {
145 printf( "Unable to open libpcap (%s). Exiting.\n", strerror( errno ) );
146 exit( -1 );
147 }
148
149 // set capturer to non-blocking mode
150 cap->setBlocking( false );
151
152 // start channel hopper
153 wiface->setChannelHopping( 1000 );
154
155 // connect
156 connect( cap, SIGNAL( receivedPacket(OPacket*) ), this, SLOT( receivePacket(OPacket*) ) );
157
158 }
159
160 ~Wellenreiter() {};
161
162public slots:
163 void receivePacket(OPacket* p)
164 {
165 if (!p)
166 {
167 printf( "(empty packet received)\n" );
168 return;
169 }
170
171 OWaveLanManagementPacket* beacon = (OWaveLanManagementPacket*) p->child( "802.11 Management" );
172
173 if ( beacon )
174 {
175 if ( stations.find( beacon->SSID() ) )
176 stations[beacon->SSID()]->beacons++;
177 else
178 {
179 printf( "found new network @ channel %d, SSID = '%s'\n", wiface->channel(), (const char*) beacon->SSID() );
180 stations.insert( beacon->SSID(), new Station( "unknown", wiface->channel(),
181 ((OWaveLanPacket*) beacon->parent())->usesWep() ) );
182 }
183 }
184 }
185private:
186 OPacketCapturer* cap;
187 OWirelessNetworkInterface* wiface;
188};
189
190
191int main( int argc, char** argv )
192{
193 Wellenreiter w( argc, argv );
194 w.exec();
195 return 0;
196}
197
198#include "miniwellenreiter.moc"
199
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 @@
1TEMPLATE = app
2CONFIG = qt warn_on debug
3HEADERS =
4SOURCES = miniwellenreiter.cpp
5INCLUDEPATH += $(OPIEDIR)/include
6DEPENDPATH += $(OPIEDIR)/include
7LIBS += -lopiecore2 -lopienet2
8TARGET = miniwellenreiter
9MOC_DIR = moc
10OBJECTS_DIR = obj
11
12include ( $(OPIEDIR)/include.pro )
13
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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1#include <opie2/onetwork.h>
2
3int main( int argc, char** argv )
4{
5 qDebug( "OPIE Network Demo" );
6
7 ONetwork* net = ONetwork::instance();
8
9 ONetwork::InterfaceIterator it = net->iterator();
10
11 while ( it.current() )
12 {
13 qDebug( "DEMO: ONetwork contains Interface '%s'", (const char*) it.current()->name() );
14 qDebug( "DEMO: MAC Address is '%s'", (const char*) it.current()->macAddress().toString() );
15 qDebug( "Demo: IPv4 Address is '%s'", (const char*) it.current()->ipV4Address() );
16 if ( it.current()->isWireless() )
17 {
18 OWirelessNetworkInterface* iface = static_cast<OWirelessNetworkInterface*>( it.current() );
19 qDebug( "DEMO: '%s' seems to feature the wireless extensions.", (const char*) iface->name() );
20 qDebug( "DEMO: Current SSID is '%s'", (const char*) iface->SSID() );
21 qDebug( "DEMO: Current NickName is '%s'", (const char*) iface->nickName() );
22 qDebug( "DEMO: Antenna is tuned to '%f', that is channel %d", iface->frequency(), iface->channel() );
23
24 //if ( iface->mode() == OWirelessNetworkInterface::adhoc )
25 //{
26 qDebug( "DEMO: Associated AP has MAC Address '%s'", (const char*) iface->associatedAP() );
27 //}
28
29 }
30 ++it;
31 }
32
33 return 0;
34
35}
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 @@
1TEMPLATE = app
2CONFIG = qt warn_on debug
3HEADERS =
4SOURCES = onetworkdemo.cpp
5INCLUDEPATH += $(OPIEDIR)/include
6DEPENDPATH += $(OPIEDIR)/include
7LIBS += -lopiecore2 -lopienet2
8TARGET = onetworkdemo
9MOC_DIR = moc
10OBJECTS_DIR = obj
11
12include ( $(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 @@
1TEMPLATE = subdirs
2SUBDIRS = miniwellenreiter onetworkdemo
3
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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1/**********************************************************************
2** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved.
3**
4** This file is part of Opie Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14**********************************************************************/
15
16#include "opieuidemo.h"
17
18#include <opie2/oapplication.h>
19
20int main( int argc, char **argv )
21{
22 OApplication a( argc, argv, "Opie UI Demo" );
23 qDebug( "." );
24 OpieUIDemo e;
25 qDebug( "." );
26 a.showMainWidget(&e);
27 qDebug( "." );
28 return a.exec();
29}
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 @@
1TEMPLATE = app
2CONFIG = qt warn_on debug
3HEADERS = opieuidemo.h \
4 oversatileviewdemo.h
5SOURCES = opieuidemo.cpp \
6 oversatileviewdemo.cpp \
7 main.cpp
8INCLUDEPATH += $(OPIEDIR)/include
9DEPENDPATH += $(OPIEDIR)/include
10LIBS += -lopieui2 -lopiecore2
11TARGET = opieuidemo
12MOC_DIR = moc
13OBJECTS_DIR = obj
14
15include ( $(OPIEDIR)/include.pro )
16
17
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 @@
1/**********************************************************************
2** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved.
3**
4** This file is part of Opie Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14***********************************************************************/
15
16// Qt
17
18#include <qcolor.h>
19#include <qpopupmenu.h>
20#include <qmenubar.h>
21#include <qmessagebox.h>
22#include <qvbox.h>
23#include <qstring.h>
24#include <qstringlist.h>
25
26// Qtopia
27
28#ifdef QWS
29#include <qpe/qpeapplication.h>
30#include <qpe/global.h>
31#endif
32
33// Opie
34
35#ifdef QWS
36#include <opie/odevice.h>
37using namespace Opie;
38#endif
39
40#include <opie2/ocompletionbox.h>
41#include <opie2/olineedit.h>
42#include <opie2/ocombobox.h>
43#include <opie2/oeditlistbox.h>
44#include <opie2/oselector.h>
45#include <opie2/opopupmenu.h>
46
47#include <qtabwidget.h>
48#include "oversatileviewdemo.h"
49
50// Local
51
52#include "opieuidemo.h"
53
54enum Demos { ocompletionbox, olineedit, ocombobox, oeditlistbox, oselector };
55
56OpieUIDemo::OpieUIDemo( QWidget* parent, const char* name, WFlags fl )
57 : QMainWindow( parent, name, fl )
58{
59
60 QMenuBar* mbar = this->menuBar();
61 OPopupMenu* demo = new OPopupMenu( this );
62 demo->setTitle( "Title" );
63 demo->setItemParameter( demo->insertItem( "OCompletionBox", this, SLOT( demo(int) ) ), ocompletionbox );
64 demo->setItemParameter( demo->insertItem( "OLineEdit", this, SLOT( demo(int) ) ), olineedit );
65 demo->setItemParameter( demo->insertItem( "OComboBox", this, SLOT( demo(int) ) ), ocombobox );
66 demo->setItemParameter( demo->insertItem( "OEditListBox", this, SLOT( demo(int) ) ), oeditlistbox );
67 demo->setItemParameter( demo->insertItem( "OSelector", this, SLOT( demo(int) ) ), oselector );
68 mbar->insertItem( "Demonstrate", demo );
69
70 build();
71
72}
73
74OpieUIDemo::~OpieUIDemo()
75{
76}
77
78void OpieUIDemo::build()
79{
80 main = new QTabWidget( this, "tabwidget" );
81 setCentralWidget( main );
82 main->show();
83
84 main->addTab( new OVersatileViewDemo( main ), "VersatileView" );
85}
86
87
88void OpieUIDemo::demo( int d )
89{
90 switch (d)
91 {
92 case ocompletionbox: demoOCompletionBox(); break;
93 case olineedit: demoOLineEdit(); break;
94 case ocombobox: demoOComboBox(); break;
95 case oeditlistbox: demoOEditListBox(); break;
96 case oselector: demoOSelector(); break;
97
98 }
99
100}
101
102void OpieUIDemo::demoOCompletionBox()
103{
104 qDebug( "ocompletionbox" );
105
106 OCompletionBox* box = new OCompletionBox( 0 );
107 box->insertItem( "This CompletionBox" );
108 box->insertItem( "Says 'Hello World'" );
109 box->insertItem( "Here are some" );
110 box->insertItem( "Additional Items" );
111 box->insertItem( "Complete Completion Box" );
112
113 connect( box, SIGNAL( activated( const QString& ) ), this, SLOT( messageBox( const QString& ) ) );
114 box->popup();
115
116}
117
118void OpieUIDemo::demoOLineEdit()
119{
120 qDebug( "olineedit" );
121
122 OLineEdit *edit = new OLineEdit( 0, "lineedit" );
123
124 edit->setCompletionMode( OGlobalSettings::CompletionPopup );
125 OCompletion* comp = edit->completionObject();
126
127 QStringList list;
128 list << "mickeyl@handhelds.org";
129 list << "mickey@tm.informatik.uni-frankfurt.de";
130 list << "mickey@vanille.de";
131
132 comp->setItems( list );
133
134 edit->show();
135
136}
137
138void OpieUIDemo::demoOComboBox()
139{
140 qDebug( "ocombobox" );
141
142 OComboBox *combo = new OComboBox( true, 0, "combobox" );
143
144 combo->setCompletionMode( OGlobalSettings::CompletionPopup );
145 OCompletion* comp = combo->completionObject();
146
147 QStringList ilist;
148 ilist << "kergoth@handhelds.org";
149 ilist << "harlekin@handhelds.org";
150 ilist << "groucho@handhelds.org";
151 combo->insertStringList( ilist );
152
153 QStringList clist;
154 clist << "mickeyl@handhelds.org";
155 clist << "mickey@tm.informatik.uni-frankfurt.de";
156 clist << "mickey@vanille.de";
157 comp->setItems( clist );
158
159 combo->show();
160
161}
162
163void OpieUIDemo::demoOEditListBox()
164{
165 qDebug( "oeditlistbox" );
166
167 OEditListBox* edit = new OEditListBox( "OEditListBox", 0, "editlistbox" );
168
169 edit->lineEdit()->setCompletionMode( OGlobalSettings::CompletionPopup );
170 OCompletion* comp = edit->lineEdit()->completionObject();
171 QStringList clist;
172 clist << "Completion everywhere";
173 clist << "Cool Completion everywhere";
174 clist << "History History History";
175 comp->setItems( clist );
176
177 QStringList list;
178 list << "kergoth@handhelds.org";
179 list << "harlekin@handhelds.org";
180 list << "groucho@handhelds.org";
181 list << "mickeyl@handhelds.org";
182 edit->insertStringList( list );
183
184 edit->show();
185
186}
187
188void OpieUIDemo::demoOSelector()
189{
190 qDebug( "oselector" );
191
192 OHSSelector* sel = new OHSSelector( 0, "gradientselector" );
193 //#sel->resize( QSize( 200, 30 ) );
194 //#sel->setColors( QColor( 90, 190, 60 ), QColor( 200, 55, 255 ) );
195 //#sel->setText( "Dark", "Light" );
196
197 sel->show();
198}
199
200void OpieUIDemo::messageBox( const QString& text )
201{
202 QString info;
203 info = "You have selected '" + text + "'";
204 QMessageBox::information( this, "OpieUIDemo", info );
205}
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 @@
1/**********************************************************************
2** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved.
3**
4** This file is part of Opie Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14**********************************************************************/
15
16#ifndef OPIEUIDEMO_H
17#define OPIEUIDEMO_H
18
19#include <qmainwindow.h>
20
21class OVersatileView;
22class QTabWidget;
23class QVBox;
24
25class OpieUIDemo : public QMainWindow {
26 Q_OBJECT
27
28public:
29
30 OpieUIDemo( QWidget* parent = 0, const char* name = 0, WFlags fl = WType_TopLevel );
31 ~OpieUIDemo();
32
33 void demoOCompletionBox();
34 void demoOLineEdit();
35 void demoOComboBox();
36 void demoOEditListBox();
37 void demoOSelector();
38
39public slots:
40 void demo( int );
41 void messageBox( const QString& text );
42
43protected:
44 void build();
45 void buildVV( QVBox* b );
46
47private:
48 QTabWidget* main;
49
50 OVersatileView* vv;
51
52};
53
54
55
56#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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael 'Mickey' Lauer
5 <mickey@tm.informatik.uni-frankfurt.de>
6 =.
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33#include "oversatileviewdemo.h"
34#include <opie2/oversatileview.h>
35#include <opie2/oversatileviewitem.h>
36
37#include <qstring.h>
38#include <qpixmap.h>
39#include <qlistview.h>
40
41OVersatileViewDemo::OVersatileViewDemo( QWidget* parent, const char* name, WFlags f )
42 :QVBox( parent, name, f )
43{
44 vv = new OVersatileView( this );
45
46 vv->addColumn( "First" );
47 vv->addColumn( "2nd" );
48 vv->addColumn( "IIIrd" );
49
50 QString counter;
51
52 QPixmap leaf( "leaf.png" );
53 QPixmap opened( "folder_opened.png" );
54 QPixmap closed( "folder_closed.png" );
55
56 QPixmap leaf32( "leaf32.png" );
57 QPixmap opened32( "folder_opened32.png" );
58 QPixmap closed32( "folder_closed32.png" );
59
60 vv->setDefaultPixmaps( OVersatileView::Tree, leaf, opened, closed );
61 vv->setDefaultPixmaps( OVersatileView::Icons, leaf32, opened32, closed32 );
62
63 OVersatileViewItem* item;
64 OVersatileViewItem* item2;
65
66 for ( int i = 0; i < 5; ++i )
67 {
68 counter.sprintf( "%d", i );
69 item = new OVersatileViewItem( vv, "Item", "Text", "Some more", counter );
70 item->setRenameEnabled( true );
71 item2 = new OVersatileViewItem( item, "OSubitem", "123", "...", counter );
72 item2->setRenameEnabled( true );
73
74 }
75
76 connect( vv, SIGNAL( selectionChanged() ), this, SLOT( selectionChanged() ) );
77 connect( vv, SIGNAL( selectionChanged( OVersatileViewItem * ) ), this, SLOT( selectionChanged( OVersatileViewItem * ) ) );
78 connect( vv, SIGNAL( currentChanged( OVersatileViewItem * ) ), this, SLOT( currentChanged( OVersatileViewItem * ) ) );
79 connect( vv, SIGNAL( clicked( OVersatileViewItem * ) ), this, SLOT( clicked( OVersatileViewItem * ) ) );
80 connect( vv, SIGNAL( pressed( OVersatileViewItem * ) ), this, SLOT( pressed( OVersatileViewItem * ) ) );
81
82 connect( vv, SIGNAL( doubleClicked( OVersatileViewItem * ) ), this, SLOT( doubleClicked( OVersatileViewItem * ) ) );
83 connect( vv, SIGNAL( returnPressed( OVersatileViewItem * ) ), this, SLOT( returnPressed( OVersatileViewItem * ) ) );
84
85 connect( vv, SIGNAL( onItem( OVersatileViewItem * ) ), this, SLOT( onItem( OVersatileViewItem * ) ) );
86 connect( vv, SIGNAL( onViewport() ), this, SLOT( onViewport() ) );
87
88 connect( vv, SIGNAL( expanded( OVersatileViewItem * ) ), this, SLOT( expanded( OVersatileViewItem * ) ) );
89 connect( vv, SIGNAL( collapsed( OVersatileViewItem * ) ), this, SLOT( collapsed( OVersatileViewItem * ) ) );
90
91 connect( vv, SIGNAL( moved() ), this, SLOT( moved() ) );
92
93 connect( vv, SIGNAL( contextMenuRequested( OVersatileViewItem *, const QPoint&, int ) ), this, SLOT( contextMenuRequested( OVersatileViewItem *, const QPoint&, int ) ) );
94
95}
96
97OVersatileViewDemo::~OVersatileViewDemo()
98{
99}
100
101void OVersatileViewDemo::selectionChanged()
102{
103 qDebug( "received signal selectionChanged()" );
104}
105void OVersatileViewDemo::selectionChanged( OVersatileViewItem * item )
106{
107 qDebug( "received signal selectionChanged(OVersatileViewItem*)" );
108}
109void OVersatileViewDemo::currentChanged( OVersatileViewItem * item )
110{
111 qDebug( "received signal currentChanged( OVersatileViewItem * )" );
112}
113void OVersatileViewDemo::clicked( OVersatileViewItem * item )
114{
115 qDebug( "received signal clicked( OVersatileViewItem * )" );
116}
117void OVersatileViewDemo::pressed( OVersatileViewItem * item )
118{
119 qDebug( "received signal pressed( OVersatileViewItem * )" );
120}
121
122void OVersatileViewDemo::doubleClicked( OVersatileViewItem *item )
123{
124 qDebug( "received signal doubleClicked( OVersatileViewItem *item )" );
125}
126void OVersatileViewDemo::returnPressed( OVersatileViewItem *item )
127{
128 qDebug( "received signal returnPressed( OVersatileViewItem *item )" );
129}
130
131void OVersatileViewDemo::onItem( OVersatileViewItem *item )
132{
133 qDebug( "received signal onItem( OVersatileViewItem *item )" );
134}
135void OVersatileViewDemo::onViewport()
136{
137 qDebug( "received signal onViewport()" );
138}
139
140void OVersatileViewDemo::expanded( OVersatileViewItem *item )
141{
142 qDebug( "received signal expanded( OVersatileViewItem *item )" );
143}
144
145void OVersatileViewDemo::collapsed( OVersatileViewItem *item )
146{
147 qDebug( "received signal collapsed( OVersatileViewItem *item )" );
148}
149
150void OVersatileViewDemo::moved()
151{
152 qDebug( "received signal moved( OVersatileViewItem *item )" );
153}
154
155void OVersatileViewDemo::contextMenuRequested( OVersatileViewItem *item, const QPoint& pos, int col )
156{
157 qDebug( "received signal contextMenuRequested( OVersatileViewItem *item )" );
158}
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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#ifndef OVERSATILEVIEWDEMO_H
33#define OVERSATILEVIEWDEMO_H
34
35#include <qvbox.h>
36
37class OVersatileView;
38class OVersatileViewItem;
39
40class OVersatileViewDemo: public QVBox
41{
42 Q_OBJECT
43
44 public:
45 OVersatileViewDemo( QWidget* parent=0, const char* name=0, WFlags f=0 );
46 virtual ~OVersatileViewDemo();
47
48 public slots:
49 void selectionChanged();
50 void selectionChanged( OVersatileViewItem * );
51 void currentChanged( OVersatileViewItem * );
52 void clicked( OVersatileViewItem * );
53 void pressed( OVersatileViewItem * );
54
55 void doubleClicked( OVersatileViewItem *item );
56 void returnPressed( OVersatileViewItem *item );
57
58 void onItem( OVersatileViewItem *item );
59 void onViewport();
60
61 void expanded( OVersatileViewItem *item );
62 void collapsed( OVersatileViewItem *item );
63
64 void moved();
65
66 void contextMenuRequested( OVersatileViewItem *item, const QPoint&, int col );
67
68 private:
69 OVersatileView* vv;
70
71};
72
73#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 @@
1Files: $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
2Priority: optional
3Section: opie/system
4Maintainer: Opie Team <opie@handhelds.org>
5Architecture: arm
6Version: 1.8.1
7Depends: libqpe1
8Provides: libopie2
9Replaces: libopie2
10Description: 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 @@
1#!/bin/sh
2
3[ -x /sbin/ldconfig ] && /sbin/ldconfig
4exit 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 @@
1TEMPLATE = subdirs
2unix:SUBDIRS = opiecore opiedb opiepim opieui opienet examples
3
4include ( $(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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1 config LIBOPIE2CORE
2 boolean "libopie2core (application, configuration and debug related classes)"
3 default "n"
4 depends ( LIBQPE || LIBQPE-X11 )
5 comment "libopie2core needs a libqpe (yet)"
6 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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29*/
30
31#include <opie2/oapplication.h>
32#include <opie2/oconfig.h>
33
34OApplication* OApplication::_instance = 0;
35
36/**************************************************************************************************/
37/* OApplicationPrivate
38/**************************************************************************************************/
39
40class OApplicationPrivate
41{
42 public:
43 OApplicationPrivate() {};
44 ~OApplicationPrivate() {};
45};
46
47/**************************************************************************************************/
48/* OApplication
49/**************************************************************************************************/
50
51
52OApplication::OApplication( int& argc, char** argv, const QCString& rAppName )
53 :OApplicationBaseClass( argc, argv ),
54 _appname( rAppName ),
55 _config( 0 )
56{
57 init();
58}
59
60
61OApplication::~OApplication()
62{
63 delete d;
64 if ( _config )
65 delete _config;
66 OApplication::_instance = 0;
67 // after deconstruction of the one-and-only application object,
68 // the construction of another object is allowed
69}
70
71
72OConfig* OApplication::config()
73{
74 if ( not _config )
75 {
76 _config = new OConfig( _appname );
77 }
78 return _config;
79}
80
81
82void OApplication::init()
83{
84 d = new OApplicationPrivate();
85 if ( !OApplication::_instance )
86 {
87 OApplication::_instance = this;
88 }
89 else
90 {
91 qFatal( "OApplication: Can't create more than one OApplication object. Aborting." );
92 }
93}
94
95void OApplication::setMainWidget( QWidget* widget )
96{
97 showMainWidget( widget );
98}
99
100void OApplication::showMainWidget( QWidget* widget, bool nomax )
101{
102 #ifdef Q_WS_QWS
103 QPEApplication::showMainWidget( widget, nomax );
104 #else
105 QApplication::setMainWidget( widget );
106 widget->show();
107 #endif
108 widget->setCaption( _appname );
109
110}
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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29*/
30
31#ifndef OAPPLICATION_H
32#define OAPPLICATION_H
33
34#define oApp OApplication::oApplication()
35
36#ifdef QWS
37 #include <qpe/qpeapplication.h>
38 #define OApplicationBaseClass QPEApplication
39#else
40 #include <qapplication.h>
41 #define OApplicationBaseClass QApplication
42#endif
43
44class OApplicationPrivate;
45class OConfig;
46
47class OApplication: public OApplicationBaseClass
48{
49 public:
50
51 /**
52 * Constructor. Parses command-line arguments and sets the window caption.
53 *
54 * @param rAppName application name. Will be used for finding the
55 * associated message, icon and configuration files
56 *
57 */
58 OApplication( int& argc, char** argv, const QCString& rAppName );
59 /**
60 * Destructor. Destroys the application object and its children.
61 */
62 virtual ~OApplication();
63
64 /**
65 * Returns the current application object.
66 *
67 * This is similar to the global @ref QApplication pointer qApp. It
68 * allows access to the single global OApplication object, since
69 * more than one cannot be created in the same application. It
70 * saves you the trouble of having to pass the pointer explicitly
71 * to every function that may require it.
72 * @return the current application object
73 */
74 static const OApplication* oApplication() { return _instance; };
75
76 /**
77 * Returns the application name as given during creation.
78 *
79 * @return A reference to the application name
80 */
81 const QCString& appName() const { return _appname; };
82
83 /**
84 * Returns the application session config object.
85 *
86 * @return A pointer to the application's instance specific
87 * @ref OConfig object.
88 * @see OConfig
89 */
90 OConfig* config();
91
92 /**
93 * Sets the main widget - reimplemented to call showMainWidget()
94 * on Qt/Embedded.
95 */
96 virtual void setMainWidget( QWidget *mainWidget );
97
98 /**
99 * Shows the main widget - reimplemented to call setMainWidget()
100 * on platforms other than Qt/Embedded.
101 */
102 virtual void showMainWidget( QWidget* widget, bool nomax = false );
103
104 protected:
105 void init();
106
107 private:
108 const QCString _appname;
109 static OApplication* _instance;
110 OConfig* _config;
111 OApplicationPrivate* d;
112};
113
114#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 @@
1/*
2                 This file is part of the Opie Project
3
4 (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 Inspired by the config classes from the KDE Project which are
6 =. (C) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30*/
31
32/* QT */
33
34#include <qfont.h>
35#include <qcolor.h>
36
37/* OPIE */
38
39#include <opie2/oconfig.h>
40
41OConfig::OConfig( const QString &name, Domain domain )
42 :Config( name, domain )
43{
44}
45
46OConfig::~OConfig()
47{
48}
49
50QColor OConfig::readColorEntry( const QString& key, const QColor* pDefault ) const
51{
52 QColor aRetColor;
53 int nRed = 0, nGreen = 0, nBlue = 0;
54
55 QString aValue = readEntry( key );
56 if( !aValue.isEmpty() )
57 {
58 if ( aValue.at(0) == '#' )
59 {
60 aRetColor.setNamedColor(aValue);
61 }
62 else
63 {
64 bool bOK;
65
66 // find first part (red)
67 int nIndex = aValue.find( ',' );
68
69 if( nIndex == -1 )
70 {
71 // return a sensible default -- Bernd
72 if( pDefault )
73 aRetColor = *pDefault;
74 return aRetColor;
75 }
76
77 nRed = aValue.left( nIndex ).toInt( &bOK );
78
79 // find second part (green)
80 int nOldIndex = nIndex;
81 nIndex = aValue.find( ',', nOldIndex+1 );
82
83 if( nIndex == -1 )
84 {
85 // return a sensible default -- Bernd
86 if( pDefault )
87 aRetColor = *pDefault;
88 return aRetColor;
89 }
90 nGreen = aValue.mid( nOldIndex+1,
91 nIndex-nOldIndex-1 ).toInt( &bOK );
92
93 // find third part (blue)
94 nBlue = aValue.right( aValue.length()-nIndex-1 ).toInt( &bOK );
95
96 aRetColor.setRgb( nRed, nGreen, nBlue );
97 }
98 }
99 else {
100
101 if( pDefault )
102 aRetColor = *pDefault;
103 }
104
105 return aRetColor;
106}
107
108// FIXME: The whole font handling has to be revised for Opie
109
110QFont OConfig::readFontEntry( const QString& key, const QFont* pDefault ) const
111{
112 /*
113 QFont aRetFont;
114
115 QString aValue = readEntry( key );
116 if( !aValue.isNull() ) {
117 if ( aValue.contains( ',' ) > 5 ) {
118 // KDE3 and upwards entry
119 if ( !aRetFont.fromString( aValue ) && pDefault )
120 aRetFont = *pDefault;
121 }
122 else {
123 // backward compatibility with older font formats
124 // ### remove KDE 3.1 ?
125 // find first part (font family)
126 int nIndex = aValue.find( ',' );
127 if( nIndex == -1 ){
128 if( pDefault )
129 aRetFont = *pDefault;
130 return aRetFont;
131 }
132 aRetFont.setFamily( aValue.left( nIndex ) );
133
134 // find second part (point size)
135 int nOldIndex = nIndex;
136 nIndex = aValue.find( ',', nOldIndex+1 );
137 if( nIndex == -1 ){
138 if( pDefault )
139 aRetFont = *pDefault;
140 return aRetFont;
141 }
142
143 aRetFont.setPointSize( aValue.mid( nOldIndex+1,
144 nIndex-nOldIndex-1 ).toInt() );
145
146 // find third part (style hint)
147 nOldIndex = nIndex;
148 nIndex = aValue.find( ',', nOldIndex+1 );
149
150 if( nIndex == -1 ){
151 if( pDefault )
152 aRetFont = *pDefault;
153 return aRetFont;
154 }
155
156 aRetFont.setStyleHint( (QFont::StyleHint)aValue.mid( nOldIndex+1, nIndex-nOldIndex-1 ).toUInt() );
157
158 // find fourth part (char set)
159 nOldIndex = nIndex;
160 nIndex = aValue.find( ',', nOldIndex+1 );
161
162 if( nIndex == -1 ){
163 if( pDefault )
164 aRetFont = *pDefault;
165 return aRetFont;
166 }
167
168 QString chStr=aValue.mid( nOldIndex+1,
169 nIndex-nOldIndex-1 );
170 // find fifth part (weight)
171 nOldIndex = nIndex;
172 nIndex = aValue.find( ',', nOldIndex+1 );
173
174 if( nIndex == -1 ){
175 if( pDefault )
176 aRetFont = *pDefault;
177 return aRetFont;
178 }
179
180 aRetFont.setWeight( aValue.mid( nOldIndex+1,
181 nIndex-nOldIndex-1 ).toUInt() );
182
183 // find sixth part (font bits)
184 uint nFontBits = aValue.right( aValue.length()-nIndex-1 ).toUInt();
185
186 aRetFont.setItalic( nFontBits & 0x01 );
187 aRetFont.setUnderline( nFontBits & 0x02 );
188 aRetFont.setStrikeOut( nFontBits & 0x04 );
189 aRetFont.setFixedPitch( nFontBits & 0x08 );
190 aRetFont.setRawMode( nFontBits & 0x20 );
191 }
192 }
193 else
194 {
195 if( pDefault )
196 aRetFont = *pDefault;
197 }
198 return aRetFont;
199 */
200 return QFont("Helvetica",10);
201}
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 @@
1/*
2                 This file is part of the Opie Project
3
4 (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 Inspired by the config classes from the KDE Project which are
6 =. (C) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30*/
31
32#ifndef OCONFIG_H
33#define OCONFIG_H
34
35//FIXME: Implement for X11 or reuse libqpe/Config there also?
36
37#include <qpe/config.h>
38
39class QColor;
40class QFont;
41
42/**
43 * A Configuration class based on the Qtopia @ref Config class
44 * featuring additional handling of color and font entries
45 */
46
47class OConfig : public Config
48{
49 public:
50
51 /**
52 * Constructs a OConfig object.
53 *
54 * @param name A file to parse.
55 */
56 OConfig( const QString &name, Domain domain = User );
57
58 /**
59 * Destructs the OConfig object.
60 *
61 * Writes back any dirty configuration entries, and destroys
62 * dynamically created objects.
63 */
64 virtual ~OConfig();
65
66 /**
67 * Returns the name of the group in which we are
68 * searching for keys and from which we are retrieving entries.
69 *
70 * @return The current group.
71 */
72 const QString& group() { return git.key(); };
73
74 /**
75 * Reads a @ref QColor entry.
76 *
77 * Read the value of an entry specified by @p pKey in the current group
78 * and interpret it as a color.
79 *
80 * @param pKey The key to search for.
81 * @param pDefault A default value (null QColor by default) returned if the
82 * key was not found or if the value cannot be interpreted.
83 * @return The value for this key.
84 */
85 QColor readColorEntry( const QString& key, const QColor* pDefault ) const;
86
87 /**
88 * Reads a @ref QFont value.
89 *
90 * Read the value of an entry specified by @p pKey in the current group
91 * and interpret it as a font object.
92 *
93 * @param pKey The key to search for.
94 * @param pDefault A default value (null QFont by default) returned if the
95 * key was not found or if the read value cannot be interpreted.
96 * @return The value for this key.
97 */
98 QFont readFontEntry( const QString& key, const QFont* pDefault ) const;
99
100};
101
102/**
103 * Helper class to facilitate working with @ref OConfig / @ref OSimpleConfig
104 * groups.
105 *
106 * Careful programmers always set the group of a
107 * @ref OConfig object to the group they want to read from
108 * and set it back to the old one of afterwards. This is usually
109 * written as:
110 * <pre>
111 *
112 * QString oldgroup config()->group();
113 * config()->setGroup( "TheGroupThatIWant" );
114 * ...
115 * config()->writeEntry( "Blah", "Blubb" );
116 *
117 * config()->setGroup( oldgroup );
118 * </pre>
119 *
120 * In order to facilitate this task, you can use
121 * OConfigGroupSaver. Simply construct such an object ON THE STACK
122 * when you want to switch to a new group. Then, when the object goes
123 * out of scope, the group will automatically be restored. If you
124 * want to use several different groups within a function or method,
125 * you can still use OConfigGroupSaver: Simply enclose all work with
126 * one group (including the creation of the OConfigGroupSaver object)
127 * in one block.
128 *
129 * @author Matthias Kalle Dalheimer <Kalle@kde.org>
130 * @version $Id$
131 * @see OConfig
132 * @short Helper class for easier use of OConfig groups
133 */
134
135class OConfigGroupSaver
136{
137 public:
138 /**
139 * Constructor. You pass a pointer to the OConfigBase-derived
140 * object you want to work with and a string indicating the _new_
141 * group.
142 * @param config The OConfig-derived object this
143 * OConfigGroupSaver works on.
144 * @param group The new group that the config object should switch to.
145 */
146 OConfigGroupSaver( OConfig* config, QString group ) :_config(config), _oldgroup(config->group() )
147 { _config->setGroup( group ); }
148
149 OConfigGroupSaver( OConfig* config, const char *group ) :_config(config), _oldgroup(config->group())
150 { _config->setGroup( group ); }
151
152 OConfigGroupSaver( OConfig* config, const QCString &group ) : _config(config), _oldgroup(config->group())
153 { _config->setGroup( group ); }
154
155 ~OConfigGroupSaver() { _config->setGroup( _oldgroup ); }
156
157 OConfig* config() { return _config; };
158
159 private:
160 OConfig* _config;
161 QString _oldgroup;
162
163 OConfigGroupSaver( const OConfigGroupSaver& );
164 OConfigGroupSaver& operator=( const OConfigGroupSaver& );
165};
166
167#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 @@
1/*
2 This file is part of the Opie Project
3 (C) 2003 Michael 'Mickey' Lauer (mickey@tm.informatik.uni-frankfurt.de)
4 Inspired by the KDE debug classes, which are
5 (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
6 (C) 2002 Holger Freyther (freyther@kde.org)
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31*/
32
33// Include this header without OPIE_NO_DEBUG defined to avoid having the oDebugInfo
34// functions inlined to noops (which would then conflict with their definition here).
35
36#include <opie2/odebug.h>
37
38#ifdef OPIE_NO_DEBUG
39#undef odDebug
40#undef odBacktrace
41#endif
42
43/* OPIE */
44
45#include <opie2/oapplication.h>
46#include <opie2/oglobalsettings.h>
47#include <opie2/oconfig.h>
48
49/* QT */
50
51#include <qbrush.h>
52#include <qdatetime.h>
53#include <qfile.h>
54#include <qhostaddress.h>
55#include <qmessagebox.h>
56#include <qintdict.h>
57#include <qpoint.h>
58#include <qrect.h>
59#include <qregion.h>
60#include <qsize.h>
61#include <qsocketdevice.h>
62#include <qstring.h>
63#include <qstringlist.h>
64#include <qtextstream.h>
65
66/* UNIX */
67
68#include <stdlib.h> // abort
69#include <unistd.h> // getpid
70#include <stdarg.h> // vararg stuff
71#include <ctype.h> // isprint
72#include <syslog.h>
73#include <errno.h>
74#include <string.h>
75
76#ifndef OPIE_NO_BACKTRACE
77#include <execinfo.h>
78#endif
79
80
81/*======================================================================================
82 * debug levels
83 *======================================================================================*/
84
85enum DebugLevels {
86 ODEBUG_INFO = 0,
87 ODEBUG_WARN = 1,
88 ODEBUG_ERROR = 2,
89 ODEBUG_FATAL = 3
90};
91
92/*======================================================================================
93 * oDebug private data
94 *======================================================================================*/
95
96/*======================================================================================
97 * the main debug function
98 *======================================================================================*/
99
100static void oDebugBackend( unsigned short level, unsigned int area, const char *data)
101{
102 //qDebug( "oDebugBackend: Level=%d, Area=%d, Data=%s", level, area, data );
103
104 // ML: OPIE doesn't use areacodes at the moment. See the KDE debug classes for an
105 // ML: example use. I think it's not necessary to implement such a strategy here.
106 // ML: Comments?
107
108 int priority = 0;
109 QString caption;
110 QString lev;
111 switch( level )
112 {
113 case ODEBUG_INFO: lev = "(Info)"; caption = "Info"; priority = LOG_INFO; break;
114 case ODEBUG_WARN: lev = "(Warn)"; caption = "Warning"; priority = LOG_WARNING; break;
115 case ODEBUG_FATAL: lev = "(Fatal)"; caption = "Fatal Error"; priority = LOG_CRIT; break;
116 default: qDebug( "oDebugBackend: Warning: Unknown debug level! - defaulting to ODEBUG_ERROR." );
117 case ODEBUG_ERROR: lev = "(Error)"; caption = "Error"; priority = LOG_ERR; break;
118 }
119
120 short output = OGlobalSettings::debugMode();
121 if (!oApp && (output == 1))
122 {
123 qDebug( "oDebugBackend: Warning: no oapplication object - can't use MsgBox" );
124 output = 2; // need an application object to use MsgBox
125 }
126
127 QString areaName = (oApp) ? oApp->appName() : "<unknown>";
128
129 // Output
130 switch( output )
131 {
132 case -1: // ignore
133 {
134 return;
135 }
136 case 0: // File
137 {
138 QString outputFilename = OGlobalSettings::debugOutput();
139
140 const int BUFSIZE = 4096;
141 char buf[BUFSIZE] = "";
142 buf[BUFSIZE-1] = '\0';
143 int nSize;
144
145 nSize = snprintf( buf, BUFSIZE-1, "%s: %s", (const char*) areaName, data);
146
147 QFile outputFile( outputFilename );
148 if ( outputFile.open( IO_WriteOnly | IO_Append ) )
149 {
150 if ( ( nSize == -1 ) || ( nSize >= BUFSIZE ) )
151 {
152 outputFile.writeBlock( buf, BUFSIZE-1 );
153 }
154 else
155 {
156 outputFile.writeBlock( buf, nSize );
157 }
158 }
159 else
160 {
161 qDebug( "ODebug: can't write to file '%s' (%s)", (const char*) outputFilename, strerror(errno) );
162 }
163 break;
164 } // automatic close of file here
165
166 case 1: // Message Box
167 {
168 // Since we are in opiecore here, we cannot use OMsgBox and use
169 // QMessageBox instead
170
171 caption += QString("(") + areaName + ")";
172 QMessageBox::warning( 0L, caption, data, ("&OK") ); // tr?
173 break;
174 }
175
176 case 2: // Shell
177 {
178 FILE *output = stderr;
179 fprintf( output, "%s: ", (const char*) areaName );
180 fputs( data, output);
181 break;
182 }
183
184 case 3: // syslog
185 {
186 syslog( priority, "%s", data);
187 break;
188 }
189
190 case 4: // socket
191 {
192 QString destination = OGlobalSettings::debugOutput();
193 if ( destination && destination.find(":") != -1 )
194 {
195 QString host = destination.left( destination.find(":") );
196 QString port = destination.right( destination.length()-host.length()-1 );
197 QHostAddress addr;
198 addr.setAddress( host );
199 // TODO: sanity check the address
200 QString line;
201 line.sprintf( "%s: %s", (const char*) areaName, (const char*) data );
202 QSocketDevice s( QSocketDevice::Datagram );
203 int result = s.writeBlock( (const char*) line, line.length(), addr, port.toInt() );
204 if ( result == -1 )
205 {
206 qDebug( "ODebug: can't send to address '%s:%d' (%s)", (const char*) host, port.toInt(), strerror(errno) );
207 }
208 }
209 break;
210 }
211 }
212
213 // check if we should abort
214
215 /*
216
217 if( ( nLevel == ODEBUG_FATAL )
218 && ( !oDebug_data->config || oDebug_data->config->readNumEntry( "AbortFatal", 1 ) ) )
219 abort();
220
221 */
222}
223
224/*======================================================================================
225 * odbgstream
226 *======================================================================================*/
227
228odbgstream& perror( odbgstream &s)
229{
230 return s << QString::fromLocal8Bit(strerror(errno));
231}
232
233odbgstream odDebug(int area)
234{
235 return odbgstream(area, ODEBUG_INFO);
236}
237odbgstream odDebug(bool cond, int area)
238{
239 if (cond) return odbgstream(area, ODEBUG_INFO);
240 else return odbgstream(0, 0, false);
241}
242
243odbgstream odError(int area)
244{
245 return odbgstream("ERROR: ", area, ODEBUG_ERROR);
246}
247
248odbgstream odError(bool cond, int area)
249{
250 if (cond) return odbgstream("ERROR: ", area, ODEBUG_ERROR); else return odbgstream(0,0,false);
251}
252
253odbgstream odWarning(int area)
254{
255 return odbgstream("WARNING: ", area, ODEBUG_WARN);
256}
257
258odbgstream odWarning(bool cond, int area)
259{
260 if (cond) return odbgstream("WARNING: ", area, ODEBUG_WARN); else return odbgstream(0,0,false);
261}
262
263odbgstream odFatal(int area)
264{
265 return odbgstream("FATAL: ", area, ODEBUG_FATAL);
266}
267
268odbgstream odFatal(bool cond, int area)
269{
270 if (cond) return odbgstream("FATAL: ", area, ODEBUG_FATAL); else return odbgstream(0,0,false);
271}
272
273odbgstream::odbgstream(unsigned int _area, unsigned int _level, bool _print)
274 :area(_area), level(_level), print(_print)
275{
276}
277
278
279odbgstream::odbgstream(const char * initialString, unsigned int _area, unsigned int _level, bool _print)
280 :output(QString::fromLatin1(initialString)), area(_area), level(_level), print(_print)
281{
282}
283
284
285odbgstream::odbgstream(odbgstream &str)
286 :output(str.output), area(str.area), level(str.level), print(str.print)
287{
288 str.output.truncate(0);
289}
290
291
292odbgstream::odbgstream(const odbgstream &str)
293 :output(str.output), area(str.area), level(str.level), print(str.print)
294{
295}
296
297odbgstream& odbgstream::operator<<(bool i)
298{
299 if (!print) return *this;
300 output += QString::fromLatin1(i ? "true" : "false");
301 return *this;
302}
303
304
305odbgstream& odbgstream::operator<<(short i)
306{
307 if (!print) return *this;
308 QString tmp; tmp.setNum(i); output += tmp;
309 return *this;
310}
311
312
313odbgstream& odbgstream::operator<<(unsigned short i)
314{
315 if (!print) return *this;
316 QString tmp; tmp.setNum(i); output += tmp;
317 return *this;
318}
319
320
321odbgstream& odbgstream::operator<<(unsigned char i)
322{
323 return operator<<( static_cast<char>( i ) );
324}
325
326
327odbgstream& odbgstream::operator<<(int i)
328{
329 if (!print) return *this;
330 QString tmp; tmp.setNum(i); output += tmp;
331 return *this;
332}
333
334
335odbgstream& odbgstream::operator<<(unsigned int i)
336{
337 if (!print) return *this;
338 QString tmp; tmp.setNum(i); output += tmp;
339 return *this;
340}
341
342
343odbgstream& odbgstream::operator<<(long i)
344{
345 if (!print) return *this;
346 QString tmp; tmp.setNum(i); output += tmp;
347 return *this;
348}
349
350
351odbgstream& odbgstream::operator<<(unsigned long i)
352{
353 if (!print) return *this;
354 QString tmp; tmp.setNum(i); output += tmp;
355 return *this;
356}
357
358
359odbgstream& odbgstream::operator<<(const QString& string)
360{
361 if (!print) return *this;
362 output += string;
363 if (output.at(output.length() -1 ) == '\n')
364 flush();
365 return *this;
366}
367
368
369odbgstream& odbgstream::operator<<(const char *string)
370{
371 if (!print) return *this;
372 output += QString::fromUtf8(string);
373 if (output.at(output.length() - 1) == '\n')
374 flush();
375 return *this;
376}
377
378
379odbgstream& odbgstream::operator<<(const QCString& string)
380{
381 *this << string.data();
382 return *this;
383}
384
385
386odbgstream& odbgstream::operator<<(const void * p)
387{
388 form("%p", p);
389 return *this;
390}
391
392odbgstream& odbgstream::operator<<(double d)
393{
394 QString tmp; tmp.setNum(d); output += tmp;
395 return *this;
396}
397
398/*
399odbgstream::odbgstream &form(const char *format, ...)
400#ifdef __GNUC__
401 __attribute__ ( ( format ( printf, 2, 3 ) ) )
402#endif
403 ;
404*/
405
406void odbgstream::flush()
407{
408 if ( output.isEmpty() || !print )
409 {
410 return;
411 }
412 else
413 {
414 oDebugBackend( level, area, output.local8Bit().data() );
415 output = QString::null;
416 }
417}
418
419odbgstream& odbgstream::form(const char *format, ...)
420{
421 char buf[4096];
422 va_list arguments;
423 va_start( arguments, format );
424 buf[sizeof(buf)-1] = '\0';
425 vsnprintf( buf, sizeof(buf)-1, format, arguments );
426 va_end(arguments);
427 *this << buf;
428 return *this;
429}
430
431odbgstream::~odbgstream()
432{
433 if (!output.isEmpty())
434 {
435 fprintf(stderr, "ASSERT: debug output not ended with \\n\n");
436 *this << "\n";
437 }
438}
439
440odbgstream& odbgstream::operator<<(char ch)
441{
442 if (!print) return *this;
443 if (!isprint(ch))
444 {
445 output += "\\x" + QString::number( static_cast<uint>( ch ) + 0x100, 16 ).right(2);
446 }
447 else
448 {
449 output += ch;
450 if (ch == '\n') flush();
451 }
452 return *this;
453}
454
455odbgstream& odbgstream::operator<<( QWidget* widget )
456{
457 QString string, temp;
458 // -----
459 if(widget==0)
460 {
461 string=(QString)"[Null pointer]";
462 } else
463 {
464 temp.setNum((ulong)widget, 16);
465 string=(QString)"["+widget->className()+" pointer " + "(0x" + temp + ")";
466 if(widget->name(0)==0)
467 {
468 string += " to unnamed widget, ";
469 } else
470 {
471 string += (QString)" to widget " + widget->name() + ", ";
472 }
473 string += "geometry="
474 + QString().setNum(widget->width())
475 + "x"+QString().setNum(widget->height())
476 + "+"+QString().setNum(widget->x())
477 + "+"+QString().setNum(widget->y())
478 + "]";
479 }
480 if (!print) return *this;
481
482 output += string;
483 if (output.at(output.length()-1) == '\n')
484 {
485 flush();
486 }
487 return *this;
488}
489
490/*
491 * either use 'output' directly and do the flush if needed
492 * or use the QString operator which calls the char* operator
493 *
494 */
495odbgstream& odbgstream::operator<<( const QDateTime& time)
496{
497 *this << time.toString();
498 return *this;
499}
500
501
502odbgstream& odbgstream::operator<<( const QDate& date)
503{
504 *this << date.toString();
505
506 return *this;
507}
508
509
510odbgstream& odbgstream::operator<<( const QTime& time )
511{
512 *this << time.toString();
513 return *this;
514}
515
516
517odbgstream& odbgstream::operator<<( const QPoint& p )
518{
519 *this << "(" << p.x() << ", " << p.y() << ")";
520 return *this;
521}
522
523
524odbgstream& odbgstream::operator<<( const QSize& s )
525{
526 *this << "[" << s.width() << "x" << s.height() << "]";
527 return *this;
528}
529
530
531odbgstream& odbgstream::operator<<( const QRect& r )
532{
533 *this << "[" << r.left() << ", " << r.top() << " - " << r.right() << ", " << r.bottom() << "]";
534 return *this;
535}
536
537
538odbgstream& odbgstream::operator<<( const QRegion& reg )
539{
540 /* Qt2 doesn't have a QMemArray... :(
541 *this << "[ ";
542 QMemArray<QRect>rs=reg.rects();
543 for (uint i=0;i<rs.size();++i)
544 *this << QString("[%1, %2 - %3, %4] ").arg(rs[i].left()).arg(rs[i].top()).arg(rs[i].right()).arg(rs[i].bottom() ) ;
545 *this <<"]";
546 */
547 return *this;
548}
549
550
551odbgstream& odbgstream::operator<<( const QStringList& l )
552{
553 *this << "(";
554 *this << l.join(",");
555 *this << ")";
556
557 return *this;
558}
559
560
561odbgstream& odbgstream::operator<<( const QColor& c )
562{
563 if ( c.isValid() )
564 *this << c.name();
565 else
566 *this << "(invalid/default)";
567 return *this;
568}
569
570
571odbgstream& odbgstream::operator<<( const QBrush& b)
572{
573 static const char* const s_brushStyles[] = {
574 "NoBrush", "SolidPattern", "Dense1Pattern", "Dense2Pattern", "Dense3Pattern",
575 "Dense4Pattern", "Dense5Pattern", "Dense6Pattern", "Dense7Pattern",
576 "HorPattern", "VerPattern", "CrossPattern", "BDiagPattern", "FDiagPattern",
577 "DiagCrossPattern" };
578
579 *this <<"[ style: ";
580 *this <<s_brushStyles[ b.style() ];
581 *this <<" color: ";
582 // can't use operator<<(str, b.color()) because that terminates a odbgstream (flushes)
583 if ( b.color().isValid() )
584 *this <<b.color().name() ;
585 else
586 *this <<"(invalid/default)";
587 if ( b.pixmap() )
588 *this <<" has a pixmap";
589 *this <<" ]";
590 return *this;
591}
592
593
594
595QString odBacktrace( int levels )
596{
597 QString s;
598#ifndef OPIE_NO_BACKTRACE
599 void* trace[256];
600 int n = backtrace(trace, 256);
601 char** strings = backtrace_symbols (trace, n);
602
603 if ( levels != -1 )
604 n = QMIN( n, levels );
605 s = "[\n";
606
607 for (int i = 0; i < n; ++i)
608 s += QString::number(i) +
609 QString::fromLatin1(": ") +
610 QString::fromLatin1(strings[i]) + QString::fromLatin1("\n");
611 s += "]\n";
612 free (strings);
613#endif
614 return s;
615}
616
617void odClearDebugConfig()
618{
619 /*
620 delete oDebug_data->config;
621 oDebug_data->config = 0;
622 */
623}
624
625#ifdef OPIE_NO_DEBUG
626#define odDebug ondDebug
627#define odBacktrace ondBacktrace
628#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 @@
1/*
2 This file is part of the Opie Project
3 (C) 2003 Michael 'Mickey' Lauer (mickey@tm.informatik.uni-frankfurt.de)
4 Inspired by the KDE debug classes, which are
5 (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
6 (C) 2002 Holger Freyther (freyther@kde.org)
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31*/
32
33#ifndef ODEBUG_H
34#define ODEBUG_H
35
36#include <qstring.h>
37
38class QWidget;
39class QDateTime;
40class QDate;
41class QTime;
42class QPoint;
43class QSize;
44class QRect;
45class QRegion;
46class QStringList;
47class QColor;
48class QBrush;
49
50class odbgstream;
51class ondbgstream;
52
53#ifdef __GNUC__
54#define o_funcinfo "[" << __PRETTY_FUNCTION__ << "] "
55#else
56#define o_funcinfo "[" << __FILE__ << ":" << __LINE__ << "] "
57#endif
58
59#define o_lineinfo "[" << __FILE__ << ":" << __LINE__ << "] "
60
61#define owarn odWarning()
62#define oerr odError()
63#define odebug odDebug()
64#define ofatal odFatal()
65#define oendl "\n"
66
67class odbgstreamprivate;
68/**
69 * odbgstream is a text stream that allows you to print debug messages.
70 * Using the overloaded "<<" operator you can send messages. Usually
71 * you do not create the odbgstream yourself, but use @ref odDebug() (odebug)
72 * @ref odWarning() (owarn), @ref odError() (oerr) or @ref odFatal (ofatal) to obtain one.
73 *
74 * Example:
75 * <pre>
76 * int i = 5;
77 * odebug << "The value of i is " << i << oendl;
78 * </pre>
79 * @see odbgstream
80 */
81
82/*======================================================================================
83 * odbgstream
84 *======================================================================================*/
85
86class odbgstream
87{
88 public:
89 /**
90 * @internal
91 */
92 odbgstream(unsigned int _area, unsigned int _level, bool _print = true);
93 odbgstream(const char * initialString, unsigned int _area, unsigned int _level, bool _print = true);
94 odbgstream(odbgstream &str);
95 odbgstream(const odbgstream &str);
96 virtual ~odbgstream();
97
98 /**
99 * Prints the given value.
100 * @param i the boolean to print (as "true" or "false")
101 * @return this stream
102 */
103 odbgstream &operator<<(bool i);
104 /**
105 * Prints the given value.
106 * @param i the short to print
107 * @return this stream
108 */
109 odbgstream &operator<<(short i);
110 /**
111 * Prints the given value.
112 * @param i the unsigned short to print
113 * @return this stream
114 */
115 odbgstream &operator<<(unsigned short i);
116 /**
117 * Prints the given value.
118 * @param i the char to print
119 * @return this stream
120 */
121 odbgstream &operator<<(char i);
122 /**
123 * Prints the given value.
124 * @param i the unsigned char to print
125 * @return this stream
126 */
127 odbgstream &operator<<(unsigned char i);
128 /**
129 * Prints the given value.
130 * @param i the int to print
131 * @return this stream
132 */
133 odbgstream &operator<<(int i);
134 /**
135 * Prints the given value.
136 * @param i the unsigned int to print
137 * @return this stream
138 */
139 odbgstream &operator<<(unsigned int i);
140 /**
141 * Prints the given value.
142 * @param i the long to print
143 * @return this stream
144 */
145 odbgstream &operator<<(long i);
146 /**
147 * Prints the given value.
148 * @param i the unsigned long to print
149 * @return this stream
150 */
151 odbgstream &operator<<(unsigned long i);
152 /**
153 * Flushes the output.
154 */
155 virtual void flush();
156 /**
157 * Prints the given value.
158 * @param string the string to print
159 * @return this stream
160 */
161 odbgstream &operator<<(const QString& string);
162 /**
163 * Prints the given value.
164 * @param string the string to print
165 * @return this stream
166 */
167 odbgstream &operator<<(const char *string);
168 /**
169 * Prints the given value.
170 * @param string the string to print
171 * @return this stream
172 */
173 odbgstream &operator<<(const QCString& string);
174 /**
175 * Prints the given value.
176 * @param p a pointer to print (in number form)
177 * @return this stream
178 */
179 odbgstream& operator<<(const void * p);
180 /**
181 * Prints the given value.
182 * @param d the double to print
183 * @return this stream
184 */
185 odbgstream& operator<<(double d);
186 /**
187 * Prints the string @p format which can contain
188 * printf-style formatted values.
189 * @param format the printf-style format
190 * @return this stream
191 */
192 odbgstream &form(const char *format, ...);
193 /** Operator to print out basic information about a QWidget.
194 * Output of class names only works if the class is moc'ified.
195 * @param widget the widget to print
196 * @return this stream
197 */
198 odbgstream& operator<< (QWidget* widget);
199
200 /**
201 * Prints the given value.
202 * @param dateTime the datetime to print
203 * @return this stream
204 */
205 odbgstream& operator<< ( const QDateTime& dateTime );
206
207 /**
208 * Prints the given value.
209 * @param date the date to print
210 * @return this stream
211 */
212 odbgstream& operator<< ( const QDate& date );
213
214 /**
215 * Prints the given value.
216 * @param time the time to print
217 * @return this stream
218 */
219 odbgstream& operator<< ( const QTime& time );
220
221 /**
222 * Prints the given value.
223 * @param point the point to print
224 * @return this stream
225 */
226 odbgstream& operator<< ( const QPoint& point );
227
228 /**
229 * Prints the given value.
230 * @param size the QSize to print
231 * @return this stream
232 */
233 odbgstream& operator<< ( const QSize& size );
234
235 /**
236 * Prints the given value.
237 * @param rect the QRect to print
238 * @return this stream
239 */
240 odbgstream& operator<< ( const QRect& rect);
241
242 /**
243 * Prints the given value.
244 * @param region the QRegion to print
245 * @return this stream
246 */
247 odbgstream& operator<< ( const QRegion& region);
248
249 /**
250 * Prints the given value.
251 * @param list the stringlist to print
252 * @return this stream
253 */
254 odbgstream& operator<< ( const QStringList& list);
255
256 /**
257 * Prints the given value.
258 * @param color the color to print
259 * @return this stream
260 */
261 odbgstream& operator<< ( const QColor& color);
262
263 /**
264 * Prints the given value.
265 * @param brush the brush to print
266 * @return this stream
267 */
268 odbgstream& operator<< ( const QBrush& brush );
269
270 private:
271 QString output;
272 unsigned int area, level;
273 bool print;
274 odbgstreamprivate* d;
275};
276
277/**
278 * Prints an "\n".
279 * @param s the debug stream to write to
280 * @return the debug stream (@p s)
281 */
282inline odbgstream& endl( odbgstream &s) { s << "\n"; return s; }
283/**
284 * Flushes the stream.
285 * @param s the debug stream to write to
286 * @return the debug stream (@p s)
287 */
288inline odbgstream& flush( odbgstream &s) { s.flush(); return s; }
289
290odbgstream &perror( odbgstream &s);
291
292/**
293 * ondbgstream is a dummy variant of @ref odbgstream. All functions do
294 * nothing.
295 * @see ondDebug()
296 */
297class ondbgstream {
298 public:
299 /// Empty constructor.
300 ondbgstream() {}
301 ~ondbgstream() {}
302 /**
303 * Does nothing.
304 * @return this stream
305 */
306 ondbgstream &operator<<(short int ) { return *this; }
307 /**
308 * Does nothing.
309 * @return this stream
310 */
311 ondbgstream &operator<<(unsigned short int ) { return *this; }
312 /**
313 * Does nothing.
314 * @return this stream
315 */
316 ondbgstream &operator<<(char ) { return *this; }
317 /**
318 * Does nothing.
319 * @return this stream
320 */
321 ondbgstream &operator<<(unsigned char ) { return *this; }
322 /**
323 * Does nothing.
324 * @return this stream
325 */
326 ondbgstream &operator<<(int ) { return *this; }
327 /**
328 * Does nothing.
329 * @return this stream
330 */
331 ondbgstream &operator<<(unsigned int ) { return *this; }
332 /**
333 * Does nothing.
334 */
335 void flush() {}
336 /**
337 * Does nothing.
338 * @return this stream
339 */
340 ondbgstream &operator<<(const QString& ) { return *this; }
341 /**
342 * Does nothing.
343 * @return this stream
344 */
345 ondbgstream &operator<<(const QCString& ) { return *this; }
346 /**
347 * Does nothing.
348 * @return this stream
349 */
350 ondbgstream &operator<<(const char *) { return *this; }
351 /**
352 * Does nothing.
353 * @return this stream
354 */
355 ondbgstream& operator<<(const void *) { return *this; }
356 /**
357 * Does nothing.
358 * @return this stream
359 */
360 ondbgstream& operator<<(void *) { return *this; }
361 /**
362 * Does nothing.
363 * @return this stream
364 */
365 ondbgstream& operator<<(double) { return *this; }
366 /**
367 * Does nothing.
368 * @return this stream
369 */
370 ondbgstream& operator<<(long) { return *this; }
371 /**
372 * Does nothing.
373 * @return this stream
374 */
375 ondbgstream& operator<<(unsigned long) { return *this; }
376 /**
377 * Does nothing.
378 * @return this stream
379 */
380 ondbgstream& operator << (QWidget*) { return *this; }
381 /**
382 * Does nothing.
383 * @return this stream
384 */
385 ondbgstream &form(const char *, ...) { return *this; }
386
387 ondbgstream& operator<<( const QDateTime& ) { return *this; }
388 ondbgstream& operator<<( const QDate& ) { return *this; }
389 ondbgstream& operator<<( const QTime& ) { return *this; }
390 ondbgstream& operator<<( const QPoint & ) { return *this; }
391 ondbgstream& operator<<( const QSize & ) { return *this; }
392 ondbgstream& operator<<( const QRect & ) { return *this; }
393 ondbgstream& operator<<( const QRegion & ) { return *this; }
394 ondbgstream& operator<<( const QStringList & ) { return *this; }
395 ondbgstream& operator<<( const QColor & ) { return *this; }
396 ondbgstream& operator<<( const QBrush & ) { return *this; }
397};
398
399/*======================================================================================
400 * related functions
401 *======================================================================================*/
402
403/**
404 * Does nothing.
405 * @param a stream
406 * @return the given @p s
407 */
408inline ondbgstream& endl( ondbgstream & s) { return s; }
409/**
410 * Does nothing.
411 * @param a stream
412 * @return the given @p s
413 */
414inline ondbgstream& flush( ondbgstream & s) { return s; }
415inline ondbgstream& perror( ondbgstream & s) { return s; }
416
417/**
418 * Returns a debug stream. You can use it to print debug
419 * information.
420 * @param area an id to identify the output, 0 for default
421 */
422odbgstream odDebug(int area = 0);
423odbgstream odDebug(bool cond, int area = 0);
424/**
425 * Returns a backtrace.
426 * @param levels the number of levels (-1 for unlimited) of the backtrace
427 * @return a backtrace
428 */
429QString odBacktrace(int levels = -1);
430/**
431 * Returns a dummy debug stream. The stream does not print anything.
432 * @param area an id to identify the output, 0 for default
433 * @see odDebug()
434 */
435inline ondbgstream ondDebug(int = 0) { return ondbgstream(); }
436inline ondbgstream ondDebug(bool , int = 0) { return ondbgstream(); }
437inline QString ondBacktrace() { return QString::null; }
438inline QString ondBacktrace(int) { return QString::null; }
439
440/**
441 * Returns a warning stream. You can use it to print warning
442 * information.
443 * @param area an id to identify the output, 0 for default
444 */
445odbgstream odWarning(int area = 0);
446odbgstream odWarning(bool cond, int area = 0);
447/**
448 * Returns an error stream. You can use it to print error
449 * information.
450 * @param area an id to identify the output, 0 for default
451 */
452odbgstream odError(int area = 0);
453odbgstream odError(bool cond, int area = 0);
454/**
455 * Returns a fatal error stream. You can use it to print fatal error
456 * information.
457 * @param area an id to identify the output, 0 for default
458 */
459odbgstream odFatal(int area = 0);
460odbgstream odFatal(bool cond, int area = 0);
461
462/**
463 * Deletes the odebugrc cache and therefore forces KDebug to reread the
464 * config file
465 */
466void odClearDebugConfig();
467
468#ifdef OPIE_NO_DEBUG
469#define odDebug ondDebug
470#define odBacktrace ondBacktrace
471#endif
472
473#endif
474
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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29 */
30
31#include <opie2/oglobal.h>
32
33OConfig* OGlobal::config()
34{
35 return &globalconfig;
36}
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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29*/
30
31#ifndef OGLOBAL_H
32#define OGLOBAL_H
33
34#include <qpe/global.h>
35#include <opie2/oconfig.h>
36
37static OConfig globalconfig = OConfig( "global" );
38
39//FIXME: Is it wise or even necessary to inherit OGlobal from Global?
40
41class OGlobal : public Global
42{
43 public:
44
45 static OConfig* config();
46};
47
48#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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 Inspired by the KDE globalsettings which are
6 Copyright (C) 2000 David Faure <faure@kde.org>
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31*/
32
33/* OPIE */
34
35#include <opie2/oglobalsettings.h>
36#include <opie2/oconfig.h>
37#include <opie2/oglobal.h>
38
39/* QT */
40
41#include <qdir.h>
42#include <qpixmap.h>
43#include <qfontinfo.h>
44
45/* UNIX */
46
47#include <stdlib.h>
48
49QString* OGlobalSettings::s_desktopPath = 0;
50QString* OGlobalSettings::s_autostartPath = 0;
51QString* OGlobalSettings::s_trashPath = 0;
52QString* OGlobalSettings::s_documentPath = 0;
53QFont *OGlobalSettings::_generalFont = 0;
54QFont *OGlobalSettings::_fixedFont = 0;
55QFont *OGlobalSettings::_toolBarFont = 0;
56QFont *OGlobalSettings::_menuFont = 0;
57QFont *OGlobalSettings::_windowTitleFont = 0;
58QFont *OGlobalSettings::_taskbarFont = 0;
59
60QColor *OGlobalSettings::OpieGray = 0;
61QColor *OGlobalSettings::OpieHighlight = 0;
62QColor *OGlobalSettings::OpieAlternate = 0;
63
64OGlobalSettings::OMouseSettings *OGlobalSettings::s_mouseSettings = 0;
65
66//FIXME: Add manipulators to the accessors
67
68int OGlobalSettings::dndEventDelay()
69{
70 OConfig *c = OGlobal::config();
71 OConfigGroupSaver cgs( c, "General" );
72 return c->readNumEntry("DndDelay", 2);
73}
74
75bool OGlobalSettings::singleClick()
76{
77 OConfig *c = OGlobal::config();
78 OConfigGroupSaver cgs( c, "OPIE" );
79 return c->readBoolEntry("SingleClick", OPIE_DEFAULT_SINGLECLICK);
80}
81
82bool OGlobalSettings::insertTearOffHandle()
83{
84 OConfig *c = OGlobal::config();
85 OConfigGroupSaver cgs( c, "OPIE" );
86 return c->readBoolEntry("InsertTearOffHandle", OPIE_DEFAULT_INSERTTEAROFFHANDLES);
87}
88
89bool OGlobalSettings::changeCursorOverIcon()
90{
91 OConfig *c = OGlobal::config();
92 OConfigGroupSaver cgs( c, "OPIE" );
93 return c->readBoolEntry("ChangeCursor", OPIE_DEFAULT_CHANGECURSOR);
94}
95
96bool OGlobalSettings::visualActivate()
97{
98 OConfig *c = OGlobal::config();
99 OConfigGroupSaver cgs( c, "OPIE" );
100 return c->readBoolEntry("VisualActivate", OPIE_DEFAULT_VISUAL_ACTIVATE);
101}
102
103unsigned int OGlobalSettings::visualActivateSpeed()
104{
105 OConfig *c = OGlobal::config();
106 OConfigGroupSaver cgs( c, "OPIE" );
107 return
108 c->readNumEntry(
109 "VisualActivateSpeed",
110 OPIE_DEFAULT_VISUAL_ACTIVATE_SPEED
111 );
112}
113
114int OGlobalSettings::autoSelectDelay()
115{
116 OConfig *c = OGlobal::config();
117 OConfigGroupSaver cgs( c, "OPIE" );
118 return c->readNumEntry("AutoSelectDelay", OPIE_DEFAULT_AUTOSELECTDELAY);
119}
120
121OGlobalSettings::Completion OGlobalSettings::completionMode()
122{
123 int completion;
124 OConfig *c = OGlobal::config();
125 OConfigGroupSaver cgs( c, "General" );
126 completion = c->readNumEntry("completionMode", -1);
127 if ((completion < (int) CompletionNone) ||
128 (completion > (int) CompletionPopupAuto))
129 {
130 completion = (int) CompletionPopup; // Default
131 }
132 return (Completion) completion;
133}
134
135
136bool OGlobalSettings::showContextMenusOnPress ()
137{
138 OConfig *c = OGlobal::config();
139 OConfigGroupSaver cgs (c, "ContextMenus");
140
141 return cgs.config()->readBoolEntry("ShowOnPress", true);
142}
143
144
145int OGlobalSettings::contextMenuKey ()
146{
147 OConfig *c = OGlobal::config();
148 OConfigGroupSaver cgs (c, "Shortcuts");
149
150 //OShortcut cut (cgs.config()->readEntry ("PopupMenuContext", "Menu"));
151 //return cut.keyCodeQt();
152
153 return 0; // FIXME
154}
155
156
157OGlobalSettings::Debug OGlobalSettings::debugMode()
158{
159 OConfig *c = OGlobal::config();
160 OConfigGroupSaver cgs( c, "General" );
161 int debug = c->readNumEntry( "debugMode", -1 );
162 if ( (debug < (int) DebugNone) || (debug > (int) DebugSocket) )
163 {
164 debug = (int) DebugStdErr; // Default
165 }
166 return (Debug) debug;
167}
168
169
170QString OGlobalSettings::debugOutput()
171{
172 OConfig *c = OGlobal::config();
173 OConfigGroupSaver cgs( c, "General" );
174 QString deflt = QString::null;
175 switch( debugMode() )
176 {
177 case DebugNone: break; // no additional information needed
178 case DebugFiles: deflt = "/var/log/opiedebug.log"; break; // file to save output in
179 case DebugMsgBox: break; // no additional information needed
180 case DebugStdErr: break; // no additional information needed
181 case DebugSysLog: break; // no additional information needed
182 case DebugSocket: deflt = "127.0.0.1:8913"; break; // address to send packets to
183 }
184
185 return c->readEntry( "debugOutput"+ QString::number(debugMode()), deflt );
186}
187
188
189QColor OGlobalSettings::toolBarHighlightColor()
190{
191 initColors();
192 OConfig *c = OGlobal::config();
193 OConfigGroupSaver cgs( c, QString::fromLatin1("Toolbar style") );
194 return c->readColorEntry("HighlightColor", OpieHighlight);
195}
196
197QColor OGlobalSettings::inactiveTitleColor()
198{
199 if (!OpieGray) OpieGray = new QColor(220, 220, 220);
200 OConfig *c = OGlobal::config();
201 OConfigGroupSaver cgs( c, QString::fromLatin1("WM") );
202 return c->readColorEntry( "inactiveBackground", OpieGray );
203}
204
205QColor OGlobalSettings::inactiveTextColor()
206{
207 OConfig *c = OGlobal::config();
208 OConfigGroupSaver cgs( c, QString::fromLatin1("WM") );
209 return c->readColorEntry( "inactiveForeground", &Qt::darkGray );
210}
211
212QColor OGlobalSettings::activeTitleColor()
213{
214 initColors();
215 OConfig *c = OGlobal::config();
216 OConfigGroupSaver cgs( c, QString::fromLatin1("WM") );
217 return c->readColorEntry( "activeBackground", OpieHighlight);
218}
219
220QColor OGlobalSettings::activeTextColor()
221{
222 OConfig *c = OGlobal::config();
223 OConfigGroupSaver cgs( c, QString::fromLatin1("WM") );
224 return c->readColorEntry( "activeForeground", &Qt::white );
225}
226
227int OGlobalSettings::contrast()
228{
229 OConfig *c = OGlobal::config();
230 OConfigGroupSaver cgs( c, QString::fromLatin1("OPIE") );
231 return c->readNumEntry( "contrast", 7 );
232}
233
234// following functions should work in OPIE - how to sync with appearance changes?
235
236QColor OGlobalSettings::baseColor()
237{
238 OConfig *c = OGlobal::config();
239 OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
240 return c->readColorEntry( "Base", &Qt::white );
241}
242
243QColor OGlobalSettings::textColor()
244{
245 OConfig *c = OGlobal::config();
246 OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
247 return c->readColorEntry( "Text", &Qt::black );
248}
249
250QColor OGlobalSettings::highlightedTextColor()
251{
252 OConfig *c = OGlobal::config();
253 OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
254 return c->readColorEntry( "HighlightedText", &Qt::white );
255}
256
257QColor OGlobalSettings::highlightColor()
258{
259 initColors();
260 OConfig *c = OGlobal::config();
261 OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
262 return c->readColorEntry( "Highlight", OpieHighlight );
263}
264
265QColor OGlobalSettings::alternateBackgroundColor()
266{
267 initColors();
268 OConfig *c = OGlobal::config();
269 OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
270 *OpieAlternate = calculateAlternateBackgroundColor( baseColor() );
271 return c->readColorEntry( "alternateBackground", OpieAlternate );
272}
273
274QColor OGlobalSettings::calculateAlternateBackgroundColor(const QColor& base)
275{
276 if (base == Qt::white)
277 return QColor(238,246,255);
278 else
279 {
280 int h, s, v;
281 base.hsv( &h, &s, &v );
282 if (v > 128)
283 return base.dark(106);
284 else if (base != Qt::black)
285 return base.light(110);
286
287 return QColor(32,32,32);
288 }
289}
290
291QColor OGlobalSettings::linkColor()
292{
293 initColors();
294 OConfig *c = OGlobal::config();
295 OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
296 return c->readColorEntry( "linkColor", OpieGray );
297}
298
299QColor OGlobalSettings::visitedLinkColor()
300{
301 OConfig *c = OGlobal::config();
302 OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
303 return c->readColorEntry( "visitedLinkColor", &Qt::magenta );
304}
305
306// FIXME: font stuff currently uses a different format in OPIE, so the
307// functions below are not yet applicable. The whole font stuff for OPIE
308// has to be revised anyway
309
310QFont OGlobalSettings::generalFont()
311{
312 if (_generalFont)
313 return *_generalFont;
314
315 _generalFont = new QFont("helvetica", 10);
316 _generalFont->setPixelSize(10);
317 _generalFont->setStyleHint(QFont::SansSerif);
318
319 OConfig *c = OGlobal::config();
320 OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") );
321 *_generalFont = c->readFontEntry("font", _generalFont);
322
323 return *_generalFont;
324}
325
326QFont OGlobalSettings::fixedFont()
327{
328 if (_fixedFont)
329 return *_fixedFont;
330
331 _fixedFont = new QFont("courier", 12);
332 _fixedFont->setPixelSize(12);
333 _fixedFont->setStyleHint(QFont::TypeWriter);
334
335 OConfig *c = OGlobal::config();
336 OConfigGroupSaver cgs( c, QString::fromLatin1("General") );
337 *_fixedFont = c->readFontEntry("fixed", _fixedFont);
338
339 return *_fixedFont;
340}
341
342QFont OGlobalSettings::toolBarFont()
343{
344 if(_toolBarFont)
345 return *_toolBarFont;
346
347 _toolBarFont = new QFont("helvetica", 10);
348 _toolBarFont->setPixelSize(10);
349 _toolBarFont->setStyleHint(QFont::SansSerif);
350
351 OConfig *c = OGlobal::config();
352 OConfigGroupSaver cgs( c, QString::fromLatin1("General") );
353 *_toolBarFont = c->readFontEntry("toolBarFont", _toolBarFont);
354
355 return *_toolBarFont;
356}
357
358QFont OGlobalSettings::menuFont()
359{
360 if(_menuFont)
361 return *_menuFont;
362
363 _menuFont = new QFont("helvetica", 12);
364 _menuFont->setPixelSize(12);
365 _menuFont->setStyleHint(QFont::SansSerif);
366
367 OConfig *c = OGlobal::config();
368 OConfigGroupSaver cgs( c, QString::fromLatin1("General") );
369 *_menuFont = c->readFontEntry("menuFont", _menuFont);
370
371 return *_menuFont;
372}
373
374QFont OGlobalSettings::windowTitleFont()
375{
376 if(_windowTitleFont)
377 return *_windowTitleFont;
378
379 _windowTitleFont = new QFont("helvetica", 12, QFont::Bold);
380 _windowTitleFont->setPixelSize(12);
381 _windowTitleFont->setStyleHint(QFont::SansSerif);
382
383 OConfig *c = OGlobal::config();
384 OConfigGroupSaver cgs( c, QString::fromLatin1("WM") );
385 *_windowTitleFont = c->readFontEntry("activeFont", _windowTitleFont); // inconsistency
386
387 return *_windowTitleFont;
388}
389
390QFont OGlobalSettings::taskbarFont()
391{
392 if(_taskbarFont)
393 return *_taskbarFont;
394
395 _taskbarFont = new QFont("helvetica", 8);
396 _taskbarFont->setPixelSize(8);
397 _taskbarFont->setStyleHint(QFont::SansSerif);
398
399 OConfig *c = OGlobal::config();
400 OConfigGroupSaver cgs( c, QString::fromLatin1("General") );
401 *_taskbarFont = c->readFontEntry("taskbarFont", _taskbarFont);
402
403 return *_taskbarFont;
404}
405
406// FIXME: the whole path stuff has to be revised for OPIE
407
408void OGlobalSettings::initStatic() // should be called initPaths(). Don't put anything else here.
409{
410 if ( s_desktopPath != 0 )
411 return;
412
413 s_desktopPath = new QString();
414 s_autostartPath = new QString();
415 s_trashPath = new QString();
416 s_documentPath = new QString();
417
418 OConfig *config = OGlobal::config();
419 //bool dollarExpansion = config->isDollarExpansion();
420 //config->setDollarExpansion(true);
421 OConfigGroupSaver cgs( config, "Paths" );
422
423 // Desktop Path
424 *s_desktopPath = QDir::homeDirPath() + "/" + "Desktop" + "/";
425 *s_desktopPath = config->readEntry( "Desktop", *s_desktopPath);
426 if ( (*s_desktopPath)[0] != '/' )
427 s_desktopPath->prepend( QDir::homeDirPath() + "/" );
428 *s_desktopPath = QDir::cleanDirPath( *s_desktopPath );
429 if ( s_desktopPath->right(1) != "/")
430 *s_desktopPath += "/";
431
432 // Trash Path
433 *s_trashPath = *s_desktopPath + QObject::tr("Trash") + "/";
434 *s_trashPath = config->readEntry( "Trash" , *s_trashPath);
435 if ( (*s_trashPath)[0] != '/' )
436 s_trashPath->prepend( QDir::homeDirPath() + "/" );
437 *s_trashPath = QDir::cleanDirPath( *s_trashPath );
438 if ( s_trashPath->right(1) != "/")
439 *s_trashPath += "/";
440 // We need to save it in any case, in case the language changes later on,
441 if ( !config->hasKey( "Trash" ) )
442 {
443 //config->writePathEntry( "Trash", *s_trashPath, true, true );
444 config->writeEntry( "Trash", *s_trashPath );
445 //config->sync();
446 }
447
448/* // Autostart Path
449 *s_autostartPath = OGlobal::dirs()->localkdedir() + "Autostart" + "/";
450 *s_autostartPath = config->readEntry( "Autostart" , *s_autostartPath);
451 if ( (*s_autostartPath)[0] != '/' )
452 s_autostartPath->prepend( QDir::homeDirPath() + "/" );
453 *s_autostartPath = QDir::cleanDirPath( *s_autostartPath );
454 if ( s_autostartPath->right(1) != "/")
455 *s_autostartPath += "/";
456*/
457 // Document Path
458 *s_documentPath = QString::null;
459 *s_documentPath = config->readEntry( "Documents" , *s_documentPath);
460 if ( (*s_documentPath)[0] != '/' )
461 s_documentPath->prepend( QDir::homeDirPath() + "/" );
462 *s_documentPath = QDir::cleanDirPath( *s_documentPath );
463 if ( s_documentPath->right(1) != "/")
464 *s_documentPath += "/";
465
466 //config->setDollarExpansion(dollarExpansion);
467
468 // Make sure this app gets the notifications about those paths
469 //if (kapp)
470 //kapp->addKipcEventMask(KIPC::SettingsChanged);
471}
472
473void OGlobalSettings::initColors()
474{
475 if ( not OpieHighlight ) OpieHighlight = new QColor( 156, 118, 32 );
476 if ( not OpieAlternate ) OpieAlternate = new QColor( 238, 246, 255 );
477 if ( not OpieGray ) OpieGray = new QColor( 220, 210, 215 );
478}
479
480void OGlobalSettings::rereadFontSettings()
481{
482 delete _generalFont;
483 _generalFont = 0L;
484 delete _fixedFont;
485 _fixedFont = 0L;
486 delete _menuFont;
487 _menuFont = 0L;
488 delete _toolBarFont;
489 _toolBarFont = 0L;
490 delete _windowTitleFont;
491 _windowTitleFont = 0L;
492 delete _taskbarFont;
493 _taskbarFont = 0L;
494}
495
496void OGlobalSettings::rereadPathSettings()
497{
498 qDebug( "OGlobalSettings::rereadPathSettings" );
499 delete s_autostartPath;
500 s_autostartPath = 0L;
501 delete s_trashPath;
502 s_trashPath = 0L;
503 delete s_desktopPath;
504 s_desktopPath = 0L;
505 delete s_documentPath;
506 s_documentPath = 0L;
507}
508
509OGlobalSettings::OMouseSettings & OGlobalSettings::mouseSettings()
510{
511 if ( ! s_mouseSettings )
512 {
513 s_mouseSettings = new OMouseSettings;
514 OMouseSettings & s = *s_mouseSettings; // for convenience
515
516 OConfigGroupSaver cgs( OGlobal::config(), "Mouse" );
517 QString setting = OGlobal::config()->readEntry("MouseButtonMapping");
518 if (setting == "RightHanded")
519 s.handed = OMouseSettings::RightHanded;
520 else if (setting == "LeftHanded")
521 s.handed = OMouseSettings::LeftHanded;
522 else
523 {
524
525 // FIXME: Implement for Opie / Qt Embedded
526
527 }
528 }
529 return *s_mouseSettings;
530}
531
532void OGlobalSettings::rereadMouseSettings()
533{
534 delete s_mouseSettings;
535 s_mouseSettings = 0L;
536}
537
538// FIXME: This won't be necessary, or will it? :-D
539
540bool OGlobalSettings::isMultiHead()
541{
542 QCString multiHead = getenv("OPIE_MULTIHEAD");
543 if (!multiHead.isEmpty()) {
544 return (multiHead.lower() == "true");
545 }
546 return false;
547}
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 @@
1/*
2                 This file is part of the Opie Project
3              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
4 Inspired by KDE OGlobalSettings
5 Copyright (C) 2000 David Faure <faure@kde.org>
6 =.
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30*/
31
32#ifndef OGLOBALSETTINGS_H
33#define OGLOBALSETTINGS_H
34
35#include <qstring.h>
36#include <qcolor.h>
37#include <qfont.h>
38
39#define OPIE_DEFAULT_SINGLECLICK true
40#define OPIE_DEFAULT_INSERTTEAROFFHANDLES true
41#define OPIE_DEFAULT_AUTOSELECTDELAY -1
42#define OPIE_DEFAULT_CHANGECURSOR true
43#define OPIE_DEFAULT_LARGE_CURSOR false
44#define OPIE_DEFAULT_VISUAL_ACTIVATE true
45#define OPIE_DEFAULT_VISUAL_ACTIVATE_SPEED 50
46
47//FIXME: There's still a whole lot of stuff in here which has to be revised
48//FIXME: before public usage... lack of time to do it at once - so it will
49//FIXME: happen step-by-step. ML.
50
51/**
52 * Access the OPIE global configuration settings.
53 *
54 */
55class OGlobalSettings
56{
57 public:
58
59 /**
60 * Returns a threshold in pixels for drag & drop operations.
61 * As long as the mouse movement has not exceeded this number
62 * of pixels in either X or Y direction no drag operation may
63 * be started. This prevents spurious drags when the user intended
64 * to click on something but moved the mouse a bit while doing so.
65 *
66 * For this to work you must save the position of the mouse (oldPos)
67 * in the @ref QWidget::mousePressEvent().
68 * When the position of the mouse (newPos)
69 * in a @ref QWidget::mouseMoveEvent() exceeds this threshold
70 * you may start a drag
71 * which should originate from oldPos.
72 *
73 * Example code:
74 * <pre>
75 * void OColorCells::mousePressEvent( QMouseEvent *e )
76 * {
77 * mOldPos = e->pos();
78 * }
79 *
80 * void OColorCells::mouseMoveEvent( QMouseEvent *e )
81 * {
82 * if( !(e->state() && LeftButton)) return;
83 *
84 * int delay = OGlobalSettings::dndEventDelay();
85 * QPoint newPos = e->pos();
86 * if(newPos.x() > mOldPos.x()+delay || newPos.x() < mOldPos.x()-delay ||
87 * newPos.y() > mOldPos.y()+delay || newPos.y() < mOldPos.y()-delay)
88 * {
89 * // Drag color object
90 * int cell = posToCell(mOldPos); // Find color at mOldPos
91 * if ((cell != -1) && colors[cell].isValid())
92 * {
93 * OColorDrag *d = OColorDrag::makeDrag( colors[cell], this);
94 * d->dragCopy();
95 * }
96 * }
97 * }
98 * </pre>
99 *
100 */
101
102 static int dndEventDelay();
103
104 /**
105 * Returns whether OPIE runs in single (default) or double click
106 * mode.
107 *
108 * @return @p true if single click mode, or @p false if double click mode.
109 *
110 * see @ref http://opie.handhelds.org/documentation/standards/opie/style/mouse/index.html
111 **/
112 static bool singleClick();
113
114 /**
115 * Returns whether tear-off handles are inserted in OPopupMenus.
116 **/
117 static bool insertTearOffHandle();
118
119 /**
120 * @return the OPIE setting for "change cursor over icon"
121 */
122 static bool changeCursorOverIcon();
123
124 /**
125 * @return whether to show some feedback when an item (specifically an
126 * icon) is activated.
127 */
128 static bool visualActivate();
129 static unsigned int visualActivateSpeed();
130
131 /**
132 * Returns the OPIE setting for the auto-select option
133 *
134 * @return the auto-select delay or -1 if auto-select is disabled.
135 */
136 static int autoSelectDelay();
137
138 /**
139 * Returns the OPIE setting for the shortcut key to open
140 * context menus.
141 *
142 * @return the key that pops up context menus.
143 */
144 static int contextMenuKey();
145
146 /**
147 * Returns the OPIE setting for context menus.
148 *
149 * @return whether context menus should be shown on button press
150 * or button release (click).
151 */
152 static bool showContextMenusOnPress ();
153
154 /**
155 * This enum describes the completion mode used for by the @ref OCompletion class.
156 * See <a href="http://opie.handhelds.org/documentation/standards/opie/style/keys/completion.html">
157 * the styleguide</a>.
158 **/
159 enum Completion {
160 /**
161 * No completion is used.
162 */
163 CompletionNone=1,
164 /**
165 * Text is automatically filled in whenever possible.
166 */
167 CompletionAuto,
168 /**
169 * Same as automatic except shortest match is used for completion.
170 */
171 CompletionMan,
172 /**
173 * Complete text much in the same way as a typical *nix shell would.
174 */
175 CompletionShell,
176 /**
177 * Lists all possible matches in a popup list-box to choose from.
178 */
179 CompletionPopup,
180 /**
181 * Lists all possible matches in a popup list-box to choose from, and automatically
182 * fill the result whenever possible.
183 */
184 CompletionPopupAuto
185 };
186 /**
187 * Returns the preferred completion mode setting.
188 *
189 * @return @ref Completion. Default is @p CompletionPopup.
190 */
191 static Completion completionMode();
192
193 /**
194 * This enum describes the debug mode used for by the @ref odbgstream class.
195 * See <a href="http://opie.handhelds.org/documentation/standards/opie/style/debug/debug.html">
196 * the styleguide</a>.
197 **/
198 enum Debug {
199 /**
200 * Debug messages are ignored.
201 */
202 DebugNone=-1,
203 /**
204 * Debug output is sent to files /var/log/***.
205 */
206 DebugFiles=0,
207 /**
208 * Debug output is written in a QMessageBox.
209 */
210 DebugMsgBox=1,
211 /**
212 * Debug output is sent to stderr.
213 */
214 DebugStdErr=2,
215 /**
216 * Debug output is sent to syslog.
217 */
218 DebugSysLog=3,
219 /**
220 * Debug output is sent via udp over a socket.
221 */
222 DebugSocket=4
223 };
224 /**
225 * Returns the preferred debug mode setting.
226 *
227 * @return @ref Debug. Default is @p DebugStdErr.
228 */
229 static Debug debugMode();
230
231 /**
232 * Returns additional information for debug output (dependent on the debug mode).
233 *
234 * @return Additional debug output information.
235 */
236 static QString debugOutput();
237 /**
238 * This is a structure containing the possible mouse settings.
239 */
240 struct OMouseSettings
241 {
242 enum { RightHanded = 0, LeftHanded = 1 };
243 int handed; // left or right
244 };
245
246 /**
247 * This returns the current mouse settings.
248 */
249 static OMouseSettings & mouseSettings();
250
251 /**
252 * The path to the desktop directory of the current user.
253 */
254 static QString desktopPath() { initStatic(); return *s_desktopPath; }
255
256 /**
257 * The path to the autostart directory of the current user.
258 */
259 static QString autostartPath() { initStatic(); return *s_autostartPath; }
260
261 /**
262 * The path to the trash directory of the current user.
263 */
264 static QString trashPath() { initStatic(); return *s_trashPath; }
265
266 /**
267 * The path where documents are stored of the current user.
268 */
269 static QString documentPath() { initStatic(); return *s_documentPath; }
270
271
272 /**
273 * The default color to use when highlighting toolbar buttons
274 */
275 static QColor toolBarHighlightColor();
276 static QColor inactiveTitleColor();
277 static QColor inactiveTextColor();
278 static QColor activeTitleColor();
279 static QColor activeTextColor();
280 static int contrast();
281
282 /**
283 * The default colors to use for text and links.
284 */
285 static QColor baseColor(); // Similair to QColorGroup::base()
286 static QColor textColor(); // Similair to QColorGroup::text()
287 static QColor linkColor();
288 static QColor visitedLinkColor();
289 static QColor highlightedTextColor(); // Similair to QColorGroup::hightlightedText()
290 static QColor highlightColor(); // Similair to QColorGroup::highlight()
291
292 /**
293 * Returns the alternate background color used by @ref OListView with
294 * @ref OListViewItem. Any other list that uses alternating background
295 * colors should use this too, to obey to the user's preferences. Returns
296 * an invalid color if the user doesn't want alternating backgrounds.
297 * @see #calculateAlternateBackgroundColor
298 */
299 static QColor alternateBackgroundColor();
300 /**
301 * Calculates a color based on @p base to be used as alternating
302 * color for e.g. listviews.
303 * @see #alternateBackgroundColor
304 */
305 static QColor calculateAlternateBackgroundColor(const QColor& base);
306
307
308 static QFont generalFont();
309 static QFont fixedFont();
310 static QFont toolBarFont();
311 static QFont menuFont();
312 static QFont windowTitleFont();
313 static QFont taskbarFont();
314
315 /**
316 * Returns if the user specified multihead. In case the display
317 * has multiple screens, the return value of this function specifies
318 * if the user wants OPIE to run on all of them or just on the primary
319 */
320 static bool isMultiHead();
321
322private:
323 /**
324 * reads in all paths from kdeglobals
325 */
326 static void initStatic();
327 /**
328 * initialise kde2Blue
329 */
330 static void initColors();
331 /**
332 * drop cached values for fonts (called by OApplication)
333 */
334 static void rereadFontSettings();
335 /**
336 * drop cached values for paths (called by OApplication)
337 */
338 static void rereadPathSettings();
339 /**
340 * drop cached values for mouse settings (called by OApplication)
341 */
342 static void rereadMouseSettings();
343
344
345 static QString* s_desktopPath;
346 static QString* s_autostartPath;
347 static QString* s_trashPath;
348 static QString* s_documentPath;
349 static QFont *_generalFont;
350 static QFont *_fixedFont;
351 static QFont *_toolBarFont;
352 static QFont *_menuFont;
353 static QFont *_windowTitleFont;
354 static QFont *_taskbarFont;
355 static QColor * kde2Gray;
356 static QColor * kde2Blue;
357 static QColor * kde2AlternateColor;
358 static OMouseSettings *s_mouseSettings;
359
360 static QColor * OpieGray;
361 static QColor * OpieBlue;
362 static QColor * OpieAlternate;
363 static QColor * OpieHighlight;
364
365 friend class OApplication;
366};
367
368#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 @@
1TEMPLATE = lib
2CONFIG += qt warn_on debug
3DESTDIR = $(OPIEDIR)/lib
4HEADERS = oapplication.h \
5 oconfig.h \
6 ocompletionbase.h \
7 ocompletion.h \
8 odebug.h \
9 oglobal.h \
10 oglobalsettings.h \
11 osortablevaluelist.h
12
13SOURCES = oapplication.cpp \
14 oconfig.cpp \
15 ocompletionbase.cpp \
16 ocompletion.cpp \
17 odebug.cpp \
18 oglobal.cpp \
19 oglobalsettings.cpp
20
21INTERFACES =
22TARGET = opiecore2
23VERSION = 1.8.1
24INCLUDEPATH += $(OPIEDIR)/include
25DEPENDPATH += $(OPIEDIR)/include
26LIBS = -lqpe
27MOC_DIR = moc
28OBJECTS_DIR = obj
29
30include ( $(OPIEDIR)/include.pro )
31
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 @@
1 config LIBOPIE2DB
2 boolean "libopie2db (database related classes)"
3 default "n"
4 depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE
5 comment "libopie2db needs a libqpe and libopie2core"
6 depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE)
7
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 @@
1TEMPLATE = lib
2CONFIG += qt warn_on debug
3DESTDIR = $(OPIEDIR)/lib
4HEADERS =
5
6SOURCES =
7INTERFACES =
8TARGET = opiedb2
9VERSION = 1.8.1
10INCLUDEPATH += $(OPIEDIR)/include
11DEPENDPATH += $(OPIEDIR)/include
12
13MOC_DIR = moc
14OBJECTS_DIR = obj
15
16include ( $(OPIEDIR)/include.pro )
17
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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1#ifndef IEEE_802_11
2#define IEEE_802_11
3
4enum ieee_802_11_link_status_failure_reason {
5 reserved0, Unspecified=1, Previous_not_valid,
6 Sender_Quits_ESS_or_IBSS,
7 Due_Inactivity, AP_Overload,
8 Class_2_from_NonAuth,
9 Class_3_from_NonAuth,
10 Sender_Quits_BSS,
11 Association_requester_not_authenticated,
12 Reserved10
13};
14
15
16#define IEEE_802_11_LINK_STATUS_FAILURE_REASON_STRINGS \
17 {\
18 {reserved0, 0xff," Reserved reason "},\
19 {Unspecified, 0xff," Unspecified Reason "},\
20 {Previous_not_valid,0xff," Previous Authentication no longer valid "},\
21 {Sender_Quits_ESS_or_IBSS,0xff," Deauthenticated because sending station is leaving (has left) IBSS or ESS "},\
22 {Due_Inactivity,0xff," Disassociated due to inactivity "},\
23 {AP_Overload, 0xff," Disassociated because AP is unable to handle all currently associated stations "},\
24 {Class_2_from_NonAuth,0xff," Class 2 frame received from non-Authenticated station"},\
25 {Class_3_from_NonAuth,0xff," Class 3 frame received from non­Associated station"},\
26 {Sender_Quits_BSS,0xff," Disassociated because sending station is leaving (has left) BSS"},\
27 {Association_requester_not_authenticated,0xff," Station requesting (Re)Association is not Authenticated with responding station"},\
28 {Reserved10, 0xff," Reserved"},\
29 {0,0,NULL}\
30};
31
32
33
34struct ieee_802_11_header {
35 u_int16_tframe_control;// needs to be subtyped
36 u_int16_tduration;
37 u_int8_tmac1[6];
38 u_int8_tmac2[6];
39 u_int8_tmac3[6];
40 u_int16_tSeqCtl;
41 u_int8_tmac4[6];
42 // u_int16_tgapLen;
43 // u_int8_tgap[8];
44};
45
46
47struct ieee_802_3_header {
48
49 u_int16_tstatus;
50 u_int16_tpayload_length;
51 u_int8_tdst_mac[6];
52 u_int8_tsrc_mac[6];
53
54};
55
56#define P80211_OUI_LEN 3
57
58struct ieee_802_11_snap_header {
59
60 u_int8_t dsap; /* always 0xAA */
61 u_int8_t ssap; /* always 0xAA */
62 u_int8_t ctrl; /* always 0x03 */
63 u_int8_t oui[P80211_OUI_LEN]; /* organizational universal id */
64
65} __attribute__ ((packed));
66
67#define P80211_LLC_OUI_LEN 3
68
69struct ieee_802_11_802_1H_header {
70
71 u_int8_t dsap;
72 u_int8_t ssap; /* always 0xAA */
73 u_int8_t ctrl; /* always 0x03 */
74 u_int8_t oui[P80211_OUI_LEN]; /* organizational universal id */
75 u_int16_t unknown1; /* packet type ID fields */
76 u_int16_t unknown2; /* here is something like length in some cases */
77} __attribute__ ((packed));
78
79struct ieee_802_11_802_2_header {
80
81 u_int8_t dsap;
82 u_int8_t ssap; /* always 0xAA */
83 u_int8_t ctrl; /* always 0x03 */
84 u_int8_t oui[P80211_OUI_LEN]; /* organizational universal id */
85 u_int16_t type; /* packet type ID field */
86
87} __attribute__ ((packed));
88
89
90
91// following is incoplete and may be incorrect and need reorganization
92
93 #define ieee_802_11_frame_type_Management0x00
94 #define ieee_802_11_frame_type_Control 0x01
95 #define ieee_802_11_frame_type_Data 0x10
96 #define ieee_802_11_frame_type_Reserved 0x11
97
98 #define ieee_802_11_frame_subtype_Association_Req0x0 // Association Request
99 #define ieee_802_11_frame_subtype_Association_Resp0x1 // Association Response
100 #define ieee_802_11_frame_subtype_Reassociation_Req0x2 // Reassociation Request
101 #define ieee_802_11_frame_subtype_Reassociation_Resp0x3 // Reassociation Response
102 #define ieee_802_11_frame_subtype_Probe_Req 0x4 // Probe Request
103 #define ieee_802_11_frame_subtype_Probe_Resp 0x5 // Probe Response
104 #define ieee_802_11_frame_subtype_Beacon 0x8 // Beacon
105 #define ieee_802_11_frame_subtype_ATIM 0x9 // ATIM
106 #define ieee_802_11_frame_subtype_Disassociation 0xA // Disassociation
107 #define ieee_802_11_frame_subtype_Authentication 0xB // Authentication
108 #define ieee_802_11_frame_subtype_Deauthentication 0xC // Deauthentication
109 #define ieee_802_11_frame_subtype_PS_Poll 0xA // PS-Poll
110 #define ieee_802_11_frame_subtype_RTS 0xB // RTS
111 #define ieee_802_11_frame_subtype_CTS 0xC // CTS
112 #define ieee_802_11_frame_subtype_ACK 0xD // ACK
113 #define ieee_802_11_frame_subtype_CFEnd 0xE // CF-End
114 #define ieee_802_11_frame_subtype_CFEnd_CFAck 0xF // CF-End + CF-Ack
115 #define ieee_802_11_frame_subtype_Data 0x0 // Data
116 #define ieee_802_11_frame_subtype_Data_CFAck 0x1 // Data + CF-Ack
117 #define ieee_802_11_frame_subtype_Data_CF_Poll 0x2 // Data + CF-Poll
118 #define ieee_802_11_frame_subtype_Data_CF_AckCF_Poll 0x3 // Data + CF-Ack + CF-Poll
119 #define ieee_802_11_frame_subtype_NullFunction 0x4 // Null Function (no data)
120 #define ieee_802_11_frame_subtype_CF_Ack 0x5 // CF-Ack (no data)
121 #define ieee_802_11_frame_subtype_CF_Poll 0x6 // CF-Poll (no data)
122 #define ieee_802_11_frame_subtype_CF_AckCF_Poll 0x7 // CF-Ack + CF-Poll (no data)
123
124
125#define ieee_802_11_frame_subtype_strings {\
126 { ieee_802_11_frame_subtype_Association_Req,0xF,"f Association Request"},\
127 { ieee_802_11_frame_subtype_Association_Resp,0xF,"1 Association Response"},\
128 { ieee_802_11_frame_subtype_Reassociation_Req,0xF,"2 Reassociation Request"},\
129 { ieee_802_11_frame_subtype_Reassociation_Resp,0xF,"3 Reassociation Response"},\
130 { ieee_802_11_frame_subtype_Probe_Req ,0xF,"4 Probe Request"},\
131 { ieee_802_11_frame_subtype_Probe_Resp ,0xF,"5 Probe Response"},\
132 { ieee_802_11_frame_subtype_Beacon ,0xF,"8 Beacon"},\
133 { ieee_802_11_frame_subtype_ATIM ,0xF,"9 ATIM"},\
134 { ieee_802_11_frame_subtype_Disassociation,0xF,"A Disassociation"},\
135 { ieee_802_11_frame_subtype_Authentication,0xF,"B Authentication"},\
136 { ieee_802_11_frame_subtype_Deauthentication,0xF,"C Deauthentication"},\
137 { ieee_802_11_frame_subtype_PS_Poll ,0xF,"A PS-Poll"},\
138 { ieee_802_11_frame_subtype_RTS ,0xF,"B RTS"},\
139 { ieee_802_11_frame_subtype_CTS ,0xF,"C CTS"},\
140 { ieee_802_11_frame_subtype_ACK ,0xF,"D ACK"},\
141 { ieee_802_11_frame_subtype_CFEnd ,0xF,"E CF-End"},\
142 { ieee_802_11_frame_subtype_CFEnd_CFAck ,0xF,"F CF-End + CF-Ack"},\
143 { ieee_802_11_frame_subtype_Data ,0xF,"0 Data"},\
144 { ieee_802_11_frame_subtype_Data_CFAck ,0xF,"1 Data + CF-Ack"},\
145 { ieee_802_11_frame_subtype_Data_CFPoll ,0xF,"2 Data + CF-Poll"},\
146 { ieee_802_11_frame_subtype_Data_CFAck_CFPoll,0xF,"3 Data + CF-Ack + CF-Poll"},\
147 { ieee_802_11_frame_subtype_Null_Function ,0xF,"4 Null Function (no data)"},\
148 { ieee_802_11_frame_subtype_CFAck , 0xF,"5 CF-Ack (no data)"},\
149 { ieee_802_11_frame_subtype_CFPoll , 0xF,"6 CF-Poll (no data)"},\
150 { ieee_802_11_frame_subtype_CFAck_CFPoll,0xF,"y7 CF-Ack + CF-Poll (no data)"},\
151 { 0,0,NULL}\
152}
153struct ieee_802_11_frame_subtype_class {
154 u_int8_tsubtype;
155 u_int8_tmask;
156 u_int8_tklass;
157 u_int8_ttype;
158};
159#define ieee_802_11_frame_subtype_classes {\
160 { ieee_802_11_frame_subtype_Association_Req,0xF,2,ieee_802_11_frame_type_Management},\
161 { ieee_802_11_frame_subtype_Association_Resp,0xF,2,ieee_802_11_frame_type_Management},\
162 { ieee_802_11_frame_subtype_Reassociation_Req,0xF,2,ieee_802_11_frame_type_Management},\
163 { ieee_802_11_frame_subtype_Reassociation_Resp,0xF,2,ieee_802_11_frame_type_Management},\
164 { ieee_802_11_frame_subtype_Probe_Req ,0xF,1,ieee_802_11_frame_type_Management},\
165 { ieee_802_11_frame_subtype_Probe_Resp ,0xF,1,ieee_802_11_frame_type_Management},\
166 { ieee_802_11_frame_subtype_Beacon ,0xF,1,ieee_802_11_frame_type_Management},\
167 { ieee_802_11_frame_subtype_ATIM ,0xF,1,ieee_802_11_frame_type_Management},\
168 { ieee_802_11_frame_subtype_Disassociation,0xF,2,ieee_802_11_frame_type_Management},\
169 { ieee_802_11_frame_subtype_Authentication,0xF,1,ieee_802_11_frame_type_Management},\
170 { ieee_802_11_frame_subtype_Deauthentication,0xF,3,ieee_802_11_frame_type_Management},\
171 { ieee_802_11_frame_subtype_PS-Poll ,0xF,3,ieee_802_11_frame_type_Control},\
172 { ieee_802_11_frame_subtype_RTS ,0xF,1,ieee_802_11_frame_type_Control},\
173 { ieee_802_11_frame_subtype_CTS ,0xF,1,ieee_802_11_frame_type_Control},\
174 { ieee_802_11_frame_subtype_ACK ,0xF,1,ieee_802_11_frame_type_Control},\
175 { ieee_802_11_frame_subtype_CFEnd ,0xF,1,ieee_802_11_frame_type_Control},\
176 { ieee_802_11_frame_subtype_CFEnd_CFAck ,0xF,1,ieee_802_11_frame_type_Control},\
177 { ieee_802_11_frame_subtype_Data ,0xF,3,ieee_802_11_frame_type_Data},\
178 { ieee_802_11_frame_subtype_Data_CFAck ,0xF,3,ieee_802_11_frame_type_Data},\
179 { ieee_802_11_frame_subtype_Data_CF_Poll 0xF,3,ieee_802_11_frame_type_Data},\
180 { ieee_802_11_frame_subtype_Data_CF_AckCF_Poll,0xF,3,ieee_802_11_frame_type_Data},\
181 { ieee_802_11_frame_subtype_NullFunction 0xF,1,ieee_802_11_frame_type_Data},\
182 { ieee_802_11_frame_subtype_CF_Ack , 0xF,1,ieee_802_11_frame_type_Data},\
183 { ieee_802_11_frame_subtype_CF_Poll , 0xF,1,ieee_802_11_frame_type_Data},\
184 { ieee_802_11_frame_subtype_CF_AckCF_Poll,0xF,1,ieee_802_11_frame_type_Data},\
185 { 0,0,NULL}\
186}
187
188 #define IEEE802_11_FC_LEN2
189
190#define T_MGMT 0x0 /* management */
191#define T_CTRL 0x1 /* control */
192#define T_DATA 0x2 /* data */
193#define T_RESV 0x3 /* reserved */
194
195 #define ST_ASSOC_REQUEST 0x0
196 #define ST_ASSOC_RESPONSE 0x1
197 #define ST_REASSOC_REQUEST 0x2
198 #define ST_REASSOC_RESPONSE 0x3
199 #define ST_PROBE_REQUEST 0x4
200 #define ST_PROBE_RESPONSE 0x5
201 /* RESERVED 0x6 */
202 /* RESERVED 0x7 */
203 #define ST_BEACON 0x8
204 #define ST_ATIM 0x9
205 #define ST_DISASSOC 0xA
206 #define ST_AUTH 0xB
207 #define ST_DEAUTH 0xC
208 /* RESERVED 0xD */
209 /* RESERVED 0xE */
210 /* RESERVED 0xF */
211
212
213 #define CTRL_PS_POLL0xA
214 #define CTRL_RTS0xB
215 #define CTRL_CTS0xC
216 #define CTRL_ACK0xD
217 #define CTRL_CF_END0xE
218 #define CTRL_END_ACK0xF
219
220/*
221 * Bits in the frame control field.
222 */
223 #define FC_VERSION(fc) ((fc) & 0x3)
224 #define FC_TYPE(fc) (((fc) >> 2) & 0x3)
225 #define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF)
226 #define FC_TO_DS(fc) ((fc) & 0x0100)
227 #define FC_FROM_DS(fc) ((fc) & 0x0200)
228 #define FC_MORE_FLAG(fc)((fc) & 0x0400)
229 #define FC_RETRY(fc) ((fc) & 0x0800)
230 #define FC_POWER_MGMT(fc)((fc) & 0x1000)
231 #define FC_MORE_DATA(fc)((fc) & 0x2000)
232 #define FC_WEP(fc) ((fc) & 0x4000)
233 #define FC_ORDER(fc) ((fc) & 0x8000)
234
235
236struct ieee_802_11_mgmt_header {
237 u_int16_t fc;
238 u_int16_t duration;
239 u_int8_t da[6];
240 u_int8_t sa[6];
241 u_int8_t bssid[6];
242 u_int16_t seq_ctrl;
243};
244
245
246struct ieee_802_11_data_header {
247 u_int16_tframe_control;
248 u_int16_tduration;
249 u_int8_tmac1[6];
250 u_int8_tmac2[6];
251 u_int8_tmac3[6];
252 u_int16_tSeqCtl;
253 u_int8_tmac4[6];
254 // u_int16_tgapLen;
255 // u_int8_tgap[8];
256};
257
258 #define CAPABILITY_ESS(cap)((cap) & 0x0001)
259 #define CAPABILITY_IBSS(cap)((cap) & 0x0002)
260 #define CAPABILITY_CFP(cap)((cap) & 0x0004)
261 #define CAPABILITY_CFP_REQ(cap)((cap) & 0x0008)
262 #define CAPABILITY_PRIVACY(cap)((cap) & 0x0010)
263
264struct ssid_t {
265 u_int8_telement_id;
266 u_int8_tlength;
267 u_char ssid[33]; /* 32 + 1 for null */
268};
269
270
271struct rates_t {
272 u_int8_telement_id;
273 u_int8_tlength;
274 u_int8_trate[8];
275};
276
277
278struct challenge_t {
279 u_int8_telement_id;
280 u_int8_tlength;
281 u_int8_ttext[254]; /* 1-253 + 1 for null */
282};
283
284
285struct fh_t {
286 u_int8_telement_id;
287 u_int8_tlength;
288 u_int16_tdwell_time;
289 u_int8_thop_set;
290 u_int8_t hop_pattern;
291 u_int8_thop_index;
292};
293
294
295struct ds_t {
296 u_int8_telement_id;
297 u_int8_tlength;
298 u_int8_tchannel;
299};
300
301
302struct cf_t {
303 u_int8_telement_id;
304 u_int8_tlength;
305 u_int8_tcount;
306 u_int8_tperiod;
307 u_int16_tmax_duration;
308 u_int16_tdur_remaing;
309};
310
311
312struct tim_t {
313 u_int8_telement_id;
314 u_int8_tlength;
315 u_int8_tcount;
316 u_int8_tperiod;
317 u_int8_tbitmap_control;
318 u_int8_tbitmap[251];
319};
320
321 #define E_SSID 0
322 #define E_RATES 1
323 #define E_FH 2
324 #define E_DS 3
325 #define E_CF 4
326 #define E_TIM 5
327 #define E_IBSS 6
328 #define E_CHALLENGE 16
329 #define E_CISCO 133
330
331
332struct ieee_802_11_mgmt_body {
333 u_int8_t timestamp[8];
334 u_int16_t beacon_interval;
335 // u_int16_t listen_interval;
336 // u_int16_t status_code;
337 // u_int16_t aid;
338 // u_char ap[6];
339 // u_int16_treason_code;
340 // u_int16_tauth_alg;
341 // u_int16_tauth_trans_seq_num;
342// struct challenge_t challenge;
343 u_int16_tcapability_info;
344 struct ssid_tssid;
345 struct rates_t rates;
346 struct ds_tds;
347 struct cf_tcf;
348 struct fh_tfh;
349 struct tim_ttim;
350};
351
352
353struct ieee_802_11_data_body {
354//FIXME
355};
356
357struct ctrl_rts_t {
358 u_int16_tfc;
359 u_int16_tduration;
360 u_int8_tra[6];
361 u_int8_tta[6];
362 u_int8_tfcs[4];
363};
364
365 #define CTRL_RTS_LEN(2+2+6+6+4)
366
367struct ctrl_cts_t {
368 u_int16_tfc;
369 u_int16_tduration;
370 u_int8_tra[6];
371 u_int8_tfcs[4];
372};
373
374 #define CTRL_CTS_LEN(2+2+6+4)
375
376struct ctrl_ack_t {
377 u_int16_tfc;
378 u_int16_tduration;
379 u_int8_tra[6];
380 u_int8_tfcs[4];
381};
382
383 #define CTRL_ACK_LEN(2+2+6+4)
384
385struct ctrl_ps_poll_t {
386 u_int16_tfc;
387 u_int16_taid;
388 u_int8_tbssid[6];
389 u_int8_tta[6];
390 u_int8_tfcs[4];
391};
392
393 #define CTRL_PS_POLL_LEN(2+2+6+6+4)
394
395struct ctrl_end_t {
396 u_int16_tfc;
397 u_int16_tduration;
398 u_int8_tra[6];
399 u_int8_tbssid[6];
400 u_int8_tfcs[4];
401};
402
403 #define CTRL_END_LEN(2+2+6+6+4)
404
405struct ctrl_end_ack_t {
406 u_int16_tfc;
407 u_int16_tduration;
408 u_int8_tra[6];
409 u_int8_tbssid[6];
410 u_int8_tfcs[4];
411};
412
413 #define CTRL_END_ACK_LEN(2+2+6+6+4)
414
415 #define IV_IV(iv)((iv) & 0xFFFFFF)
416 #define IV_PAD(iv)(((iv) >> 24) & 0x3F)
417 #define IV_KEYID(iv)(((iv) >> 30) & 0x03)
418
419#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 @@
1 config LIBOPIE2NET
2 boolean "libopie2net (network and packet capturing related classes)"
3 default "n"
4 depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE
5 comment "libopie2net needs a libqpe and libopie2core"
6 depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE)
7
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 @@
1/*
2                 This file is part of the Opie Project
3
4              (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#include <opie2/onetutils.h>
33
34#include <net/if.h>
35
36#include <cstdio>
37using namespace std;
38
39/*======================================================================================
40 * OMacAddress
41 *======================================================================================*/
42
43// static initializer for broadcast and unknown MAC Adresses
44const unsigned char __broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
45const OMacAddress& OMacAddress::broadcast = OMacAddress( __broadcast );
46const unsigned char __unknown[6] = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 };
47const OMacAddress& OMacAddress::unknown = OMacAddress( __unknown );
48
49
50//TODO: Incorporate Ethernet Manufacturer database here!
51
52OMacAddress::OMacAddress( unsigned char* p )
53{
54 memcpy( _bytes, p, 6 ); // D'OH! memcpy in my sources... eeek...
55}
56
57
58OMacAddress::OMacAddress( const unsigned char* p )
59{
60 memcpy( _bytes, p, 6 );
61}
62
63
64OMacAddress::OMacAddress( struct ifreq& ifr )
65{
66 memcpy( _bytes, ifr.ifr_hwaddr.sa_data, 6 );
67}
68
69
70OMacAddress::~OMacAddress()
71{
72}
73
74
75QString OMacAddress::toString() const
76{
77 QString s;
78 s.sprintf( "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
79 _bytes[0]&0xff, _bytes[1]&0xff, _bytes[2]&0xff,
80 _bytes[3]&0xff, _bytes[4]&0xff, _bytes[5]&0xff );
81 return s;
82}
83
84
85bool operator==( const OMacAddress &m1, const OMacAddress &m2 )
86{
87 return memcmp( &m1._bytes, &m2._bytes, 6 ) == 0;
88}
89
90void dumpBytes( const unsigned char* data, int num )
91{
92 printf( "Dumping %d bytes @ %0x", num, data );
93 printf( "-------------------------------------------\n" );
94
95 for ( int i = 0; i < num; ++i )
96 {
97 printf( "%02x ", data[i] );
98 if ( !((i+1) % 32) ) printf( "\n" );
99 }
100 printf( "\n\n" );
101}
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 @@
1/*
2                 This file is part of the Opie Project
3
4              (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#ifndef ONETUTILS_H
33#define ONETUTILS_H
34
35#include <qdict.h>
36#include <qmap.h>
37#include <qstring.h>
38#include <qhostaddress.h>
39
40struct ifreq;
41
42/*======================================================================================
43 * OMacAddress
44 *======================================================================================*/
45
46class OMacAddress
47{
48 public:
49 OMacAddress( unsigned char* );
50 OMacAddress( const unsigned char* );
51 OMacAddress( struct ifreq& );
52 ~OMacAddress();
53
54 QString toString() const;
55
56 public:
57 static const OMacAddress& broadcast; // ff:ff:ff:ff:ff:ff
58 static const OMacAddress& unknown; // 44:44:44:44:44:44
59
60 private:
61 unsigned char _bytes[6];
62
63 friend bool operator==( const OMacAddress &m1, const OMacAddress &m2 );
64
65};
66
67bool operator==( const OMacAddress &m1, const OMacAddress &m2 );
68
69
70/*======================================================================================
71 * OHostAddress
72 *======================================================================================*/
73
74class OHostAddress : public QHostAddress
75{
76 public:
77 OHostAddress();
78 ~OHostAddress();
79};
80
81
82/*======================================================================================
83 * Miscellaneous
84 *======================================================================================*/
85
86/* dump bytes */
87
88void dumpBytes( const unsigned char* data, int num );
89
90/* Network to host order macros */
91
92#ifdef LBL_ALIGN
93#define EXTRACT_16BITS(p) \
94 ((u_int16_t)((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | \
95 (u_int16_t)*((const u_int8_t *)(p) + 1)))
96#define EXTRACT_32BITS(p) \
97 ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 0) << 24 | \
98 (u_int32_t)*((const u_int8_t *)(p) + 1) << 16 | \
99 (u_int32_t)*((const u_int8_t *)(p) + 2) << 8 | \
100 (u_int32_t)*((const u_int8_t *)(p) + 3)))
101#else
102#define EXTRACT_16BITS(p) \
103 ((u_int16_t)ntohs(*(const u_int16_t *)(p)))
104#define EXTRACT_32BITS(p) \
105 ((u_int32_t)ntohl(*(const u_int32_t *)(p)))
106#endif
107
108#define EXTRACT_24BITS(p) \
109 ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 0) << 16 | \
110 (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \
111 (u_int32_t)*((const u_int8_t *)(p) + 2)))
112
113/* Little endian protocol host order macros */
114#define EXTRACT_LE_8BITS(p) (*(p))
115#define EXTRACT_LE_16BITS(p) \
116 ((u_int16_t)((u_int16_t)*((const u_int8_t *)(p) + 1) << 8 | \
117 (u_int16_t)*((const u_int8_t *)(p) + 0)))
118#define EXTRACT_LE_32BITS(p) \
119 ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 3) << 24 | \
120 (u_int32_t)*((const u_int8_t *)(p) + 2) << 16 | \
121 (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \
122 (u_int32_t)*((const u_int8_t *)(p) + 0)))
123
124#endif // ONETUTILS_H
125
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 @@
1/*
2                 This file is part of the Opie Project
3              Copyright (C) 2003 by the Wellenreiter team:
4 Martin J. Muench <mjm@remote-exploit.org>
5 Max Moser <mmo@remote-exploit.org
6 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31
32*/
33
34/* OPIE */
35
36#include <opie2/onetwork.h>
37
38/* QT */
39
40#include <qfile.h>
41#include <qtextstream.h>
42
43/* UNIX */
44
45#include <arpa/inet.h>
46#include <cerrno>
47#include <cstring>
48#include <cstdlib>
49#include <math.h>
50#include <sys/ioctl.h>
51#include <sys/socket.h>
52#include <sys/types.h>
53#include <unistd.h>
54#include <linux/wireless.h>
55
56using namespace std;
57
58/*======================================================================================
59 * ONetwork
60 *======================================================================================*/
61
62ONetwork* ONetwork::_instance = 0;
63
64ONetwork::ONetwork()
65{
66 qDebug( "ONetwork::ONetwork()" );
67 synchronize();
68}
69
70void ONetwork::synchronize()
71{
72 // gather available interfaces by inspecting /proc/net/dev
73 // we could use SIOCGIFCONF here, but we aren't interested in virtual (e.g. eth0:0) devices
74
75 _interfaces.clear();
76 QString str;
77 QFile f( "/proc/net/dev" );
78 bool hasFile = f.open( IO_ReadOnly );
79 if ( !hasFile )
80 {
81 qDebug( "ONetwork: /proc/net/dev not existing. No network devices available" );
82 return;
83 }
84 QTextStream s( &f );
85 s.readLine();
86 s.readLine();
87 while ( !s.atEnd() )
88 {
89 s >> str;
90 str.truncate( str.find( ':' ) );
91 qDebug( "ONetwork: found interface '%s'", (const char*) str );
92 ONetworkInterface* iface;
93 if ( isWirelessInterface( str ) )
94 {
95 iface = new OWirelessNetworkInterface( str );
96 qDebug( "ONetwork: interface '%s' has Wireless Extensions", (const char*) str );
97 }
98 else
99 {
100 iface = new ONetworkInterface( str );
101 }
102 _interfaces.insert( str, iface );
103 s.readLine();
104 }
105}
106
107
108ONetworkInterface* ONetwork::interface( QString iface ) const
109{
110 return _interfaces[iface];
111}
112
113
114ONetwork* ONetwork::instance()
115{
116 if ( !_instance ) _instance = new ONetwork();
117 return _instance;
118}
119
120
121ONetwork::InterfaceIterator ONetwork::iterator() const
122{
123 return ONetwork::InterfaceIterator( _interfaces );
124}
125
126
127bool ONetwork::isWirelessInterface( const char* name ) const
128{
129 int sfd = socket( AF_INET, SOCK_DGRAM, 0 );
130 iwreqstruct iwr;
131 memset( &iwr, 0, sizeof( iwreqstruct ) );
132 strcpy( (char*) &iwr.ifr_name, name );
133 int result = ::ioctl( sfd, SIOCGIWNAME, &iwr );
134 if ( result == -1 )
135 qDebug( "ONetwork::ioctl(): SIOCGIWNAME failed: %d (%s)", result, strerror( errno ) );
136 else
137 qDebug( "ONetwork::ioctl(): SIOCGIWNAME ok." );
138 return ( result != -1 );
139}
140
141/*======================================================================================
142 * ONetworkInterface
143 *======================================================================================*/
144
145ONetworkInterface::ONetworkInterface( const QString& name )
146 :_name( name ), _sfd( socket( AF_INET, SOCK_DGRAM, 0 ) ), _mon( 0 )
147{
148 qDebug( "ONetworkInterface::ONetworkInterface()" );
149 init();
150}
151
152
153ifreqstruct& ONetworkInterface::ifr() const
154{
155 return _ifr;
156}
157
158
159void ONetworkInterface::init()
160{
161 qDebug( "ONetworkInterface::init()" );
162
163 memset( &_ifr, 0, sizeof( struct ifreq ) );
164
165 if ( _sfd == -1 )
166 {
167 qDebug( "ONetworkInterface::init(): Warning - can't get socket for device '%s'", (const char*) _name );
168 return;
169 }
170}
171
172
173bool ONetworkInterface::ioctl( int call, ifreqstruct& ifreq ) const
174{
175 int result = ::ioctl( _sfd, call, &ifreq );
176 if ( result == -1 )
177 qDebug( "ONetworkInterface::ioctl(): Call %d - Status: Failed: %d (%s)", call, result, strerror( errno ) );
178 else
179 qDebug( "ONetworkInterface::ioctl(): Call %d - Status: Ok.", call );
180 return ( result != -1 );
181}
182
183
184bool ONetworkInterface::ioctl( int call ) const
185{
186 strcpy( _ifr.ifr_name, (const char*) _name );
187 return ioctl( call, _ifr );
188}
189
190
191bool ONetworkInterface::isLoopback() const
192{
193 ioctl( SIOCGIFFLAGS );
194 return _ifr.ifr_flags & IFF_LOOPBACK;
195}
196
197
198bool ONetworkInterface::setUp( bool b )
199{
200 ioctl( SIOCGIFFLAGS );
201 if ( b ) _ifr.ifr_flags |= IFF_UP;
202 else _ifr.ifr_flags &= (~IFF_UP);
203 return ioctl( SIOCSIFFLAGS );
204}
205
206
207bool ONetworkInterface::isUp() const
208{
209 ioctl( SIOCGIFFLAGS );
210 return _ifr.ifr_flags & IFF_UP;
211}
212
213
214QString ONetworkInterface::ipV4Address() const
215{
216 if ( ioctl( SIOCGIFADDR ) )
217 {
218 struct sockaddr_in *sa = (struct sockaddr_in *) &_ifr.ifr_addr;
219 //FIXME: Use QHostAddress here
220 return QString( inet_ntoa( sa->sin_addr ) );
221 }
222 else
223 return "<unknown>";
224}
225
226
227OMacAddress ONetworkInterface::macAddress() const
228{
229 if ( ioctl( SIOCGIFHWADDR ) )
230 {
231 return OMacAddress( _ifr );
232 }
233 else
234 {
235 return OMacAddress::unknown;
236 }
237}
238
239
240void ONetworkInterface::setMonitoring( OMonitoringInterface* m )
241{
242 _mon = m;
243 qDebug( "ONetwork::setMonitoring(): Installed monitoring interface '%s'", (const char*) m->name() );
244}
245
246
247OMonitoringInterface* ONetworkInterface::monitoring() const
248{
249 return _mon;
250}
251
252
253const QString& ONetworkInterface::name() const
254{
255 return _name;
256}
257
258
259ONetworkInterface::~ONetworkInterface()
260{
261 qDebug( "ONetworkInterface::~ONetworkInterface()" );
262 if ( _sfd != -1 ) ::close( _sfd );
263}
264
265
266bool ONetworkInterface::setPromiscuousMode( bool b )
267{
268 ioctl( SIOCGIFFLAGS );
269 if ( b ) _ifr.ifr_flags |= IFF_PROMISC;
270 else _ifr.ifr_flags &= (~IFF_PROMISC);
271 return ioctl( SIOCSIFFLAGS );
272}
273
274
275bool ONetworkInterface::promiscuousMode() const
276{
277 ioctl( SIOCGIFFLAGS );
278 return _ifr.ifr_flags & IFF_PROMISC;
279}
280
281
282bool ONetworkInterface::isWireless() const
283{
284 return ioctl( SIOCGIWNAME );
285}
286
287
288/*======================================================================================
289 * OChannelHopper
290 *======================================================================================*/
291
292OChannelHopper::OChannelHopper( OWirelessNetworkInterface* iface )
293 :QObject( 0, "Mickey's funky hopper" ),
294 _iface( iface ), _interval( 0 ), _channel( 0 ), _tid( 0 )
295{
296}
297
298
299OChannelHopper::~OChannelHopper()
300{
301}
302
303
304void OChannelHopper::timerEvent( QTimerEvent* )
305{
306 //FIXME: Get available channels from OWirelessNetworkInterface
307 if ( --_channel < 0 ) _channel = 13;
308 _iface->setChannel( _channel );
309 qDebug( "OChannelHopper::timerEvent(): set channel %d on interface '%s'",
310 _channel, (const char*) _iface->name() );
311}
312
313
314void OChannelHopper::setInterval( int interval )
315{
316 if ( interval == _interval )
317 return;
318
319 if ( _interval )
320 killTimer( _tid );
321
322 _interval = interval;
323
324 if ( _interval )
325 {
326 _tid = startTimer( interval );
327 }
328}
329
330
331int OChannelHopper::interval() const
332{
333 return _interval;
334}
335
336
337/*======================================================================================
338 * OWirelessNetworkInterface
339 *======================================================================================*/
340
341OWirelessNetworkInterface::OWirelessNetworkInterface( const QString& name )
342 :ONetworkInterface( name ), _hopper( this )
343{
344 qDebug( "OWirelessNetworkInterface::OWirelessNetworkInterface()" );
345 init();
346}
347
348
349OWirelessNetworkInterface::~OWirelessNetworkInterface()
350{
351}
352
353
354iwreqstruct& OWirelessNetworkInterface::iwr() const
355{
356 return _iwr;
357}
358
359
360void OWirelessNetworkInterface::init()
361{
362 qDebug( "OWirelessNetworkInterface::init()" );
363
364 memset( &_iwr, 0, sizeof( struct iwreq ) );
365
366 // IEEE802.11(b) radio frequency channels
367 //FIXME: get these directly from the interface
368 //FIXME: check if these channels are off-by-one
369
370 iwrangestruct range;
371 _iwr.u.data.pointer = (char*) &range;
372 _iwr.u.data.length = sizeof( iwrangestruct );
373 if ( !wioctl( SIOCGIWRANGE ) )
374 {
375 qDebug( "OWirelessNetworkInterface::init(): SIOCGIWRANGE failed (%s)", strerror( errno ) );
376 return;
377 }
378
379 //TODO: Find out what the difference between num_channel and
380 // num_frequency is about.
381
382 for ( int i = 0; i < range.num_frequency; ++i )
383 {
384 int freq = (int) ( double( range.freq[i].m ) * pow( 10, range.freq[i].e ) / 1000000.0 );
385 _channels.insert( freq, i );
386 }
387}
388
389
390QString OWirelessNetworkInterface::associatedAP() const
391{
392 //FIXME: use OMacAddress
393 QString mac;
394
395 if ( ioctl( SIOCGIWAP ) )
396 {
397 mac.sprintf( "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
398 _ifr.ifr_hwaddr.sa_data[0]&0xff,
399 _ifr.ifr_hwaddr.sa_data[1]&0xff,
400 _ifr.ifr_hwaddr.sa_data[2]&0xff,
401 _ifr.ifr_hwaddr.sa_data[3]&0xff,
402 _ifr.ifr_hwaddr.sa_data[4]&0xff,
403 _ifr.ifr_hwaddr.sa_data[5]&0xff );
404 }
405 else
406 {
407 mac = "<Unknown>";
408 }
409 return mac;
410}
411
412
413int OWirelessNetworkInterface::channel() const
414{
415 if ( !wioctl( SIOCGIWFREQ ) )
416 {
417 return -1;
418 }
419 else
420 {
421 //FIXME: This is off-by-one !? Why?
422 return _channels[ static_cast<int>(double( _iwr.u.freq.m ) * pow( 10, _iwr.u.freq.e ) / 1000000) ];
423 }
424}
425
426
427void OWirelessNetworkInterface::setChannel( int c ) const
428{
429 if ( !_mon )
430 {
431 memset( &_iwr, 0, sizeof( iwreqstruct ) );
432 _iwr.u.freq.m = c;
433 _iwr.u.freq.e = 0;
434 wioctl( SIOCSIWFREQ );
435 }
436 else
437 {
438 _mon->setChannel( c );
439 }
440}
441
442
443double OWirelessNetworkInterface::frequency() const
444{
445 if ( !wioctl( SIOCGIWFREQ ) )
446 {
447 return -1.0;
448 }
449 else
450 {
451 return double( _iwr.u.freq.m ) * pow( 10, _iwr.u.freq.e ) / 1000000000.0;
452 }
453}
454
455
456int OWirelessNetworkInterface::channels() const
457{
458 return _channels.count();
459}
460
461
462void OWirelessNetworkInterface::setChannelHopping( int interval )
463{
464 _hopper.setInterval( interval );
465}
466
467
468int OWirelessNetworkInterface::channelHopping() const
469{
470 return _hopper.interval();
471}
472
473
474void OWirelessNetworkInterface::setMonitorMode( bool b )
475{
476 if ( _mon )
477 _mon->setEnabled( b );
478 else
479 qDebug( "ONetwork(): can't switch monitor mode without installed monitoring interface" );
480}
481
482bool OWirelessNetworkInterface::monitorMode() const
483{
484 return _mon ? _mon->enabled() : false;
485}
486
487
488QString OWirelessNetworkInterface::nickName() const
489{
490 char str[IW_ESSID_MAX_SIZE];
491 _iwr.u.data.pointer = &str[0];
492 _iwr.u.data.length = IW_ESSID_MAX_SIZE;
493 if ( !wioctl( SIOCGIWNICKN ) )
494 {
495 return "<unknown>";
496 }
497 else
498 {
499 str[_iwr.u.data.length] = 0x0; // some drivers (e.g. wlan-ng) don't zero-terminate the string
500 return str;
501 }
502}
503
504
505QString OWirelessNetworkInterface::SSID() const
506{
507 char str[IW_ESSID_MAX_SIZE];
508 _iwr.u.essid.pointer = &str[0];
509 _iwr.u.essid.length = IW_ESSID_MAX_SIZE;
510 if ( !wioctl( SIOCGIWESSID ) )
511 {
512 return "<unknown>";
513 }
514 else
515 {
516 return str;
517 }
518}
519
520
521void OWirelessNetworkInterface::setSSID( const QString& ssid )
522{
523 _iwr.u.essid.pointer = const_cast<char*>( (const char*) ssid );
524 _iwr.u.essid.length = ssid.length();
525 wioctl( SIOCSIWESSID );
526}
527
528
529bool OWirelessNetworkInterface::wioctl( int call, iwreqstruct& iwreq ) const
530{
531 int result = ::ioctl( _sfd, call, &iwreq );
532 if ( result == -1 )
533 qDebug( "ONetworkInterface::wioctl(): Call %d - Status: Failed: %d (%s)", call, result, strerror( errno ) );
534 else
535 qDebug( "ONetworkInterface::wioctl(): Call %d - Status: Ok.", call );
536 return ( result != -1 );
537}
538
539
540bool OWirelessNetworkInterface::wioctl( int call ) const
541{
542 strcpy( _iwr.ifr_name, (const char*) _name );
543 return wioctl( call, _iwr );
544}
545
546
547/*======================================================================================
548 * OMonitoringInterface
549 *======================================================================================*/
550
551OMonitoringInterface::OMonitoringInterface( ONetworkInterface* iface )
552 :_enabled( false ), _if( static_cast<OWirelessNetworkInterface*>( iface ) )
553{
554}
555
556
557OMonitoringInterface::~OMonitoringInterface()
558{
559}
560
561
562void OMonitoringInterface::setChannel( int c )
563{
564 // use standard WE channel switching protocol
565 memset( &_if->_iwr, 0, sizeof( iwreqstruct ) );
566 _if->_iwr.u.freq.m = c;
567 _if->_iwr.u.freq.e = 0;
568 _if->wioctl( SIOCSIWFREQ );
569}
570
571
572bool OMonitoringInterface::enabled() const
573{
574 return _enabled;
575}
576
577void OMonitoringInterface::setEnabled( bool b )
578{
579 // open a packet capturer here or leave this to
580 // the client code?
581
582 /*
583
584 if ( b )
585 {
586 OPacketCapturer* opcap = new OPacketCapturer();
587 opcap->open( _if->name() );
588 }
589 */
590
591 _enabled = b;
592
593}
594
595/*======================================================================================
596 * OCiscoMonitoringInterface
597 *======================================================================================*/
598
599OCiscoMonitoringInterface::OCiscoMonitoringInterface( ONetworkInterface* iface )
600 :OMonitoringInterface( iface )
601{
602 iface->setMonitoring( this );
603}
604
605
606OCiscoMonitoringInterface::~OCiscoMonitoringInterface()
607{
608}
609
610
611void OCiscoMonitoringInterface::setEnabled( bool b )
612{
613 QString fname;
614 fname.sprintf( "/proc/driver/aironet/%s", (const char*) _if->name() );
615 QFile f( fname );
616 if ( !f.exists() ) return;
617
618 if ( f.open( IO_WriteOnly ) )
619 {
620 QTextStream s( &f );
621 s << "Mode: r";
622 s << "Mode: y";
623 s << "XmitPower: 1";
624
625 OMonitoringInterface::setEnabled( b );
626
627 }
628
629 // flushing and closing will be done automatically when f goes out of scope
630}
631
632
633QString OCiscoMonitoringInterface::name() const
634{
635 return "cisco";
636}
637
638
639void OCiscoMonitoringInterface::setChannel( int )
640{
641 // cisco devices automatically switch channels when in monitor mode
642}
643
644
645/*======================================================================================
646 * OWlanNGMonitoringInterface
647 *======================================================================================*/
648
649
650OWlanNGMonitoringInterface::OWlanNGMonitoringInterface( ONetworkInterface* iface )
651 :OMonitoringInterface( iface )
652{
653 iface->setMonitoring( this );
654}
655
656
657OWlanNGMonitoringInterface::~OWlanNGMonitoringInterface()
658{
659}
660
661
662void OWlanNGMonitoringInterface::setEnabled( bool b )
663{
664 //FIXME: do nothing if its already in the same mode
665
666 QString enable = b ? "true" : "false";
667 QString cmd;
668 cmd.sprintf( "$(which wlanctl-ng) %s lnxreq_wlansniff channel=%d enable=%s", (const char*) _if->name(), 1, (const char*) enable );
669 system( cmd );
670
671 OMonitoringInterface::setEnabled( b );
672}
673
674
675QString OWlanNGMonitoringInterface::name() const
676{
677 return "wlan-ng";
678}
679
680
681void OWlanNGMonitoringInterface::setChannel( int )
682{
683 // wlan-ng devices automatically switch channels when in monitor mode
684}
685
686
687/*======================================================================================
688 * OHostAPMonitoringInterface
689 *======================================================================================*/
690
691OHostAPMonitoringInterface::OHostAPMonitoringInterface( ONetworkInterface* iface )
692 :OMonitoringInterface( iface )
693{
694 iface->setMonitoring( this );
695}
696
697OHostAPMonitoringInterface::~OHostAPMonitoringInterface()
698{
699}
700
701void OHostAPMonitoringInterface::setEnabled( bool b )
702{
703 // IW_MODE_MONITOR was introduced in Wireless Extensions Version 15
704 // Wireless Extensions < Version 15 need iwpriv commandos for monitoring
705
706 #if WIRELESS_EXT > 14
707 _if->_iwr.u.mode = IW_MODE_MONITOR;
708 _if->wioctl( SIOCSIWMODE );
709 #else
710 int* args = (int*) &_if._iwr.u.name;
711 args[0] = 2;
712 args[1] = 0;
713 _if->wioctl( SIOCDEVPRIVATE );
714 #endif
715
716 OMonitoringInterface::setEnabled( b );
717}
718
719
720QString OHostAPMonitoringInterface::name() const
721{
722 return "hostap";
723}
724
725
726/*======================================================================================
727 * OOrinocoNetworkInterface
728 *======================================================================================*/
729
730OOrinocoMonitoringInterface::OOrinocoMonitoringInterface( ONetworkInterface* iface )
731 :OMonitoringInterface( iface )
732{
733 iface->setMonitoring( this );
734}
735
736
737OOrinocoMonitoringInterface::~OOrinocoMonitoringInterface()
738{
739}
740
741
742void OOrinocoMonitoringInterface::setChannel( int c )
743{
744 // call iwpriv <device> monitor 2 <channel>
745 int* args = (int*) &_if->_iwr.u.name;
746 args[0] = 2;
747 args[1] = c;
748 _if->wioctl( SIOCIWFIRSTPRIV + 0x8 );
749}
750
751
752void OOrinocoMonitoringInterface::setEnabled( bool b )
753{
754 if ( b )
755 {
756 setChannel( 1 );
757 }
758 else
759 {
760 // call iwpriv <device> monitor 0 0
761 int* args = (int*) &_if->_iwr.u.name;
762 args[0] = 0;
763 args[1] = 0;
764 _if->wioctl( SIOCIWFIRSTPRIV + 0x8 );
765 }
766
767 OMonitoringInterface::setEnabled( b );
768}
769
770
771QString OOrinocoMonitoringInterface::name() const
772{
773 return "orinoco";
774}
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 @@
1/*
2                 This file is part of the Opie Project
3              Copyright (C) 2003 by the Wellenreiter team:
4 Martin J. Muench <mjm@remote-exploit.org>
5 Max Moser <mmo@remote-exploit.org
6 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31
32*/
33
34#ifndef ONETWORK_H
35#define ONETWORK_H
36
37/* QT */
38
39#include <qdict.h>
40#include <qmap.h>
41#include <qobject.h>
42#include <qhostaddress.h>
43
44/* OPIE */
45
46#include <opie2/onetutils.h>
47
48// ML: Yeah, I hate to include kernel headers, but it's necessary here
49// ML: Recent RedHat and MandrakePatches to the Kernel and WE broke something
50// ML: #include <net/if.h> e.g. conflicts with #include <linux/wireless.h>
51#define IFNAMSIZ 16
52#include <linux/wireless.h>
53#include <net/if.h>
54
55class ONetworkInterface;
56class OWirelessNetworkInterface;
57class OChannelHopper;
58class OMonitoringInterface;
59
60typedef struct ifreq ifreqstruct;
61typedef struct iwreq iwreqstruct;
62typedef struct iw_event iweventstruct;
63typedef struct iw_freq iwfreqstruct;
64typedef struct iw_priv_args iwprivargsstruct;
65typedef struct iw_range iwrangestruct;
66
67/*======================================================================================
68 * ONetwork
69 *======================================================================================*/
70
71class ONetwork : public QObject
72{
73 Q_OBJECT
74
75 public:
76 typedef QDict<ONetworkInterface> InterfaceMap;
77 typedef QDictIterator<ONetworkInterface> InterfaceIterator;
78
79 public:
80 static ONetwork* instance();
81 InterfaceIterator iterator() const;
82 bool isWirelessInterface( const char* ) const;
83 ONetworkInterface* interface( QString ) const;
84
85 protected:
86 ONetwork();
87 void synchronize();
88
89 private:
90 static ONetwork* _instance;
91 InterfaceMap _interfaces;
92};
93
94
95/*======================================================================================
96 * ONetworkInterface
97 *======================================================================================*/
98
99class ONetworkInterface
100{
101 friend class OMonitoringInterface;
102 friend class OCiscoMonitoringInterface;
103 friend class OWlanNGMonitoringInterface;
104 friend class OHostAPMonitoringInterface;
105 friend class OOrinocoMonitoringInterface;
106
107 public:
108 ONetworkInterface( const QString& name );
109 virtual ~ONetworkInterface();
110
111 const QString& name() const;
112 void setMonitoring( OMonitoringInterface* );
113 OMonitoringInterface* monitoring() const;
114 bool setPromiscuousMode( bool );
115 bool promiscuousMode() const;
116 bool setUp( bool );
117 bool isUp() const;
118 bool isLoopback() const;
119 bool isWireless() const;
120 QString ipV4Address() const;
121 OMacAddress macAddress() const;
122
123 protected:
124 const QString _name;
125 const int _sfd;
126 mutable ifreqstruct _ifr;
127 OMonitoringInterface* _mon;
128
129 protected:
130 ifreqstruct& ifr() const;
131 virtual void init();
132 bool ioctl( int call ) const;
133 bool ioctl( int call, ifreqstruct& ) const;
134};
135
136/*======================================================================================
137 * OChannelHopper
138 *======================================================================================*/
139
140class OChannelHopper : public QObject
141{
142 public:
143 OChannelHopper( OWirelessNetworkInterface* );
144 virtual ~OChannelHopper();
145 virtual void timerEvent( QTimerEvent* );
146 void setInterval( int );
147 int interval() const;
148
149 private:
150 OWirelessNetworkInterface* _iface;
151 int _interval;
152 int _channel;
153 int _tid;
154};
155
156
157/*======================================================================================
158 * OWirelessNetworkInterface
159 *======================================================================================*/
160
161class OWirelessNetworkInterface : public ONetworkInterface
162{
163 friend class OMonitoringInterface;
164 friend class OCiscoMonitoringInterface;
165 friend class OWlanNGMonitoringInterface;
166 friend class OHostAPMonitoringInterface;
167 friend class OOrinocoMonitoringInterface;
168
169 public:
170 enum Mode { AdHoc, Managed, Monitor };
171
172 OWirelessNetworkInterface( const QString& name );
173 virtual ~OWirelessNetworkInterface();
174
175 virtual void setChannel( int ) const;
176 virtual int channel() const;
177 virtual double frequency() const;
178 virtual int channels() const;
179 //virtual double frequency(int) const;
180
181 virtual void setMode( Mode ) {};
182 virtual bool mode() const {};
183
184 virtual void setMonitorMode( bool );
185 virtual bool monitorMode() const;
186
187 virtual void setChannelHopping( int interval );
188 virtual int channelHopping() const;
189
190 virtual void setNickName( const QString& ) {};
191 virtual QString nickName() const;
192
193 virtual bool isAssociated() const {};
194 virtual QString associatedAP() const;
195
196 virtual void setSSID( const QString& );
197 virtual QString SSID() const;
198
199 protected:
200 mutable iwreqstruct _iwr;
201 QMap<int,int> _channels;
202
203 protected:
204 virtual void init();
205 iwreqstruct& iwr() const;
206 bool wioctl( int call ) const;
207 bool wioctl( int call, iwreqstruct& ) const;
208
209 private:
210 OChannelHopper _hopper;
211};
212
213
214/*======================================================================================
215 * OMonitoringInterface
216 *======================================================================================*/
217
218
219class OMonitoringInterface
220{
221 public:
222 OMonitoringInterface();
223 OMonitoringInterface( ONetworkInterface* );
224 virtual ~OMonitoringInterface();
225
226 public:
227 virtual void setEnabled( bool );
228 virtual bool enabled() const;
229 virtual void setChannel( int );
230
231 virtual QString name() const = 0;
232
233 protected:
234 bool _enabled;
235 const OWirelessNetworkInterface* _if;
236
237};
238
239
240/*======================================================================================
241 * OCiscoMonitoring
242 *======================================================================================*/
243
244
245class OCiscoMonitoringInterface : public OMonitoringInterface
246{
247 public:
248 OCiscoMonitoringInterface( ONetworkInterface* );
249 virtual ~OCiscoMonitoringInterface();
250
251 virtual void setEnabled( bool );
252 virtual QString name() const;
253 virtual void setChannel( int );
254
255};
256
257/*======================================================================================
258 * OWlanNGMonitoringInterface
259 *======================================================================================*/
260
261class OWlanNGMonitoringInterface : public OMonitoringInterface
262{
263 public:
264 OWlanNGMonitoringInterface( ONetworkInterface* );
265 virtual ~OWlanNGMonitoringInterface();
266
267 public:
268 virtual void setEnabled( bool );
269 virtual QString name() const;
270 virtual void setChannel( int );
271
272};
273
274/*======================================================================================
275 * OHostAPMonitoringInterface
276 *======================================================================================*/
277
278class OHostAPMonitoringInterface : public OMonitoringInterface
279{
280 public:
281 OHostAPMonitoringInterface( ONetworkInterface* );
282 virtual ~OHostAPMonitoringInterface();
283
284 public:
285 virtual void setEnabled( bool );
286 virtual QString name() const;
287 };
288
289/*======================================================================================
290 * OOrinocoMonitoringInterface
291 *======================================================================================*/
292
293class OOrinocoMonitoringInterface : public OMonitoringInterface
294{
295 public:
296 OOrinocoMonitoringInterface( ONetworkInterface* );
297 virtual ~OOrinocoMonitoringInterface();
298
299 public:
300 virtual void setChannel( int );
301 virtual void setEnabled( bool );
302 virtual QString name() const;
303
304};
305
306#endif // ONETWORK_H
307
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 @@
1/*
2                 This file is part of the Opie Project
3              Copyright (C) 2003 by the Wellenreiter team:
4 Martin J. Muench <mjm@remote-exploit.org>
5 Max Moser <mmo@remote-exploit.org
6 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31
32*/
33
34/* OPIE */
35
36#include <opie2/opcap.h>
37
38/* QT */
39
40#include <qapplication.h> // don't use oapplication here (will decrease reusability in other projects)
41#include <qsocketnotifier.h>
42
43/*======================================================================================
44 * OPacket
45 *======================================================================================*/
46
47OPacket::OPacket( packetheaderstruct header, const unsigned char* data, QObject* parent )
48 :QObject( parent, "Generic" ), _hdr( header ), _data( data )
49{
50 qDebug( "OPacket::OPacket(): (Len %d, CapLen %d)" /*, ctime((const time_t*) header.ts.tv_sec)*/, header.len, header.caplen );
51
52 if ( packetCapturer()->dataLink() == DLT_EN10MB )
53 {
54 qDebug( "OPacket::OPacket(): Received Packet. Datalink = ETHERNET" );
55 new OEthernetPacket( (const struct ether_header*) data, this );
56 }
57 else
58 {
59 qDebug( "OPacket::OPacket(): Received Packet. Datalink = IEEE802.11" );
60 new OWaveLanPacket( (const struct ieee_802_11_header*) data, this );
61 }
62}
63
64
65OPacket::~OPacket()
66{
67}
68
69
70OPacketCapturer* OPacket::packetCapturer() const
71{
72 return parent()->inherits( "OPacketCapturer" ) ? static_cast<OPacketCapturer*>( parent() ) : 0;
73}
74
75
76timevalstruct OPacket::timeval() const
77{
78 return _hdr.ts;
79}
80
81
82int OPacket::caplen() const
83{
84 return _hdr.caplen;
85}
86
87
88void OPacket::dump() const
89{
90 printf( "OPacket::dump()\n" );
91 printf( "----------------\n" );
92
93 for ( int i = 0; i < _hdr.caplen; ++i )
94 {
95 printf( "%02x ", _data[i] );
96 if ( !((i+1) % 32) ) printf( "\n" );
97 }
98 printf( "\n\n" );
99}
100
101
102
103int OPacket::len() const
104{
105 return _hdr.len;
106}
107
108/*======================================================================================
109 * OEthernetPacket
110 *======================================================================================*/
111
112OEthernetPacket::OEthernetPacket( const struct ether_header* data, QObject* parent )
113 :QObject( parent, "Ethernet" ), _ether( data )
114
115{
116
117 qDebug( "Source = %s", (const char*) sourceAddress().toString() );
118 qDebug( "Destination = %s", (const char*) destinationAddress().toString() );
119
120 if ( sourceAddress() == OMacAddress::broadcast )
121 qDebug( "Source is broadcast address" );
122 if ( destinationAddress() == OMacAddress::broadcast )
123 qDebug( "Destination is broadcast address" );
124
125 switch ( type() )
126 {
127 case ETHERTYPE_IP: new OIPPacket( (const struct iphdr*) (data+1), this ); break;
128 case ETHERTYPE_ARP: { qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = ARP" ); break; }
129 case ETHERTYPE_REVARP: { qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = RARP" ); break; }
130 default: qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = UNKNOWN" );
131 }
132
133}
134
135
136OEthernetPacket::~OEthernetPacket()
137{
138}
139
140
141OMacAddress OEthernetPacket::sourceAddress() const
142{
143 return OMacAddress( _ether->ether_shost );
144}
145
146
147OMacAddress OEthernetPacket::destinationAddress() const
148{
149 return OMacAddress( _ether->ether_dhost );
150}
151
152int OEthernetPacket::type() const
153{
154 return ntohs( _ether->ether_type );
155}
156
157
158/*======================================================================================
159 * OIPPacket
160 *======================================================================================*/
161
162
163OIPPacket::OIPPacket( const struct iphdr* data, QObject* parent )
164 :QObject( parent, "IP" ), _iphdr( data )
165
166{
167 qDebug( "OIPPacket::OIPPacket(): decoding IP header..." );
168
169 //qDebug( "FromAddress: %s", (const char*) inet_ntoa( *src ) );
170 //qDebug( " ToAddress: %s", (const char*) inet_ntoa( *dst ) );
171
172 qDebug( "FromAddress: %s", (const char*) fromIPAddress().toString() );
173 qDebug( " toAddress: %s", (const char*) toIPAddress().toString() );
174
175 switch ( protocol() )
176 {
177 case IPPROTO_UDP: new OUDPPacket( (const struct udphdr*) (data+1), this ); break;
178 case IPPROTO_TCP: new OTCPPacket( (const struct tcphdr*) (data+1), this ); break;
179 default: qDebug( "OIPPacket::OIPPacket(): unknown IP protocol type = %d", protocol() );
180 }
181
182}
183
184OIPPacket::~OIPPacket()
185{
186}
187
188
189QHostAddress OIPPacket::fromIPAddress() const
190{
191 return EXTRACT_32BITS( &_iphdr->saddr );
192}
193
194
195QHostAddress OIPPacket::toIPAddress() const
196{
197 return EXTRACT_32BITS( &_iphdr->saddr );
198}
199
200
201int OIPPacket::tos() const
202{
203 return _iphdr->tos;
204}
205
206
207int OIPPacket::len() const
208{
209 return EXTRACT_16BITS( &_iphdr->tot_len );
210}
211
212
213int OIPPacket::id() const
214{
215 return EXTRACT_16BITS( &_iphdr->id );
216}
217
218
219int OIPPacket::offset() const
220{
221 return EXTRACT_16BITS( &_iphdr->frag_off );
222}
223
224
225int OIPPacket::ttl() const
226{
227 return _iphdr->ttl;
228}
229
230
231int OIPPacket::protocol() const
232{
233 return _iphdr->protocol;
234}
235
236
237int OIPPacket::checksum() const
238{
239 return EXTRACT_16BITS( &_iphdr->check );
240}
241
242/*======================================================================================
243 * OUDPPacket
244 *======================================================================================*/
245
246
247OUDPPacket::OUDPPacket( const struct udphdr* data, QObject* parent )
248 :QObject( parent, "UDP" ), _udphdr( data )
249
250{
251 qDebug( "OUDPPacket::OUDPPacket(): decoding UDP header..." );
252}
253
254OUDPPacket::~OUDPPacket()
255{
256}
257
258
259/*======================================================================================
260 * OTCPPacket
261 *======================================================================================*/
262
263
264OTCPPacket::OTCPPacket( const struct tcphdr* data, QObject* parent )
265 :QObject( parent, "TCP" ), _tcphdr( data )
266
267{
268 qDebug( "OTCPPacket::OTCPPacket(): decoding TCP header..." );
269}
270
271OTCPPacket::~OTCPPacket()
272{
273}
274
275
276/*======================================================================================
277 * OWaveLanPacket
278 *======================================================================================*/
279
280
281OWaveLanPacket::OWaveLanPacket( const struct ieee_802_11_header* data, QObject* parent )
282 :QObject( parent, "802.11" ), _wlanhdr( data )
283
284{
285 qDebug( "OWaveLanPacket::OWaveLanPacket(): decoding IEEE 802.11 header..." );
286 qDebug( "type: %0X", type() );
287 qDebug( "subType: %0X", subType() );
288 qDebug( "duration: %d", duration() );
289 qDebug( "powermanagement: %d", usesPowerManagement() );
290 qDebug( "wep: %d", usesWep() );
291 qDebug( "MAC1: %s", (const char*) macAddress1().toString() );
292 qDebug( "MAC2: %s", (const char*) macAddress2().toString() );
293 qDebug( "MAC3: %s", (const char*) macAddress3().toString() );
294 qDebug( "MAC4: %s", (const char*) macAddress4().toString() );
295
296 switch ( type() )
297 {
298 case T_MGMT: new OWaveLanManagementPacket( (const struct ieee_802_11_mgmt_header*) data, this ); break;
299 case T_DATA: new OWaveLanDataPacket( (const struct ieee_802_11_data_header*) data, this ); break;
300 //case T_CTRL: new OWaveLanControlPacket( (const struct ieee_802_11_ctrl_header*) data, this ); break;
301 default: qDebug( "OWaveLanPacket::OWaveLanPacket(): Warning: Unknown type!" );
302 }
303}
304
305OWaveLanPacket::~OWaveLanPacket()
306{
307}
308
309
310int OWaveLanPacket::duration() const
311{
312 return _wlanhdr->duration;
313}
314
315
316OMacAddress OWaveLanPacket::macAddress1() const
317{
318 return OMacAddress( _wlanhdr->mac1 );
319}
320
321
322OMacAddress OWaveLanPacket::macAddress2() const
323{
324 return OMacAddress( _wlanhdr->mac2 );
325}
326
327
328OMacAddress OWaveLanPacket::macAddress3() const
329{
330 return OMacAddress( _wlanhdr->mac3 );
331}
332
333
334OMacAddress OWaveLanPacket::macAddress4() const
335{
336 return OMacAddress( _wlanhdr->mac4 );
337}
338
339
340int OWaveLanPacket::subType() const
341{
342 return FC_SUBTYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
343}
344
345
346int OWaveLanPacket::type() const
347{
348 return FC_TYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
349}
350
351
352int OWaveLanPacket::version() const
353{
354 return FC_VERSION( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
355}
356
357
358bool OWaveLanPacket::fromDS() const
359{
360 return FC_FROM_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
361}
362
363
364bool OWaveLanPacket::toDS() const
365{
366 return FC_TO_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
367}
368
369
370bool OWaveLanPacket::usesPowerManagement() const
371{
372 return FC_POWER_MGMT( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
373}
374
375
376bool OWaveLanPacket::usesWep() const
377{
378 return FC_WEP( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
379}
380
381
382/*======================================================================================
383 * OWaveLanManagementPacket
384 *======================================================================================*/
385
386OWaveLanManagementPacket::OWaveLanManagementPacket( const struct ieee_802_11_mgmt_header* data, OWaveLanPacket* parent )
387 :QObject( parent, "802.11 Management" ), _header( data ),
388 _body( (const struct ieee_802_11_mgmt_body*) (data+1) )
389{
390 qDebug( "OWaveLanManagementPacket::OWaveLanManagementPacket(): decoding frame..." );
391
392 switch ( ((OWaveLanPacket*) this->parent() )->subType() )
393 {
394 case ST_BEACON:
395 {
396 qDebug( "TYPE: BEACON FRAME" );
397 qDebug( "ESSID: %s", (const char*) SSID() );
398 break;
399 }
400 }
401}
402
403
404OWaveLanManagementPacket::~OWaveLanManagementPacket()
405{
406}
407
408
409QString OWaveLanManagementPacket::SSID() const
410{
411 int length = _body->ssid.length;
412 if ( length > 32 ) length = 32;
413 char essid[length+1];
414 memcpy( &essid, _body->ssid.ssid, length );
415 essid[length] = 0x0;
416 return essid;
417}
418
419
420/*======================================================================================
421 * OWaveLanDataPacket
422 *======================================================================================*/
423
424OWaveLanDataPacket::OWaveLanDataPacket( const struct ieee_802_11_data_header* data, OWaveLanPacket* parent )
425 :QObject( parent, "802.11 Data" ), _header( data )
426{
427 //qDebug( "size of header = %d", sizeof( struct ieee_802_11_data_header ) );
428 //qDebug( "header: %0x", data );
429 const unsigned char* payload = (const unsigned char*) data + sizeof( struct ieee_802_11_data_header );
430 //qDebug( "payload: %0x", payload );
431
432 if (!( ( (OWaveLanPacket*) this->parent())->duration() )) payload -= 6; // compensation for missing last address
433
434 new OLLCPacket( (const struct ieee_802_11_802_2_header*) payload, this );
435}
436
437
438OWaveLanDataPacket::~OWaveLanDataPacket()
439{
440}
441
442
443/*======================================================================================
444 * OLLCPacket
445 *======================================================================================*/
446
447OLLCPacket::OLLCPacket( const struct ieee_802_11_802_2_header* data, QObject* parent )
448 :QObject( parent, "802.11 802_2" ), _header( data )
449{
450 qDebug( "OLLCPacket::OLLCPacket(): decoding frame..." );
451
452 if ( !(_header->oui[0] || _header->oui[1] || _header->oui[2]) )
453 {
454 qDebug( "OLLCPacket::OLLCPacket(): contains an encapsulated Ethernet frame (type=%04X)", EXTRACT_16BITS( &_header->type ) );
455
456 switch ( EXTRACT_16BITS( &_header->type ) ) // defined in linux/if_ether.h
457 {
458 case ETH_P_IP: new OIPPacket( (const struct iphdr*) (data+1), this ); break;
459 default: qDebug( "OLLCPacket::OLLCPacket(): Unknown Encapsulation Type" );
460 }
461
462 }
463}
464
465
466OLLCPacket::~OLLCPacket()
467{
468}
469
470/*======================================================================================
471 * OPacketCapturer
472 *======================================================================================*/
473
474OPacketCapturer::OPacketCapturer( QObject* parent, const char* name )
475 :QObject( parent, name ), _name( QString::null ), _open( false ),
476 _pch( 0 )
477{
478}
479
480
481OPacketCapturer::~OPacketCapturer()
482{
483 if ( _open )
484 {
485 qDebug( "OPacketCapturer::~OPacketCapturer(): pcap still open, autoclosing." );
486 close();
487 }
488}
489
490
491void OPacketCapturer::setBlocking( bool b )
492{
493 if ( pcap_setnonblock( _pch, 1-b, _errbuf ) != -1 )
494 {
495 qDebug( "OPacketCapturer::setBlocking(): blocking mode changed successfully." );
496 }
497 else
498 {
499 qDebug( "OPacketCapturer::setBlocking(): can't change blocking mode: %s", _errbuf );
500 }
501}
502
503
504bool OPacketCapturer::blocking() const
505{
506 int b = pcap_getnonblock( _pch, _errbuf );
507 if ( b == -1 )
508 {
509 qDebug( "OPacketCapturer::blocking(): can't get blocking mode: %s", _errbuf );
510 return -1;
511 }
512 return !b;
513}
514
515
516void OPacketCapturer::close()
517{
518 if ( _open )
519 {
520 pcap_close( _pch );
521 _open = false;
522 }
523}
524
525
526int OPacketCapturer::dataLink() const
527{
528 return pcap_datalink( _pch );
529}
530
531
532int OPacketCapturer::fileno() const
533{
534 if ( _open )
535 {
536 return pcap_fileno( _pch );
537 }
538 else
539 {
540 return -1;
541 }
542}
543
544
545OPacket* OPacketCapturer::next()
546{
547 packetheaderstruct header;
548 const unsigned char* pdata = pcap_next( _pch, &header );
549 if ( header.len )
550 return new OPacket( header, pdata, this );
551 else
552 return 0;
553}
554
555
556bool OPacketCapturer::open( const QString& name )
557{
558 if ( _open )
559 {
560 if ( name == _name ) // ignore opening an already openend device
561 {
562 return true;
563 }
564 else // close the last opened device
565 {
566 close();
567 }
568 }
569
570 _name = name;
571
572 pcap_t* handle = pcap_open_live( const_cast<char*>( (const char*) name ), 1024, 0, 0, &_errbuf[0] );
573
574 if ( handle )
575 {
576 qDebug( "OPacketCapturer::open(): libpcap opened successfully." );
577 _pch = handle;
578 _open = true;
579
580 // in case we have a qapp, create a socket notifier
581 if ( qApp )
582 {
583 QSocketNotifier* sn = new QSocketNotifier( fileno(), QSocketNotifier::Read, this );
584 connect( sn, SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) );
585 }
586
587 return true;
588 }
589 else
590 {
591 qDebug( "OPacketCapturer::open(): can't open libpcap: %s", _errbuf );
592 return false;
593 }
594
595}
596
597
598bool OPacketCapturer::isOpen() const
599{
600 return _open;
601}
602
603
604void OPacketCapturer::readyToReceive()
605{
606 qDebug( "OPacketCapturer::readyToReceive(): about to emit 'receivePacket(...)'" );
607 emit receivedPacket( next() );
608}
609
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 @@
1/*
2                 This file is part of the Opie Project
3              Copyright (C) 2003 by the Wellenreiter team:
4 Martin J. Muench <mjm@remote-exploit.org>
5 Max Moser <mmo@remote-exploit.org
6 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31
32*/
33
34#ifndef OPCAP_H
35#define OPCAP_H
36
37/* LINUX */
38extern "C" // work around a bpf/pcap conflict in recent headers
39{
40 #include <pcap.h>
41}
42#include <netinet/ether.h>
43#include <netinet/ip.h>
44#include <netinet/udp.h>
45#include <netinet/tcp.h>
46#include <time.h>
47
48/* QT */
49#include <qhostaddress.h>
50#include <qobject.h>
51#include <qstring.h>
52
53/* OPIE */
54#include <opie2/onetutils.h>
55#include "802_11_user.h"
56
57/* TYPEDEFS */
58typedef struct timeval timevalstruct;
59typedef struct pcap_pkthdr packetheaderstruct;
60
61/* FORWARDS */
62class OPacketCapturer;
63
64/*======================================================================================
65 * OPacket - A frame on the wire
66 *======================================================================================*/
67
68class OPacket : public QObject
69{
70 Q_OBJECT
71
72 public:
73 OPacket( packetheaderstruct, const unsigned char*, QObject* parent );
74 virtual ~OPacket();
75
76 timevalstruct timeval() const;
77
78 OPacketCapturer* packetCapturer() const;
79
80 int caplen() const;
81 int len() const;
82 void dump() const;
83
84 private:
85 const packetheaderstruct _hdr; // pcap packet header
86 const unsigned char* _data; // pcap packet data
87};
88
89/*======================================================================================
90 * OEthernetPacket - DLT_EN10MB frame
91 *======================================================================================*/
92
93class OEthernetPacket : public QObject
94{
95 Q_OBJECT
96
97 public:
98 OEthernetPacket( const struct ether_header*, QObject* parent = 0 );
99 virtual ~OEthernetPacket();
100
101 OMacAddress sourceAddress() const;
102 OMacAddress destinationAddress() const;
103 int type() const;
104
105 private:
106 const struct ether_header* _ether;
107};
108
109
110/*======================================================================================
111 * OWaveLanPacket - DLT_IEEE802_11 frame
112 *======================================================================================*/
113
114class OWaveLanPacket : public QObject
115{
116 Q_OBJECT
117
118 public:
119 OWaveLanPacket( const struct ieee_802_11_header*, QObject* parent = 0 );
120 virtual ~OWaveLanPacket();
121
122 int duration() const;
123 bool fromDS() const;
124 bool toDS() const;
125 virtual OMacAddress macAddress1() const;
126 virtual OMacAddress macAddress2() const;
127 virtual OMacAddress macAddress3() const;
128 virtual OMacAddress macAddress4() const;
129 bool usesPowerManagement() const;
130 int type() const;
131 int subType() const;
132 int version() const;
133 bool usesWep() const;
134
135 private:
136 const struct ieee_802_11_header* _wlanhdr;
137};
138
139
140/*======================================================================================
141 * OWaveLanManagementPacket - type: management (T_MGMT)
142 *======================================================================================*/
143
144class OWaveLanManagementPacket : public QObject
145{
146 Q_OBJECT
147
148 public:
149 OWaveLanManagementPacket( const struct ieee_802_11_mgmt_header*, OWaveLanPacket* parent = 0 );
150 virtual ~OWaveLanManagementPacket();
151
152 QString SSID() const;
153
154 private:
155 const struct ieee_802_11_mgmt_header* _header;
156 const struct ieee_802_11_mgmt_body* _body;
157};
158
159
160/*======================================================================================
161 * OWaveLanDataPacket - type: data (T_DATA)
162 *======================================================================================*/
163
164class OWaveLanDataPacket : public QObject
165{
166 Q_OBJECT
167
168 public:
169 OWaveLanDataPacket( const struct ieee_802_11_data_header*, OWaveLanPacket* parent = 0 );
170 virtual ~OWaveLanDataPacket();
171
172 private:
173 const struct ieee_802_11_data_header* _header;
174};
175
176/*======================================================================================
177 * OLLCPacket - IEEE 802.2 Link Level Control
178 *======================================================================================*/
179
180class OLLCPacket : public QObject
181{
182 Q_OBJECT
183
184 public:
185 OLLCPacket( const struct ieee_802_11_802_2_header* data, QObject* parent = 0 );
186 virtual ~OLLCPacket();
187
188 private:
189 const struct ieee_802_11_802_2_header* _header;
190};
191
192/*======================================================================================
193 * OIPPacket
194 *======================================================================================*/
195
196class OIPPacket : public QObject
197{
198 Q_OBJECT
199
200 public:
201 OIPPacket( const struct iphdr*, QObject* parent = 0 );
202 virtual ~OIPPacket();
203
204 QHostAddress fromIPAddress() const;
205 QHostAddress toIPAddress() const;
206
207 int tos() const;
208 int len() const;
209 int id() const;
210 int offset() const;
211 int ttl() const;
212 int protocol() const;
213 int checksum() const;
214
215 private:
216 const struct iphdr* _iphdr;
217};
218
219/*======================================================================================
220 * OUDPPacket
221 *======================================================================================*/
222
223class OUDPPacket : public QObject
224{
225 Q_OBJECT
226
227 public:
228 OUDPPacket( const struct udphdr*, QObject* parent = 0 );
229 virtual ~OUDPPacket();
230
231 int fromPort() const;
232 int toPort() const;
233
234 private:
235 const struct udphdr* _udphdr;
236};
237
238/*======================================================================================
239 * OTCPPacket
240 *======================================================================================*/
241
242class OTCPPacket : public QObject
243{
244 Q_OBJECT
245
246 public:
247 OTCPPacket( const struct tcphdr*, QObject* parent = 0 );
248 virtual ~OTCPPacket();
249
250 int fromPort() const;
251 int toPort() const;
252
253 private:
254 const struct tcphdr* _tcphdr;
255};
256
257
258/*======================================================================================
259 * OPacketCapturer
260 *======================================================================================*/
261
262class OPacketCapturer : public QObject
263{
264 Q_OBJECT
265
266 public:
267 OPacketCapturer( QObject* parent = 0, const char* name = 0 );
268 ~OPacketCapturer();
269
270 void setBlocking( bool );
271 bool blocking() const;
272
273 void close();
274 int dataLink() const;
275 int fileno() const;
276 OPacket* next();
277 bool open( const QString& name );
278 bool isOpen() const;
279
280 signals:
281 void receivedPacket( OPacket* );
282
283 protected slots:
284 void readyToReceive();
285
286 protected:
287 QString _name; // devicename
288 bool _open; // check this before doing pcap calls
289 pcap_t* _pch; // pcap library handle
290 mutable char _errbuf[PCAP_ERRBUF_SIZE];
291};
292
293#endif // OPCAP_H
294
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 @@
1TEMPLATE = lib
2CONFIG += qt warn_on debug
3DESTDIR = $(OPIEDIR)/lib
4HEADERS = onetutils.cpp onetwork.h opcap.h
5
6SOURCES = onetutils.cpp onetwork.cpp opcap.cpp
7INTERFACES =
8TARGET = opienet2
9VERSION = 1.8.1
10INCLUDEPATH += $(OPIEDIR)/include
11DEPENDPATH += $(OPIEDIR)/include
12LIBS += -lpcap
13
14MOC_DIR = moc
15OBJECTS_DIR = obj
16
17include ( $(OPIEDIR)/include.pro )
18
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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1 config LIBOPIE2PIM
2 boolean "libopie2pim (pim related classes)"
3 default "n"
4 depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE
5 comment "libopie2pim needs a libqpe and libopie2core"
6 depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE)
7
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 @@
1TEMPLATE = lib
2CONFIG += qt warn_on debug
3DESTDIR = $(OPIEDIR)/lib
4HEADERS =
5
6SOURCES =
7INTERFACES =
8TARGET = opiepim2
9VERSION = 1.8.1
10INCLUDEPATH += $(OPIEDIR)/include
11DEPENDPATH += $(OPIEDIR)/include
12
13MOC_DIR = moc
14OBJECTS_DIR = obj
15
16include ( $(OPIEDIR)/include.pro )
17
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 @@
1Makefile*
2moc*
3*moc
4*.o
5~*
6
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 @@
1 config LIBOPIE2UI
2 boolean "libopie2ui (user interface related classes)"
3 default "n"
4 depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE
5 comment "libopie2ui needs a libqpe and libopie2core"
6 depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE)
7
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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#include <opie2/odialog.h>
33
34int ODialog::mMarginSize = 5; // 11 like in KDialog is probably too much for PDA
35int ODialog::mSpacingSize = 2; // 6 like in KDialog is probably too much for PDA
36
37ODialog::ODialog(QWidget *parent, const char *name, bool modal, WFlags f)
38 : QDialog(parent, name, modal, f)
39{
40}
41
42int ODialog::marginHint()
43{
44 return( mMarginSize );
45}
46
47
48int ODialog::spacingHint()
49{
50 return( mSpacingSize );
51}
52
53// 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 @@
1/*
2                 This file is part of the Opie Project
3
4              (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#ifndef ODIALOG_H
33#define ODIALOG_H
34
35class QLayoutItem;
36
37#include <qdialog.h>
38
39/**
40 * Dialog with extended nonmodal support and methods for OPIE standard
41 * compliance.
42 *
43 * The @ref marginHint() and @ref spacingHint() sizes shall be used
44 * whenever you layout the interior of a dialog. One special note. If
45 * you make your own action buttons (OK, Cancel etc), the space
46 * beteween the buttons shall be @ref spacingHint(), whereas the space
47 * above, below, to the right and to the left shall be @ref marginHint().
48 * If you add a separator line above the buttons, there shall be a
49 * @ref marginHint() between the buttons and the separator and a
50 * @ref marginHint() above the separator as well.
51 *
52 * @author Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
53 */
54
55class ODialog : public QDialog
56{
57 Q_OBJECT
58
59 public:
60
61 /**
62 * Constructor.
63 *
64 * Takes the same arguments as @ref QDialog.
65 */
66 ODialog(QWidget *parent = 0, const char *name = 0,
67 bool modal = false, WFlags f = 0);
68
69 /**
70 * Return the number of pixels you shall use between a
71 * dialog edge and the outermost widget(s) according to the KDE standard.
72 **/
73 static int marginHint();
74
75 /**
76 * Return the number of pixels you shall use between
77 * widgets inside a dialog according to the KDE standard.
78 */
79 static int spacingHint();
80
81 private:
82 static int mMarginSize;
83 static int mSpacingSize;
84
85 //class ODialogPrivate;
86 //ODialogPrivate *d;
87
88};
89#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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1998, 1999, 2001, 2002 Daniel M. Duley <mosfet@kde.org>
3 (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
4 (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
5 (C) 2000 Josef Weidendorfer <weidendo@in.tum.de>
6
7Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions
9are met:
10
111. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
132. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16
17THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28*/
29
30// $Id$
31
32#include <math.h>
33
34#include <qimage.h>
35#include <stdlib.h>
36#include <iostream>
37
38#include "oimageeffect.h"
39
40#define MaxRGB 255L
41#define DegreesToRadians(x) ((x)*M_PI/180.0)
42
43using namespace std;
44
45inline unsigned int intensityValue(unsigned int color)
46{
47 return((unsigned int)((0.299*qRed(color) +
48 0.587*qGreen(color) +
49 0.1140000000000001*qBlue(color))));
50}
51
52//======================================================================
53//
54// Gradient effects
55//
56//======================================================================
57
58QImage OImageEffect::gradient(const QSize &size, const QColor &ca,
59 const QColor &cb, GradientType eff, int ncols)
60{
61 int rDiff, gDiff, bDiff;
62 int rca, gca, bca, rcb, gcb, bcb;
63
64 QImage image(size, 32);
65
66 if (size.width() == 0 || size.height() == 0) {
67#ifndef NDEBUG
68 cerr << "WARNING: OImageEffect::gradient: invalid image" << endl;
69#endif
70 return image;
71 }
72
73 register int x, y;
74
75 rDiff = (rcb = cb.red()) - (rca = ca.red());
76 gDiff = (gcb = cb.green()) - (gca = ca.green());
77 bDiff = (bcb = cb.blue()) - (bca = ca.blue());
78
79 if( eff == VerticalGradient || eff == HorizontalGradient ){
80
81 uint *p;
82 uint rgb;
83
84 register int rl = rca << 16;
85 register int gl = gca << 16;
86 register int bl = bca << 16;
87
88 if( eff == VerticalGradient ) {
89
90 int rcdelta = ((1<<16) / size.height()) * rDiff;
91 int gcdelta = ((1<<16) / size.height()) * gDiff;
92 int bcdelta = ((1<<16) / size.height()) * bDiff;
93
94 for ( y = 0; y < size.height(); y++ ) {
95 p = (uint *) image.scanLine(y);
96
97 rl += rcdelta;
98 gl += gcdelta;
99 bl += bcdelta;
100
101 rgb = qRgb( (rl>>16), (gl>>16), (bl>>16) );
102
103 for( x = 0; x < size.width(); x++ ) {
104 *p = rgb;
105 p++;
106 }
107 }
108
109 }
110 else { // must be HorizontalGradient
111
112 unsigned int *o_src = (unsigned int *)image.scanLine(0);
113 unsigned int *src = o_src;
114
115 int rcdelta = ((1<<16) / size.width()) * rDiff;
116 int gcdelta = ((1<<16) / size.width()) * gDiff;
117 int bcdelta = ((1<<16) / size.width()) * bDiff;
118
119 for( x = 0; x < size.width(); x++) {
120
121 rl += rcdelta;
122 gl += gcdelta;
123 bl += bcdelta;
124
125 *src++ = qRgb( (rl>>16), (gl>>16), (bl>>16));
126 }
127
128 src = o_src;
129
130 // Believe it or not, manually copying in a for loop is faster
131 // than calling memcpy for each scanline (on the order of ms...).
132 // I think this is due to the function call overhead (mosfet).
133
134 for (y = 1; y < size.height(); ++y) {
135
136 p = (unsigned int *)image.scanLine(y);
137 src = o_src;
138 for(x=0; x < size.width(); ++x)
139 *p++ = *src++;
140 }
141 }
142 }
143
144 else {
145
146 float rfd, gfd, bfd;
147 float rd = rca, gd = gca, bd = bca;
148
149 unsigned char *xtable[3];
150 unsigned char *ytable[3];
151
152 unsigned int w = size.width(), h = size.height();
153 xtable[0] = new unsigned char[w];
154 xtable[1] = new unsigned char[w];
155 xtable[2] = new unsigned char[w];
156 ytable[0] = new unsigned char[h];
157 ytable[1] = new unsigned char[h];
158 ytable[2] = new unsigned char[h];
159 w*=2, h*=2;
160
161 if ( eff == DiagonalGradient || eff == CrossDiagonalGradient) {
162 // Diagonal dgradient code inspired by BlackBox (mosfet)
163 // BlackBox dgradient is (C) Brad Hughes, <bhughes@tcac.net> and
164 // Mike Cole <mike@mydot.com>.
165
166 rfd = (float)rDiff/w;
167 gfd = (float)gDiff/w;
168 bfd = (float)bDiff/w;
169
170 int dir;
171 for (x = 0; x < size.width(); x++, rd+=rfd, gd+=gfd, bd+=bfd) {
172 dir = eff == DiagonalGradient? x : size.width() - x - 1;
173 xtable[0][dir] = (unsigned char) rd;
174 xtable[1][dir] = (unsigned char) gd;
175 xtable[2][dir] = (unsigned char) bd;
176 }
177 rfd = (float)rDiff/h;
178 gfd = (float)gDiff/h;
179 bfd = (float)bDiff/h;
180 rd = gd = bd = 0;
181 for (y = 0; y < size.height(); y++, rd+=rfd, gd+=gfd, bd+=bfd) {
182 ytable[0][y] = (unsigned char) rd;
183 ytable[1][y] = (unsigned char) gd;
184 ytable[2][y] = (unsigned char) bd;
185 }
186
187 for (y = 0; y < size.height(); y++) {
188 unsigned int *scanline = (unsigned int *)image.scanLine(y);
189 for (x = 0; x < size.width(); x++) {
190 scanline[x] = qRgb(xtable[0][x] + ytable[0][y],
191 xtable[1][x] + ytable[1][y],
192 xtable[2][x] + ytable[2][y]);
193 }
194 }
195 }
196
197 else if (eff == RectangleGradient ||
198 eff == PyramidGradient ||
199 eff == PipeCrossGradient ||
200 eff == EllipticGradient)
201 {
202 int rSign = rDiff>0? 1: -1;
203 int gSign = gDiff>0? 1: -1;
204 int bSign = bDiff>0? 1: -1;
205
206 rfd = (float)rDiff / size.width();
207 gfd = (float)gDiff / size.width();
208 bfd = (float)bDiff / size.width();
209
210 rd = (float)rDiff/2;
211 gd = (float)gDiff/2;
212 bd = (float)bDiff/2;
213
214 for (x = 0; x < size.width(); x++, rd-=rfd, gd-=gfd, bd-=bfd)
215 {
216 xtable[0][x] = (unsigned char) abs((int)rd);
217 xtable[1][x] = (unsigned char) abs((int)gd);
218 xtable[2][x] = (unsigned char) abs((int)bd);
219 }
220
221 rfd = (float)rDiff/size.height();
222 gfd = (float)gDiff/size.height();
223 bfd = (float)bDiff/size.height();
224
225 rd = (float)rDiff/2;
226 gd = (float)gDiff/2;
227 bd = (float)bDiff/2;
228
229 for (y = 0; y < size.height(); y++, rd-=rfd, gd-=gfd, bd-=bfd)
230 {
231 ytable[0][y] = (unsigned char) abs((int)rd);
232 ytable[1][y] = (unsigned char) abs((int)gd);
233 ytable[2][y] = (unsigned char) abs((int)bd);
234 }
235 unsigned int rgb;
236 int h = (size.height()+1)>>1;
237 for (y = 0; y < h; y++) {
238 unsigned int *sl1 = (unsigned int *)image.scanLine(y);
239 unsigned int *sl2 = (unsigned int *)image.scanLine(QMAX(size.height()-y-1, y));
240
241 int w = (size.width()+1)>>1;
242 int x2 = size.width()-1;
243
244 for (x = 0; x < w; x++, x2--) {
245 rgb = 0;
246 if (eff == PyramidGradient) {
247 rgb = qRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]),
248 gcb-gSign*(xtable[1][x]+ytable[1][y]),
249 bcb-bSign*(xtable[2][x]+ytable[2][y]));
250 }
251 if (eff == RectangleGradient) {
252 rgb = qRgb(rcb - rSign *
253 QMAX(xtable[0][x], ytable[0][y]) * 2,
254 gcb - gSign *
255 QMAX(xtable[1][x], ytable[1][y]) * 2,
256 bcb - bSign *
257 QMAX(xtable[2][x], ytable[2][y]) * 2);
258 }
259 if (eff == PipeCrossGradient) {
260 rgb = qRgb(rcb - rSign *
261 QMIN(xtable[0][x], ytable[0][y]) * 2,
262 gcb - gSign *
263 QMIN(xtable[1][x], ytable[1][y]) * 2,
264 bcb - bSign *
265 QMIN(xtable[2][x], ytable[2][y]) * 2);
266 }
267 if (eff == EllipticGradient) {
268 rgb = qRgb(rcb - rSign *
269 (int)sqrt((xtable[0][x]*xtable[0][x] +
270 ytable[0][y]*ytable[0][y])*2.0),
271 gcb - gSign *
272 (int)sqrt((xtable[1][x]*xtable[1][x] +
273 ytable[1][y]*ytable[1][y])*2.0),
274 bcb - bSign *
275 (int)sqrt((xtable[2][x]*xtable[2][x] +
276 ytable[2][y]*ytable[2][y])*2.0));
277 }
278
279 sl1[x] = sl2[x] = rgb;
280 sl1[x2] = sl2[x2] = rgb;
281 }
282 }
283 }
284
285 delete [] xtable[0];
286 delete [] xtable[1];
287 delete [] xtable[2];
288 delete [] ytable[0];
289 delete [] ytable[1];
290 delete [] ytable[2];
291 }
292
293 // dither if necessary
294 if (ncols && (QPixmap::defaultDepth() < 15 )) {
295 if ( ncols < 2 || ncols > 256 )
296 ncols = 3;
297 QColor *dPal = new QColor[ncols];
298 for (int i=0; i<ncols; i++) {
299 dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ),
300 gca + gDiff * i / ( ncols - 1 ),
301 bca + bDiff * i / ( ncols - 1 ) );
302 }
303 dither(image, dPal, ncols);
304 delete [] dPal;
305 }
306
307 return image;
308}
309
310
311// -----------------------------------------------------------------------------
312
313//CT this was (before Dirk A. Mueller's speedup changes)
314// merely the same code as in the above method, but it's supposedly
315// way less performant since it introduces a lot of supplementary tests
316// and simple math operations for the calculus of the balance.
317// (surprizingly, it isn't less performant, in the contrary :-)
318// Yes, I could have merged them, but then the excellent performance of
319// the balanced code would suffer with no other gain than a mere
320// source code and byte code size economy.
321
322QImage OImageEffect::unbalancedGradient(const QSize &size, const QColor &ca,
323 const QColor &cb, GradientType eff, int xfactor, int yfactor,
324 int ncols)
325{
326 int dir; // general parameter used for direction switches
327
328 bool _xanti = false , _yanti = false;
329
330 if (xfactor < 0) _xanti = true; // negative on X direction
331 if (yfactor < 0) _yanti = true; // negative on Y direction
332
333 xfactor = abs(xfactor);
334 yfactor = abs(yfactor);
335
336 if (!xfactor) xfactor = 1;
337 if (!yfactor) yfactor = 1;
338
339 if (xfactor > 200 ) xfactor = 200;
340 if (yfactor > 200 ) yfactor = 200;
341
342
343 // float xbal = xfactor/5000.;
344 // float ybal = yfactor/5000.;
345 float xbal = xfactor/30./size.width();
346 float ybal = yfactor/30./size.height();
347 float rat;
348
349 int rDiff, gDiff, bDiff;
350 int rca, gca, bca, rcb, gcb, bcb;
351
352 QImage image(size, 32);
353
354 if (size.width() == 0 || size.height() == 0) {
355#ifndef NDEBUG
356 cerr << "WARNING: OImageEffect::unbalancedGradient : invalid image\n";
357#endif
358 return image;
359 }
360
361 register int x, y;
362 unsigned int *scanline;
363
364 rDiff = (rcb = cb.red()) - (rca = ca.red());
365 gDiff = (gcb = cb.green()) - (gca = ca.green());
366 bDiff = (bcb = cb.blue()) - (bca = ca.blue());
367
368 if( eff == VerticalGradient || eff == HorizontalGradient){
369 QColor cRow;
370
371 uint *p;
372 uint rgbRow;
373
374 if( eff == VerticalGradient) {
375 for ( y = 0; y < size.height(); y++ ) {
376 dir = _yanti ? y : size.height() - 1 - y;
377 p = (uint *) image.scanLine(dir);
378 rat = 1 - exp( - (float)y * ybal );
379
380 cRow.setRgb( rcb - (int) ( rDiff * rat ),
381 gcb - (int) ( gDiff * rat ),
382 bcb - (int) ( bDiff * rat ) );
383
384 rgbRow = cRow.rgb();
385
386 for( x = 0; x < size.width(); x++ ) {
387 *p = rgbRow;
388 p++;
389 }
390 }
391 }
392 else {
393
394 unsigned int *src = (unsigned int *)image.scanLine(0);
395 for(x = 0; x < size.width(); x++ )
396 {
397 dir = _xanti ? x : size.width() - 1 - x;
398 rat = 1 - exp( - (float)x * xbal );
399
400 src[dir] = qRgb(rcb - (int) ( rDiff * rat ),
401 gcb - (int) ( gDiff * rat ),
402 bcb - (int) ( bDiff * rat ));
403 }
404
405 // Believe it or not, manually copying in a for loop is faster
406 // than calling memcpy for each scanline (on the order of ms...).
407 // I think this is due to the function call overhead (mosfet).
408
409 for(y = 1; y < size.height(); ++y)
410 {
411 scanline = (unsigned int *)image.scanLine(y);
412 for(x=0; x < size.width(); ++x)
413 scanline[x] = src[x];
414 }
415 }
416 }
417
418 else {
419 int w=size.width(), h=size.height();
420
421 unsigned char *xtable[3];
422 unsigned char *ytable[3];
423 xtable[0] = new unsigned char[w];
424 xtable[1] = new unsigned char[w];
425 xtable[2] = new unsigned char[w];
426 ytable[0] = new unsigned char[h];
427 ytable[1] = new unsigned char[h];
428 ytable[2] = new unsigned char[h];
429
430 if ( eff == DiagonalGradient || eff == CrossDiagonalGradient)
431 {
432 for (x = 0; x < w; x++) {
433 dir = _xanti ? x : w - 1 - x;
434 rat = 1 - exp( - (float)x * xbal );
435
436 xtable[0][dir] = (unsigned char) ( rDiff/2 * rat );
437 xtable[1][dir] = (unsigned char) ( gDiff/2 * rat );
438 xtable[2][dir] = (unsigned char) ( bDiff/2 * rat );
439 }
440
441 for (y = 0; y < h; y++) {
442 dir = _yanti ? y : h - 1 - y;
443 rat = 1 - exp( - (float)y * ybal );
444
445 ytable[0][dir] = (unsigned char) ( rDiff/2 * rat );
446 ytable[1][dir] = (unsigned char) ( gDiff/2 * rat );
447 ytable[2][dir] = (unsigned char) ( bDiff/2 * rat );
448 }
449
450 for (y = 0; y < h; y++) {
451 unsigned int *scanline = (unsigned int *)image.scanLine(y);
452 for (x = 0; x < w; x++) {
453 scanline[x] = qRgb(rcb - (xtable[0][x] + ytable[0][y]),
454 gcb - (xtable[1][x] + ytable[1][y]),
455 bcb - (xtable[2][x] + ytable[2][y]));
456 }
457 }
458 }
459
460 else if (eff == RectangleGradient ||
461 eff == PyramidGradient ||
462 eff == PipeCrossGradient ||
463 eff == EllipticGradient)
464 {
465 int rSign = rDiff>0? 1: -1;
466 int gSign = gDiff>0? 1: -1;
467 int bSign = bDiff>0? 1: -1;
468
469 for (x = 0; x < w; x++)
470 {
471 dir = _xanti ? x : w - 1 - x;
472 rat = 1 - exp( - (float)x * xbal );
473
474 xtable[0][dir] = (unsigned char) abs((int)(rDiff*(0.5-rat)));
475 xtable[1][dir] = (unsigned char) abs((int)(gDiff*(0.5-rat)));
476 xtable[2][dir] = (unsigned char) abs((int)(bDiff*(0.5-rat)));
477 }
478
479 for (y = 0; y < h; y++)
480 {
481 dir = _yanti ? y : h - 1 - y;
482
483 rat = 1 - exp( - (float)y * ybal );
484
485 ytable[0][dir] = (unsigned char) abs((int)(rDiff*(0.5-rat)));
486 ytable[1][dir] = (unsigned char) abs((int)(gDiff*(0.5-rat)));
487 ytable[2][dir] = (unsigned char) abs((int)(bDiff*(0.5-rat)));
488 }
489
490 for (y = 0; y < h; y++) {
491 unsigned int *scanline = (unsigned int *)image.scanLine(y);
492 for (x = 0; x < w; x++) {
493 if (eff == PyramidGradient)
494 {
495 scanline[x] = qRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]),
496 gcb-gSign*(xtable[1][x]+ytable[1][y]),
497 bcb-bSign*(xtable[2][x]+ytable[2][y]));
498 }
499 if (eff == RectangleGradient)
500 {
501 scanline[x] = qRgb(rcb - rSign *
502 QMAX(xtable[0][x], ytable[0][y]) * 2,
503 gcb - gSign *
504 QMAX(xtable[1][x], ytable[1][y]) * 2,
505 bcb - bSign *
506 QMAX(xtable[2][x], ytable[2][y]) * 2);
507 }
508 if (eff == PipeCrossGradient)
509 {
510 scanline[x] = qRgb(rcb - rSign *
511 QMIN(xtable[0][x], ytable[0][y]) * 2,
512 gcb - gSign *
513 QMIN(xtable[1][x], ytable[1][y]) * 2,
514 bcb - bSign *
515 QMIN(xtable[2][x], ytable[2][y]) * 2);
516 }
517 if (eff == EllipticGradient)
518 {
519 scanline[x] = qRgb(rcb - rSign *
520 (int)sqrt((xtable[0][x]*xtable[0][x] +
521 ytable[0][y]*ytable[0][y])*2.0),
522 gcb - gSign *
523 (int)sqrt((xtable[1][x]*xtable[1][x] +
524 ytable[1][y]*ytable[1][y])*2.0),
525 bcb - bSign *
526 (int)sqrt((xtable[2][x]*xtable[2][x] +
527 ytable[2][y]*ytable[2][y])*2.0));
528 }
529 }
530 }
531 }
532
533 if (ncols && (QPixmap::defaultDepth() < 15 )) {
534 if ( ncols < 2 || ncols > 256 )
535 ncols = 3;
536 QColor *dPal = new QColor[ncols];
537 for (int i=0; i<ncols; i++) {
538 dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ),
539 gca + gDiff * i / ( ncols - 1 ),
540 bca + bDiff * i / ( ncols - 1 ) );
541 }
542 dither(image, dPal, ncols);
543 delete [] dPal;
544 }
545
546 delete [] xtable[0];
547 delete [] xtable[1];
548 delete [] xtable[2];
549 delete [] ytable[0];
550 delete [] ytable[1];
551 delete [] ytable[2];
552
553 }
554
555 return image;
556}
557
558
559//======================================================================
560//
561// Intensity effects
562//
563//======================================================================
564
565
566/* This builds a 256 byte unsigned char lookup table with all
567 * the possible percent values prior to applying the effect, then uses
568 * integer math for the pixels. For any image larger than 9x9 this will be
569 * less expensive than doing a float operation on the 3 color components of
570 * each pixel. (mosfet)
571 */
572
573QImage& OImageEffect::intensity(QImage &image, float percent)
574{
575 if (image.width() == 0 || image.height() == 0) {
576#ifndef NDEBUG
577 cerr << "WARNING: OImageEffect::intensity : invalid image\n";
578#endif
579 return image;
580 }
581
582 int segColors = image.depth() > 8 ? 256 : image.numColors();
583 unsigned char *segTbl = new unsigned char[segColors];
584 int pixels = image.depth() > 8 ? image.width()*image.height() :
585 image.numColors();
586 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
587 (unsigned int *)image.colorTable();
588
589 bool brighten = (percent >= 0);
590 if(percent < 0)
591 percent = -percent;
592
593 if(brighten){ // keep overflow check out of loops
594 for(int i=0; i < segColors; ++i){
595 int tmp = (int)(i*percent);
596 if(tmp > 255)
597 tmp = 255;
598 segTbl[i] = tmp;
599 }
600 }
601 else{
602 for(int i=0; i < segColors; ++i){
603 int tmp = (int)(i*percent);
604 if(tmp < 0)
605 tmp = 0;
606 segTbl[i] = tmp;
607 }
608 }
609
610 if(brighten){ // same here
611 for(int i=0; i < pixels; ++i){
612 int r = qRed(data[i]);
613 int g = qGreen(data[i]);
614 int b = qBlue(data[i]);
615 int a = qAlpha(data[i]);
616 r = r + segTbl[r] > 255 ? 255 : r + segTbl[r];
617 g = g + segTbl[g] > 255 ? 255 : g + segTbl[g];
618 b = b + segTbl[b] > 255 ? 255 : b + segTbl[b];
619 data[i] = qRgba(r, g, b,a);
620 }
621 }
622 else{
623 for(int i=0; i < pixels; ++i){
624 int r = qRed(data[i]);
625 int g = qGreen(data[i]);
626 int b = qBlue(data[i]);
627 int a = qAlpha(data[i]);
628 r = r - segTbl[r] < 0 ? 0 : r - segTbl[r];
629 g = g - segTbl[g] < 0 ? 0 : g - segTbl[g];
630 b = b - segTbl[b] < 0 ? 0 : b - segTbl[b];
631 data[i] = qRgba(r, g, b, a);
632 }
633 }
634 delete [] segTbl;
635
636 return image;
637}
638
639QImage& OImageEffect::channelIntensity(QImage &image, float percent,
640 RGBComponent channel)
641{
642 if (image.width() == 0 || image.height() == 0) {
643#ifndef NDEBUG
644 cerr << "WARNING: OImageEffect::channelIntensity : invalid image\n";
645#endif
646 return image;
647 }
648
649 int segColors = image.depth() > 8 ? 256 : image.numColors();
650 unsigned char *segTbl = new unsigned char[segColors];
651 int pixels = image.depth() > 8 ? image.width()*image.height() :
652 image.numColors();
653 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
654 (unsigned int *)image.colorTable();
655 bool brighten = (percent >= 0);
656 if(percent < 0)
657 percent = -percent;
658
659 if(brighten){ // keep overflow check out of loops
660 for(int i=0; i < segColors; ++i){
661 int tmp = (int)(i*percent);
662 if(tmp > 255)
663 tmp = 255;
664 segTbl[i] = tmp;
665 }
666 }
667 else{
668 for(int i=0; i < segColors; ++i){
669 int tmp = (int)(i*percent);
670 if(tmp < 0)
671 tmp = 0;
672 segTbl[i] = tmp;
673 }
674 }
675
676 if(brighten){ // same here
677 if(channel == Red){ // and here ;-)
678 for(int i=0; i < pixels; ++i){
679 int c = qRed(data[i]);
680 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
681 data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i]));
682 }
683 }
684 if(channel == Green){
685 for(int i=0; i < pixels; ++i){
686 int c = qGreen(data[i]);
687 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
688 data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i]));
689 }
690 }
691 else{
692 for(int i=0; i < pixels; ++i){
693 int c = qBlue(data[i]);
694 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
695 data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i]));
696 }
697 }
698
699 }
700 else{
701 if(channel == Red){
702 for(int i=0; i < pixels; ++i){
703 int c = qRed(data[i]);
704 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
705 data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i]));
706 }
707 }
708 if(channel == Green){
709 for(int i=0; i < pixels; ++i){
710 int c = qGreen(data[i]);
711 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
712 data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i]));
713 }
714 }
715 else{
716 for(int i=0; i < pixels; ++i){
717 int c = qBlue(data[i]);
718 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
719 data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i]));
720 }
721 }
722 }
723 delete [] segTbl;
724
725 return image;
726}
727
728// Modulate an image with an RBG channel of another image
729//
730QImage& OImageEffect::modulate(QImage &image, QImage &modImage, bool reverse,
731 ModulationType type, int factor, RGBComponent channel)
732{
733 if (image.width() == 0 || image.height() == 0 ||
734 modImage.width() == 0 || modImage.height() == 0) {
735#ifndef NDEBUG
736 cerr << "WARNING: OImageEffect::modulate : invalid image\n";
737#endif
738 return image;
739 }
740
741 int r, g, b, h, s, v, a;
742 QColor clr;
743 int mod=0;
744 unsigned int x1, x2, y1, y2;
745 register int x, y;
746
747 // for image, we handle only depth 32
748 if (image.depth()<32) image = image.convertDepth(32);
749
750 // for modImage, we handle depth 8 and 32
751 if (modImage.depth()<8) modImage = modImage.convertDepth(8);
752
753 unsigned int *colorTable2 = (modImage.depth()==8) ?
754 modImage.colorTable():0;
755 unsigned int *data1, *data2;
756 unsigned char *data2b;
757 unsigned int color1, color2;
758
759 x1 = image.width(); y1 = image.height();
760 x2 = modImage.width(); y2 = modImage.height();
761
762 for (y = 0; y < (int)y1; y++) {
763 data1 = (unsigned int *) image.scanLine(y);
764 data2 = (unsigned int *) modImage.scanLine( y%y2 );
765 data2b = (unsigned char *) modImage.scanLine( y%y2 );
766
767 x=0;
768 while(x < (int)x1) {
769 color2 = (colorTable2) ? colorTable2[*data2b] : *data2;
770 if (reverse) {
771 color1 = color2;
772 color2 = *data1;
773 }
774 else
775 color1 = *data1;
776
777 if (type == Intensity || type == Contrast) {
778 r = qRed(color1);
779 g = qGreen(color1);
780 b = qBlue(color1);
781 if (channel != All) {
782 mod = (channel == Red) ? qRed(color2) :
783 (channel == Green) ? qGreen(color2) :
784 (channel == Blue) ? qBlue(color2) :
785 (channel == Gray) ? qGray(color2) : 0;
786 mod = mod*factor/50;
787 }
788
789 if (type == Intensity) {
790 if (channel == All) {
791 r += r * factor/50 * qRed(color2)/256;
792 g += g * factor/50 * qGreen(color2)/256;
793 b += b * factor/50 * qBlue(color2)/256;
794 }
795 else {
796 r += r * mod/256;
797 g += g * mod/256;
798 b += b * mod/256;
799 }
800 }
801 else { // Contrast
802 if (channel == All) {
803 r += (r-128) * factor/50 * qRed(color2)/128;
804 g += (g-128) * factor/50 * qGreen(color2)/128;
805 b += (b-128) * factor/50 * qBlue(color2)/128;
806 }
807 else {
808 r += (r-128) * mod/128;
809 g += (g-128) * mod/128;
810 b += (b-128) * mod/128;
811 }
812 }
813
814 if (r<0) r=0; if (r>255) r=255;
815 if (g<0) g=0; if (g>255) g=255;
816 if (b<0) b=0; if (b>255) b=255;
817 a = qAlpha(*data1);
818 *data1 = qRgba(r, g, b, a);
819 }
820 else if (type == Saturation || type == HueShift) {
821 clr.setRgb(color1);
822 clr.hsv(&h, &s, &v);
823 mod = (channel == Red) ? qRed(color2) :
824 (channel == Green) ? qGreen(color2) :
825 (channel == Blue) ? qBlue(color2) :
826 (channel == Gray) ? qGray(color2) : 0;
827 mod = mod*factor/50;
828
829 if (type == Saturation) {
830 s -= s * mod/256;
831 if (s<0) s=0; if (s>255) s=255;
832 }
833 else { // HueShift
834 h += mod;
835 while(h<0) h+=360;
836 h %= 360;
837 }
838
839 clr.setHsv(h, s, v);
840 a = qAlpha(*data1);
841 *data1 = clr.rgb() | ((uint)(a & 0xff) << 24);
842 }
843 data1++; data2++; data2b++; x++;
844 if ( (x%x2) ==0) { data2 -= x2; data2b -= x2; }
845 }
846 }
847 return image;
848}
849
850
851
852//======================================================================
853//
854// Blend effects
855//
856//======================================================================
857
858
859// Nice and fast direct pixel manipulation
860QImage& OImageEffect::blend(const QColor& clr, QImage& dst, float opacity)
861{
862 if (dst.width() <= 0 || dst.height() <= 0)
863 return dst;
864
865 if (opacity < 0.0 || opacity > 1.0) {
866#ifndef NDEBUG
867 cerr << "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1]\n";
868#endif
869 return dst;
870 }
871
872 int depth = dst.depth();
873 if (depth != 32)
874 dst = dst.convertDepth(32);
875
876 int pixels = dst.width() * dst.height();
877 int rcol, gcol, bcol;
878 clr.rgb(&rcol, &gcol, &bcol);
879
880#ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
881 register unsigned char *data = (unsigned char *)dst.bits() + 1;
882#else // BGRA
883 register unsigned char *data = (unsigned char *)dst.bits();
884#endif
885
886 for (register int i=0; i<pixels; i++)
887 {
888#ifdef WORDS_BIGENDIAN
889 *(data++) += (unsigned char)((rcol - *data) * opacity);
890 *(data++) += (unsigned char)((gcol - *data) * opacity);
891 *(data++) += (unsigned char)((bcol - *data) * opacity);
892#else
893 *(data++) += (unsigned char)((bcol - *data) * opacity);
894 *(data++) += (unsigned char)((gcol - *data) * opacity);
895 *(data++) += (unsigned char)((rcol - *data) * opacity);
896#endif
897 data++; // skip alpha
898 }
899 return dst;
900}
901
902// Nice and fast direct pixel manipulation
903QImage& OImageEffect::blend(QImage& src, QImage& dst, float opacity)
904{
905 if (src.width() <= 0 || src.height() <= 0)
906 return dst;
907 if (dst.width() <= 0 || dst.height() <= 0)
908 return dst;
909
910 if (src.width() != dst.width() || src.height() != dst.height()) {
911#ifndef NDEBUG
912 cerr << "WARNING: OImageEffect::blend : src and destination images are not the same size\n";
913#endif
914 return dst;
915 }
916
917 if (opacity < 0.0 || opacity > 1.0) {
918#ifndef NDEBUG
919 cerr << "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1]\n";
920#endif
921 return dst;
922 }
923
924 if (src.depth() != 32) src = src.convertDepth(32);
925 if (dst.depth() != 32) dst = dst.convertDepth(32);
926
927 int pixels = src.width() * src.height();
928#ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
929 register unsigned char *data1 = (unsigned char *)dst.bits() + 1;
930 register unsigned char *data2 = (unsigned char *)src.bits() + 1;
931#else // BGRA
932 register unsigned char *data1 = (unsigned char *)dst.bits();
933 register unsigned char *data2 = (unsigned char *)src.bits();
934#endif
935
936 for (register int i=0; i<pixels; i++)
937 {
938#ifdef WORDS_BIGENDIAN
939 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
940 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
941 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
942#else
943 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
944 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
945 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
946#endif
947 data1++; // skip alpha
948 data2++;
949 }
950
951 return dst;
952}
953
954
955QImage& OImageEffect::blend(QImage &image, float initial_intensity,
956 const QColor &bgnd, GradientType eff,
957 bool anti_dir)
958{
959 if (image.width() == 0 || image.height() == 0 || image.depth()!=32 ) {
960#ifndef NDEBUG
961 cerr << "WARNING: OImageEffect::blend : invalid image\n";
962#endif
963 return image;
964 }
965
966 int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue();
967 int r, g, b;
968 int ind;
969
970 unsigned int xi, xf, yi, yf;
971 unsigned int a;
972
973 // check the boundaries of the initial intesity param
974 float unaffected = 1;
975 if (initial_intensity > 1) initial_intensity = 1;
976 if (initial_intensity < -1) initial_intensity = -1;
977 if (initial_intensity < 0) {
978 unaffected = 1. + initial_intensity;
979 initial_intensity = 0;
980 }
981
982
983 float intensity = initial_intensity;
984 float var = 1. - initial_intensity;
985
986 if (anti_dir) {
987 initial_intensity = intensity = 1.;
988 var = -var;
989 }
990
991 register int x, y;
992
993 unsigned int *data = (unsigned int *)image.bits();
994
995 int image_width = image.width(); //Those can't change
996 int image_height = image.height();
997
998
999 if( eff == VerticalGradient || eff == HorizontalGradient ) {
1000
1001 // set the image domain to apply the effect to
1002 xi = 0, xf = image_width;
1003 yi = 0, yf = image_height;
1004 if (eff == VerticalGradient) {
1005 if (anti_dir) yf = (int)(image_height * unaffected);
1006 else yi = (int)(image_height * (1 - unaffected));
1007 }
1008 else {
1009 if (anti_dir) xf = (int)(image_width * unaffected);
1010 else xi = (int)(image_height * (1 - unaffected));
1011 }
1012
1013 var /= (eff == VerticalGradient?yf-yi:xf-xi);
1014
1015 int ind_base;
1016 for (y = yi; y < (int)yf; y++) {
1017 intensity = eff == VerticalGradient? intensity + var :
1018 initial_intensity;
1019 ind_base = image_width * y ;
1020 for (x = xi; x < (int)xf ; x++) {
1021 if (eff == HorizontalGradient) intensity += var;
1022 ind = x + ind_base;
1023 r = qRed (data[ind]) + (int)(intensity *
1024 (r_bgnd - qRed (data[ind])));
1025 g = qGreen(data[ind]) + (int)(intensity *
1026 (g_bgnd - qGreen(data[ind])));
1027 b = qBlue (data[ind]) + (int)(intensity *
1028 (b_bgnd - qBlue (data[ind])));
1029 if (r > 255) r = 255; if (r < 0 ) r = 0;
1030 if (g > 255) g = 255; if (g < 0 ) g = 0;
1031 if (b > 255) b = 255; if (b < 0 ) b = 0;
1032 a = qAlpha(data[ind]);
1033 data[ind] = qRgba(r, g, b, a);
1034 }
1035 }
1036 }
1037 else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) {
1038 float xvar = var / 2 / image_width; // / unaffected;
1039 float yvar = var / 2 / image_height; // / unaffected;
1040 float tmp;
1041
1042 for (x = 0; x < image_width ; x++) {
1043 tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1);
1044 ind = x;
1045 for (y = 0; y < image_height ; y++) {
1046 intensity = initial_intensity + tmp + yvar * y;
1047
1048 r = qRed (data[ind]) + (int)(intensity *
1049 (r_bgnd - qRed (data[ind])));
1050 g = qGreen(data[ind]) + (int)(intensity *
1051 (g_bgnd - qGreen(data[ind])));
1052 b = qBlue (data[ind]) + (int)(intensity *
1053 (b_bgnd - qBlue (data[ind])));
1054 if (r > 255) r = 255; if (r < 0 ) r = 0;
1055 if (g > 255) g = 255; if (g < 0 ) g = 0;
1056 if (b > 255) b = 255; if (b < 0 ) b = 0;
1057 a = qAlpha(data[ind]);
1058 data[ind] = qRgba(r, g, b, a);
1059
1060 ind += image_width;
1061 }
1062 }
1063 }
1064
1065 else if (eff == RectangleGradient || eff == EllipticGradient) {
1066 float xvar;
1067 float yvar;
1068
1069 for (x = 0; x < image_width / 2 + image_width % 2; x++) {
1070 xvar = var / image_width * (image_width - x*2/unaffected-1);
1071 for (y = 0; y < image_height / 2 + image_height % 2; y++) {
1072 yvar = var / image_height * (image_height - y*2/unaffected -1);
1073
1074 if (eff == RectangleGradient)
1075 intensity = initial_intensity + QMAX(xvar, yvar);
1076 else
1077 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
1078 if (intensity > 1) intensity = 1;
1079 if (intensity < 0) intensity = 0;
1080
1081 //NW
1082 ind = x + image_width * y ;
1083 r = qRed (data[ind]) + (int)(intensity *
1084 (r_bgnd - qRed (data[ind])));
1085 g = qGreen(data[ind]) + (int)(intensity *
1086 (g_bgnd - qGreen(data[ind])));
1087 b = qBlue (data[ind]) + (int)(intensity *
1088 (b_bgnd - qBlue (data[ind])));
1089 if (r > 255) r = 255; if (r < 0 ) r = 0;
1090 if (g > 255) g = 255; if (g < 0 ) g = 0;
1091 if (b > 255) b = 255; if (b < 0 ) b = 0;
1092 a = qAlpha(data[ind]);
1093 data[ind] = qRgba(r, g, b, a);
1094
1095 //NE
1096 ind = image_width - x - 1 + image_width * y ;
1097 r = qRed (data[ind]) + (int)(intensity *
1098 (r_bgnd - qRed (data[ind])));
1099 g = qGreen(data[ind]) + (int)(intensity *
1100 (g_bgnd - qGreen(data[ind])));
1101 b = qBlue (data[ind]) + (int)(intensity *
1102 (b_bgnd - qBlue (data[ind])));
1103 if (r > 255) r = 255; if (r < 0 ) r = 0;
1104 if (g > 255) g = 255; if (g < 0 ) g = 0;
1105 if (b > 255) b = 255; if (b < 0 ) b = 0;
1106 a = qAlpha(data[ind]);
1107 data[ind] = qRgba(r, g, b, a);
1108 }
1109 }
1110
1111 //CT loop is doubled because of stupid central row/column issue.
1112 // other solution?
1113 for (x = 0; x < image_width / 2; x++) {
1114 xvar = var / image_width * (image_width - x*2/unaffected-1);
1115 for (y = 0; y < image_height / 2; y++) {
1116 yvar = var / image_height * (image_height - y*2/unaffected -1);
1117
1118 if (eff == RectangleGradient)
1119 intensity = initial_intensity + QMAX(xvar, yvar);
1120 else
1121 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
1122 if (intensity > 1) intensity = 1;
1123 if (intensity < 0) intensity = 0;
1124
1125 //SW
1126 ind = x + image_width * (image_height - y -1) ;
1127 r = qRed (data[ind]) + (int)(intensity *
1128 (r_bgnd - qRed (data[ind])));
1129 g = qGreen(data[ind]) + (int)(intensity *
1130 (g_bgnd - qGreen(data[ind])));
1131 b = qBlue (data[ind]) + (int)(intensity *
1132 (b_bgnd - qBlue (data[ind])));
1133 if (r > 255) r = 255; if (r < 0 ) r = 0;
1134 if (g > 255) g = 255; if (g < 0 ) g = 0;
1135 if (b > 255) b = 255; if (b < 0 ) b = 0;
1136 a = qAlpha(data[ind]);
1137 data[ind] = qRgba(r, g, b, a);
1138
1139 //SE
1140 ind = image_width-x-1 + image_width * (image_height - y - 1) ;
1141 r = qRed (data[ind]) + (int)(intensity *
1142 (r_bgnd - qRed (data[ind])));
1143 g = qGreen(data[ind]) + (int)(intensity *
1144 (g_bgnd - qGreen(data[ind])));
1145 b = qBlue (data[ind]) + (int)(intensity *
1146 (b_bgnd - qBlue (data[ind])));
1147 if (r > 255) r = 255; if (r < 0 ) r = 0;
1148 if (g > 255) g = 255; if (g < 0 ) g = 0;
1149 if (b > 255) b = 255; if (b < 0 ) b = 0;
1150 a = qAlpha(data[ind]);
1151 data[ind] = qRgba(r, g, b, a);
1152 }
1153 }
1154 }
1155#ifndef NDEBUG
1156 else cerr << "OImageEffect::blend effect not implemented" << endl;
1157#endif
1158 return image;
1159}
1160
1161// Not very efficient as we create a third big image...
1162//
1163QImage& OImageEffect::blend(QImage &image1, QImage &image2,
1164 GradientType gt, int xf, int yf)
1165{
1166 if (image1.width() == 0 || image1.height() == 0 ||
1167 image2.width() == 0 || image2.height() == 0)
1168 return image1;
1169
1170 QImage image3;
1171
1172 image3 = OImageEffect::unbalancedGradient(image1.size(),
1173 QColor(0,0,0), QColor(255,255,255),
1174 gt, xf, yf, 0);
1175
1176 return blend(image1,image2,image3, Red); // Channel to use is arbitrary
1177}
1178
1179// Blend image2 into image1, using an RBG channel of blendImage
1180//
1181QImage& OImageEffect::blend(QImage &image1, QImage &image2,
1182 QImage &blendImage, RGBComponent channel)
1183{
1184 if (image1.width() == 0 || image1.height() == 0 ||
1185 image2.width() == 0 || image2.height() == 0 ||
1186 blendImage.width() == 0 || blendImage.height() == 0) {
1187#ifndef NDEBUG
1188 cerr << "OImageEffect::blend effect invalid image" << endl;
1189#endif
1190 return image1;
1191 }
1192
1193 int r, g, b;
1194 int ind1, ind2, ind3;
1195
1196 unsigned int x1, x2, x3, y1, y2, y3;
1197 unsigned int a;
1198
1199 register int x, y;
1200
1201 // for image1 and image2, we only handle depth 32
1202 if (image1.depth()<32) image1 = image1.convertDepth(32);
1203 if (image2.depth()<32) image2 = image2.convertDepth(32);
1204
1205 // for blendImage, we handle depth 8 and 32
1206 if (blendImage.depth()<8) blendImage = blendImage.convertDepth(8);
1207
1208 unsigned int *colorTable3 = (blendImage.depth()==8) ?
1209 blendImage.colorTable():0;
1210
1211 unsigned int *data1 = (unsigned int *)image1.bits();
1212 unsigned int *data2 = (unsigned int *)image2.bits();
1213 unsigned int *data3 = (unsigned int *)blendImage.bits();
1214 unsigned char *data3b = (unsigned char *)blendImage.bits();
1215 unsigned int color3;
1216
1217 x1 = image1.width(); y1 = image1.height();
1218 x2 = image2.width(); y2 = image2.height();
1219 x3 = blendImage.width(); y3 = blendImage.height();
1220
1221 for (y = 0; y < (int)y1; y++) {
1222 ind1 = x1*y;
1223 ind2 = x2*(y%y2);
1224 ind3 = x3*(y%y3);
1225
1226 x=0;
1227 while(x < (int)x1) {
1228 color3 = (colorTable3) ? colorTable3[data3b[ind3]] : data3[ind3];
1229
1230 a = (channel == Red) ? qRed(color3) :
1231 (channel == Green) ? qGreen(color3) :
1232 (channel == Blue) ? qBlue(color3) : qGray(color3);
1233
1234 r = (a*qRed(data1[ind1]) + (256-a)*qRed(data2[ind2]))/256;
1235 g = (a*qGreen(data1[ind1]) + (256-a)*qGreen(data2[ind2]))/256;
1236 b = (a*qBlue(data1[ind1]) + (256-a)*qBlue(data2[ind2]))/256;
1237
1238 a = qAlpha(data1[ind1]);
1239 data1[ind1] = qRgba(r, g, b, a);
1240
1241 ind1++; ind2++; ind3++; x++;
1242 if ( (x%x2) ==0) ind2 -= x2;
1243 if ( (x%x3) ==0) ind3 -= x3;
1244 }
1245 }
1246 return image1;
1247}
1248
1249
1250//======================================================================
1251//
1252// Hash effects
1253//
1254//======================================================================
1255
1256unsigned int OImageEffect::lHash(unsigned int c)
1257{
1258 unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c);
1259 unsigned char nr, ng, nb;
1260 nr =(r >> 1) + (r >> 2); nr = nr > r ? 0 : nr;
1261 ng =(g >> 1) + (g >> 2); ng = ng > g ? 0 : ng;
1262 nb =(b >> 1) + (b >> 2); nb = nb > b ? 0 : nb;
1263
1264 return qRgba(nr, ng, nb, a);
1265}
1266
1267
1268// -----------------------------------------------------------------------------
1269
1270unsigned int OImageEffect::uHash(unsigned int c)
1271{
1272 unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c);
1273 unsigned char nr, ng, nb;
1274 nr = r + (r >> 3); nr = nr < r ? ~0 : nr;
1275 ng = g + (g >> 3); ng = ng < g ? ~0 : ng;
1276 nb = b + (b >> 3); nb = nb < b ? ~0 : nb;
1277
1278 return qRgba(nr, ng, nb, a);
1279}
1280
1281
1282// -----------------------------------------------------------------------------
1283
1284QImage& OImageEffect::hash(QImage &image, Lighting lite, unsigned int spacing)
1285{
1286 if (image.width() == 0 || image.height() == 0) {
1287#ifndef NDEBUG
1288 cerr << "OImageEffect::hash effect invalid image" << endl;
1289#endif
1290 return image;
1291 }
1292
1293 register int x, y;
1294 unsigned int *data = (unsigned int *)image.bits();
1295 unsigned int ind;
1296
1297 //CT no need to do it if not enough space
1298 if ((lite == NorthLite ||
1299 lite == SouthLite)&&
1300 (unsigned)image.height() < 2+spacing) return image;
1301 if ((lite == EastLite ||
1302 lite == WestLite)&&
1303 (unsigned)image.height() < 2+spacing) return image;
1304
1305 if (lite == NorthLite || lite == SouthLite) {
1306 for (y = 0 ; y < image.height(); y = y + 2 + spacing) {
1307 for (x = 0; x < image.width(); x++) {
1308 ind = x + image.width() * y;
1309 data[ind] = lite==NorthLite?uHash(data[ind]):lHash(data[ind]);
1310
1311 ind = ind + image.width();
1312 data[ind] = lite==NorthLite?lHash(data[ind]):uHash(data[ind]);
1313 }
1314 }
1315 }
1316
1317 else if (lite == EastLite || lite == WestLite) {
1318 for (y = 0 ; y < image.height(); y++) {
1319 for (x = 0; x < image.width(); x = x + 2 + spacing) {
1320 ind = x + image.width() * y;
1321 data[ind] = lite==EastLite?uHash(data[ind]):lHash(data[ind]);
1322
1323 ind++;
1324 data[ind] = lite==EastLite?lHash(data[ind]):uHash(data[ind]);
1325 }
1326 }
1327 }
1328
1329 else if (lite == NWLite || lite == SELite) {
1330 for (y = 0 ; y < image.height(); y++) {
1331 for (x = 0;
1332 x < (int)(image.width() - ((y & 1)? 1 : 0) * spacing);
1333 x = x + 2 + spacing) {
1334 ind = x + image.width() * y + ((y & 1)? 1 : 0);
1335 data[ind] = lite==NWLite?uHash(data[ind]):lHash(data[ind]);
1336
1337 ind++;
1338 data[ind] = lite==NWLite?lHash(data[ind]):uHash(data[ind]);
1339 }
1340 }
1341 }
1342
1343 else if (lite == SWLite || lite == NELite) {
1344 for (y = 0 ; y < image.height(); y++) {
1345 for (x = 0 + ((y & 1)? 1 : 0); x < image.width(); x = x + 2 + spacing) {
1346 ind = x + image.width() * y - ((y & 1)? 1 : 0);
1347 data[ind] = lite==SWLite?uHash(data[ind]):lHash(data[ind]);
1348
1349 ind++;
1350 data[ind] = lite==SWLite?lHash(data[ind]):uHash(data[ind]);
1351 }
1352 }
1353 }
1354
1355 return image;
1356}
1357
1358
1359//======================================================================
1360//
1361// Flatten effects
1362//
1363//======================================================================
1364
1365QImage& OImageEffect::flatten(QImage &img, const QColor &ca,
1366 const QColor &cb, int ncols)
1367{
1368 if (img.width() == 0 || img.height() == 0)
1369 return img;
1370
1371 // a bitmap is easy...
1372 if (img.depth() == 1) {
1373 img.setColor(0, ca.rgb());
1374 img.setColor(1, cb.rgb());
1375 return img;
1376 }
1377
1378 int r1 = ca.red(); int r2 = cb.red();
1379 int g1 = ca.green(); int g2 = cb.green();
1380 int b1 = ca.blue(); int b2 = cb.blue();
1381 int min = 0, max = 255;
1382
1383 QRgb col;
1384
1385 // Get minimum and maximum greylevel.
1386 if (img.numColors()) {
1387 // pseudocolor
1388 for (int i = 0; i < img.numColors(); i++) {
1389 col = img.color(i);
1390 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
1391 min = QMIN(min, mean);
1392 max = QMAX(max, mean);
1393 }
1394 } else {
1395 // truecolor
1396 for (int y=0; y < img.height(); y++)
1397 for (int x=0; x < img.width(); x++) {
1398 col = img.pixel(x, y);
1399 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
1400 min = QMIN(min, mean);
1401 max = QMAX(max, mean);
1402 }
1403 }
1404
1405 // Conversion factors
1406 float sr = ((float) r2 - r1) / (max - min);
1407 float sg = ((float) g2 - g1) / (max - min);
1408 float sb = ((float) b2 - b1) / (max - min);
1409
1410
1411 // Repaint the image
1412 if (img.numColors()) {
1413 for (int i=0; i < img.numColors(); i++) {
1414 col = img.color(i);
1415 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
1416 int r = (int) (sr * (mean - min) + r1 + 0.5);
1417 int g = (int) (sg * (mean - min) + g1 + 0.5);
1418 int b = (int) (sb * (mean - min) + b1 + 0.5);
1419 img.setColor(i, qRgba(r, g, b, qAlpha(col)));
1420 }
1421 } else {
1422 for (int y=0; y < img.height(); y++)
1423 for (int x=0; x < img.width(); x++) {
1424 col = img.pixel(x, y);
1425 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
1426 int r = (int) (sr * (mean - min) + r1 + 0.5);
1427 int g = (int) (sg * (mean - min) + g1 + 0.5);
1428 int b = (int) (sb * (mean - min) + b1 + 0.5);
1429 img.setPixel(x, y, qRgba(r, g, b, qAlpha(col)));
1430 }
1431 }
1432
1433
1434 // Dither if necessary
1435 if ( (ncols <= 0) || ((img.numColors() != 0) && (img.numColors() <= ncols)))
1436 return img;
1437
1438 if (ncols == 1) ncols++;
1439 if (ncols > 256) ncols = 256;
1440
1441 QColor *pal = new QColor[ncols];
1442 sr = ((float) r2 - r1) / (ncols - 1);
1443 sg = ((float) g2 - g1) / (ncols - 1);
1444 sb = ((float) b2 - b1) / (ncols - 1);
1445
1446 for (int i=0; i<ncols; i++)
1447 pal[i] = QColor(r1 + int(sr*i), g1 + int(sg*i), b1 + int(sb*i));
1448
1449 dither(img, pal, ncols);
1450
1451 delete[] pal;
1452 return img;
1453}
1454
1455
1456//======================================================================
1457//
1458// Fade effects
1459//
1460//======================================================================
1461
1462QImage& OImageEffect::fade(QImage &img, float val, const QColor &color)
1463{
1464 if (img.width() == 0 || img.height() == 0)
1465 return img;
1466
1467 // We don't handle bitmaps
1468 if (img.depth() == 1)
1469 return img;
1470
1471 unsigned char tbl[256];
1472 for (int i=0; i<256; i++)
1473 tbl[i] = (int) (val * i + 0.5);
1474
1475 int red = color.red();
1476 int green = color.green();
1477 int blue = color.blue();
1478
1479 QRgb col;
1480 int r, g, b, cr, cg, cb;
1481
1482 if (img.depth() <= 8) {
1483 // pseudo color
1484 for (int i=0; i<img.numColors(); i++) {
1485 col = img.color(i);
1486 cr = qRed(col); cg = qGreen(col); cb = qBlue(col);
1487 if (cr > red)
1488 r = cr - tbl[cr - red];
1489 else
1490 r = cr + tbl[red - cr];
1491 if (cg > green)
1492 g = cg - tbl[cg - green];
1493 else
1494 g = cg + tbl[green - cg];
1495 if (cb > blue)
1496 b = cb - tbl[cb - blue];
1497 else
1498 b = cb + tbl[blue - cb];
1499 img.setColor(i, qRgba(r, g, b, qAlpha(col)));
1500 }
1501
1502 } else {
1503 // truecolor
1504 for (int y=0; y<img.height(); y++) {
1505 QRgb *data = (QRgb *) img.scanLine(y);
1506 for (int x=0; x<img.width(); x++) {
1507 col = *data;
1508 cr = qRed(col); cg = qGreen(col); cb = qBlue(col);
1509 if (cr > red)
1510 r = cr - tbl[cr - red];
1511 else
1512 r = cr + tbl[red - cr];
1513 if (cg > green)
1514 g = cg - tbl[cg - green];
1515 else
1516 g = cg + tbl[green - cg];
1517 if (cb > blue)
1518 b = cb - tbl[cb - blue];
1519 else
1520 b = cb + tbl[blue - cb];
1521 *data++ = qRgba(r, g, b, qAlpha(col));
1522 }
1523 }
1524 }
1525
1526 return img;
1527}
1528
1529//======================================================================
1530//
1531// Color effects
1532//
1533//======================================================================
1534
1535// This code is adapted from code (C) Rik Hemsley <rik@kde.org>
1536//
1537// The formula used (r + b + g) /3 is different from the qGray formula
1538// used by Qt. This is because our formula is much much faster. If,
1539// however, it turns out that this is producing sub-optimal images,
1540// then it will have to change (kurt)
1541//
1542// It does produce lower quality grayscale ;-) Use fast == true for the fast
1543// algorithm, false for the higher quality one (mosfet).
1544QImage& OImageEffect::toGray(QImage &img, bool fast)
1545{
1546 if (img.width() == 0 || img.height() == 0)
1547 return img;
1548
1549 if(fast){
1550 if (img.depth() == 32) {
1551 register uchar * r(img.bits());
1552 register uchar * g(img.bits() + 1);
1553 register uchar * b(img.bits() + 2);
1554
1555 uchar * end(img.bits() + img.numBytes());
1556
1557 while (r != end) {
1558
1559 *r = *g = *b = (((*r + *g) >> 1) + *b) >> 1; // (r + b + g) / 3
1560
1561 r += 4;
1562 g += 4;
1563 b += 4;
1564 }
1565 }
1566 else
1567 {
1568 for (int i = 0; i < img.numColors(); i++)
1569 {
1570 register uint r = qRed(img.color(i));
1571 register uint g = qGreen(img.color(i));
1572 register uint b = qBlue(img.color(i));
1573
1574 register uint gray = (((r + g) >> 1) + b) >> 1;
1575 img.setColor(i, qRgba(gray, gray, gray, qAlpha(img.color(i))));
1576 }
1577 }
1578 }
1579 else{
1580 int pixels = img.depth() > 8 ? img.width()*img.height() :
1581 img.numColors();
1582 unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
1583 (unsigned int *)img.colorTable();
1584 int val, i;
1585 for(i=0; i < pixels; ++i){
1586 val = qGray(data[i]);
1587 data[i] = qRgba(val, val, val, qAlpha(data[i]));
1588 }
1589 }
1590 return img;
1591}
1592
1593// CT 29Jan2000 - desaturation algorithms
1594QImage& OImageEffect::desaturate(QImage &img, float desat)
1595{
1596 if (img.width() == 0 || img.height() == 0)
1597 return img;
1598
1599 if (desat < 0) desat = 0.;
1600 if (desat > 1) desat = 1.;
1601 int pixels = img.depth() > 8 ? img.width()*img.height() :
1602 img.numColors();
1603 unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
1604 (unsigned int *)img.colorTable();
1605 int h, s, v, i;
1606 QColor clr; // keep constructor out of loop (mosfet)
1607 for(i=0; i < pixels; ++i){
1608 clr.setRgb(data[i]);
1609 clr.hsv(&h, &s, &v);
1610 clr.setHsv(h, (int)(s * (1. - desat)), v);
1611 data[i] = clr.rgb();
1612 }
1613 return img;
1614}
1615
1616// Contrast stuff (mosfet)
1617QImage& OImageEffect::contrast(QImage &img, int c)
1618{
1619 if (img.width() == 0 || img.height() == 0)
1620 return img;
1621
1622 if(c > 255)
1623 c = 255;
1624 if(c < -255)
1625 c = -255;
1626 int pixels = img.depth() > 8 ? img.width()*img.height() :
1627 img.numColors();
1628 unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
1629 (unsigned int *)img.colorTable();
1630 int i, r, g, b;
1631 for(i=0; i < pixels; ++i){
1632 r = qRed(data[i]);
1633 g = qGreen(data[i]);
1634 b = qBlue(data[i]);
1635 if(qGray(data[i]) <= 127){
1636 if(r - c <= 255)
1637 r -= c;
1638 if(g - c <= 255)
1639 g -= c;
1640 if(b - c <= 255)
1641 b -= c;
1642 }
1643 else{
1644 if(r + c <= 255)
1645 r += c;
1646 if(g + c <= 255)
1647 g += c;
1648 if(b + c <= 255)
1649 b += c;
1650 }
1651 data[i] = qRgba(r, g, b, qAlpha(data[i]));
1652 }
1653 return(img);
1654}
1655
1656//======================================================================
1657//
1658// Dithering effects
1659//
1660//======================================================================
1661
1662// adapted from kFSDither (C) 1997 Martin Jones (mjones@kde.org)
1663//
1664// Floyd-Steinberg dithering
1665// Ref: Bitmapped Graphics Programming in C++
1666// Marv Luse, Addison-Wesley Publishing, 1993.
1667QImage& OImageEffect::dither(QImage &img, const QColor *palette, int size)
1668{
1669 if (img.width() == 0 || img.height() == 0 ||
1670 palette == 0 || img.depth() <= 8)
1671 return img;
1672
1673 QImage dImage( img.width(), img.height(), 8, size );
1674 int i;
1675
1676 dImage.setNumColors( size );
1677 for ( i = 0; i < size; i++ )
1678 dImage.setColor( i, palette[ i ].rgb() );
1679
1680 int *rerr1 = new int [ img.width() * 2 ];
1681 int *gerr1 = new int [ img.width() * 2 ];
1682 int *berr1 = new int [ img.width() * 2 ];
1683
1684 memset( rerr1, 0, sizeof( int ) * img.width() * 2 );
1685 memset( gerr1, 0, sizeof( int ) * img.width() * 2 );
1686 memset( berr1, 0, sizeof( int ) * img.width() * 2 );
1687
1688 int *rerr2 = rerr1 + img.width();
1689 int *gerr2 = gerr1 + img.width();
1690 int *berr2 = berr1 + img.width();
1691
1692 for ( int j = 0; j < img.height(); j++ )
1693 {
1694 uint *ip = (uint * )img.scanLine( j );
1695 uchar *dp = dImage.scanLine( j );
1696
1697 for ( i = 0; i < img.width(); i++ )
1698 {
1699 rerr1[i] = rerr2[i] + qRed( *ip );
1700 rerr2[i] = 0;
1701 gerr1[i] = gerr2[i] + qGreen( *ip );
1702 gerr2[i] = 0;
1703 berr1[i] = berr2[i] + qBlue( *ip );
1704 berr2[i] = 0;
1705 ip++;
1706 }
1707
1708 *dp++ = nearestColor( rerr1[0], gerr1[0], berr1[0], palette, size );
1709
1710 for ( i = 1; i < img.width()-1; i++ )
1711 {
1712 int indx = nearestColor( rerr1[i], gerr1[i], berr1[i], palette, size );
1713 *dp = indx;
1714
1715 int rerr = rerr1[i];
1716 rerr -= palette[indx].red();
1717 int gerr = gerr1[i];
1718 gerr -= palette[indx].green();
1719 int berr = berr1[i];
1720 berr -= palette[indx].blue();
1721
1722 // diffuse red error
1723 rerr1[ i+1 ] += ( rerr * 7 ) >> 4;
1724 rerr2[ i-1 ] += ( rerr * 3 ) >> 4;
1725 rerr2[ i ] += ( rerr * 5 ) >> 4;
1726 rerr2[ i+1 ] += ( rerr ) >> 4;
1727
1728 // diffuse green error
1729 gerr1[ i+1 ] += ( gerr * 7 ) >> 4;
1730 gerr2[ i-1 ] += ( gerr * 3 ) >> 4;
1731 gerr2[ i ] += ( gerr * 5 ) >> 4;
1732 gerr2[ i+1 ] += ( gerr ) >> 4;
1733
1734 // diffuse red error
1735 berr1[ i+1 ] += ( berr * 7 ) >> 4;
1736 berr2[ i-1 ] += ( berr * 3 ) >> 4;
1737 berr2[ i ] += ( berr * 5 ) >> 4;
1738 berr2[ i+1 ] += ( berr ) >> 4;
1739
1740 dp++;
1741 }
1742
1743 *dp = nearestColor( rerr1[i], gerr1[i], berr1[i], palette, size );
1744 }
1745
1746 delete [] rerr1;
1747 delete [] gerr1;
1748 delete [] berr1;
1749
1750 img = dImage;
1751 return img;
1752}
1753
1754int OImageEffect::nearestColor( int r, int g, int b, const QColor *palette, int size )
1755{
1756 if (palette == 0)
1757 return 0;
1758
1759 int dr = palette[0].red() - r;
1760 int dg = palette[0].green() - g;
1761 int db = palette[0].blue() - b;
1762
1763 int minDist = dr*dr + dg*dg + db*db;
1764 int nearest = 0;
1765
1766 for (int i = 1; i < size; i++ )
1767 {
1768 dr = palette[i].red() - r;
1769 dg = palette[i].green() - g;
1770 db = palette[i].blue() - b;
1771
1772 int dist = dr*dr + dg*dg + db*db;
1773
1774 if ( dist < minDist )
1775 {
1776 minDist = dist;
1777 nearest = i;
1778 }
1779 }
1780
1781 return nearest;
1782}
1783
1784bool OImageEffect::blend(
1785 const QImage & upper,
1786 const QImage & lower,
1787 QImage & output
1788)
1789{
1790 if (
1791 upper.width() > lower.width() ||
1792 upper.height() > lower.height() ||
1793 upper.depth() != 32 ||
1794 lower.depth() != 32
1795 )
1796 {
1797#ifndef NDEBUG
1798 cerr << "OImageEffect::blend : Sizes not correct\n" ;
1799#endif
1800 return false;
1801 }
1802
1803 output = lower.copy();
1804
1805 register uchar *i, *o;
1806 register int a;
1807 register int col;
1808 register int w = upper.width();
1809 int row(upper.height() - 1);
1810
1811 do {
1812
1813 i = upper.scanLine(row);
1814 o = output.scanLine(row);
1815
1816 col = w << 2;
1817 --col;
1818
1819 do {
1820
1821 while (!(a = i[col]) && (col != 3)) {
1822 --col; --col; --col; --col;
1823 }
1824
1825 --col;
1826 o[col] += ((i[col] - o[col]) * a) >> 8;
1827
1828 --col;
1829 o[col] += ((i[col] - o[col]) * a) >> 8;
1830
1831 --col;
1832 o[col] += ((i[col] - o[col]) * a) >> 8;
1833
1834 } while (col--);
1835
1836 } while (row--);
1837
1838 return true;
1839}
1840
1841#if 0
1842// Not yet...
1843bool OImageEffect::blend(
1844 const QImage & upper,
1845 const QImage & lower,
1846 QImage & output,
1847 const QRect & destRect
1848)
1849{
1850 output = lower.copy();
1851 return output;
1852}
1853
1854#endif
1855
1856bool OImageEffect::blend(
1857 int &x, int &y,
1858 const QImage & upper,
1859 const QImage & lower,
1860 QImage & output
1861)
1862{
1863 int cx=0, cy=0, cw=upper.width(), ch=upper.height();
1864
1865 if ( upper.width() + x > lower.width() ||
1866 upper.height() + y > lower.height() ||
1867 x < 0 || y < 0 ||
1868 upper.depth() != 32 || lower.depth() != 32 )
1869 {
1870 if ( x > lower.width() || y > lower.height() ) return false;
1871 if ( upper.width()<=0 || upper.height() <= 0 ) return false;
1872 if ( lower.width()<=0 || lower.height() <= 0 ) return false;
1873
1874 if (x<0) {cx=-x; cw+=x; x=0; };
1875 if (cw + x > lower.width()) { cw=lower.width()-x; };
1876 if (y<0) {cy=-y; ch+=y; y=0; };
1877 if (ch + y > lower.height()) { ch=lower.height()-y; };
1878
1879 if ( cx >= upper.width() || cy >= upper.height() ) return true;
1880 if ( cw <= 0 || ch <= 0 ) return true;
1881 }
1882
1883 output.create(cw,ch,32);
1884// output.setAlphaBuffer(true); // I should do some benchmarks to see if
1885 // this is worth the effort
1886
1887 register QRgb *i, *o, *b;
1888
1889 register int a;
1890 register int j,k;
1891 for (j=0; j<ch; j++)
1892 {
1893 b=reinterpret_cast<QRgb *>(&lower.scanLine(y+j) [ (x+cw) << 2 ]);
1894 i=reinterpret_cast<QRgb *>(&upper.scanLine(cy+j)[ (cx+cw) << 2 ]);
1895 o=reinterpret_cast<QRgb *>(&output.scanLine(j) [ cw << 2 ]);
1896
1897 k=cw-1;
1898 --b; --i; --o;
1899 do
1900 {
1901 while ( !(a=qAlpha(*i)) && k>0 )
1902 {
1903 i--;
1904 //*o=0;
1905 *o=*b;
1906 --o; --b;
1907 k--;
1908 };
1909// *o=0xFF;
1910 *o = qRgb(qRed(*b) + (((qRed(*i) - qRed(*b)) * a) >> 8),
1911 qGreen(*b) + (((qGreen(*i) - qGreen(*b)) * a) >> 8),
1912 qBlue(*b) + (((qBlue(*i) - qBlue(*b)) * a) >> 8));
1913 --i; --o; --b;
1914 } while (k--);
1915 }
1916
1917 return true;
1918}
1919
1920bool OImageEffect::blendOnLower(
1921 int x, int y,
1922 const QImage & upper,
1923 const QImage & lower
1924)
1925{
1926 int cx=0, cy=0, cw=upper.width(), ch=upper.height();
1927
1928 if ( upper.depth() != 32 || lower.depth() != 32 ) return false;
1929 if ( x + cw > lower.width() ||
1930 y + ch > lower.height() ||
1931 x < 0 || y < 0 )
1932 {
1933 if ( x > lower.width() || y > lower.height() ) return true;
1934 if ( upper.width()<=0 || upper.height() <= 0 ) return true;
1935 if ( lower.width()<=0 || lower.height() <= 0 ) return true;
1936
1937 if (x<0) {cx=-x; cw+=x; x=0; };
1938 if (cw + x > lower.width()) { cw=lower.width()-x; };
1939 if (y<0) {cy=-y; ch+=y; y=0; };
1940 if (ch + y > lower.height()) { ch=lower.height()-y; };
1941
1942 if ( cx >= upper.width() || cy >= upper.height() ) return true;
1943 if ( cw <= 0 || ch <= 0 ) return true;
1944 }
1945
1946 register uchar *i, *b;
1947 register int a;
1948 register int k;
1949
1950 for (int j=0; j<ch; j++)
1951 {
1952 b=&lower.scanLine(y+j) [ (x+cw) << 2 ];
1953 i=&upper.scanLine(cy+j)[ (cx+cw) << 2 ];
1954
1955 k=cw-1;
1956 --b; --i;
1957 do
1958 {
1959#ifndef WORDS_BIGENDIAN
1960 while ( !(a=*i) && k>0 )
1961#else
1962 while ( !(a=*(i-3)) && k>0 )
1963#endif
1964 {
1965 i-=4; b-=4; k--;
1966 };
1967
1968#ifndef WORDS_BIGENDIAN
1969 --i; --b;
1970 *b += ( ((*i - *b) * a) >> 8 );
1971 --i; --b;
1972 *b += ( ((*i - *b) * a) >> 8 );
1973 --i; --b;
1974 *b += ( ((*i - *b) * a) >> 8 );
1975 --i; --b;
1976#else
1977 *b += ( ((*i - *b) * a) >> 8 );
1978 --i; --b;
1979 *b += ( ((*i - *b) * a) >> 8 );
1980 --i; --b;
1981 *b += ( ((*i - *b) * a) >> 8 );
1982 i -= 2; b -= 2;
1983#endif
1984 } while (k--);
1985 }
1986
1987 return true;
1988}
1989
1990// For selected icons
1991QImage& OImageEffect::selectedImage( QImage &img, const QColor &col )
1992{
1993 return blend( col, img, 0.5);
1994}
1995
1996//
1997// ===================================================================
1998// Effects originally ported from ImageMagick for PixiePlus, plus a few
1999// new ones. (mosfet 12/29/01)
2000// ===================================================================
2001//
2002
2003void OImageEffect::normalize(QImage &img)
2004{
2005 int *histogram, threshold_intensity, intense;
2006 int x, y, i;
2007
2008 unsigned int gray_value;
2009 unsigned int *normalize_map;
2010 unsigned int high, low;
2011
2012 // allocate histogram and normalize map
2013 histogram = (int *)calloc(MaxRGB+1, sizeof(int));
2014 normalize_map = (unsigned int *)malloc((MaxRGB+1)*sizeof(unsigned int));
2015 if(!normalize_map || !histogram){
2016 qWarning("Unable to allocate normalize histogram and map");
2017 free(normalize_map);
2018 free(histogram);
2019 return;
2020 }
2021
2022 // form histogram
2023 if(img.depth() > 8){ // DirectClass
2024 unsigned int *data;
2025 for(y=0; y < img.height(); ++y){
2026 data = (unsigned int *)img.scanLine(y);
2027 for(x=0; x < img.width(); ++x){
2028 gray_value = intensityValue(data[x]);
2029 histogram[gray_value]++;
2030 }
2031 }
2032 }
2033 else{ // PsudeoClass
2034 unsigned char *data;
2035 unsigned int *cTable = img.colorTable();
2036 for(y=0; y < img.height(); ++y){
2037 data = (unsigned char *)img.scanLine(y);
2038 for(x=0; x < img.width(); ++x){
2039 gray_value = intensityValue(*(cTable+data[x]));
2040 histogram[gray_value]++;
2041 }
2042 }
2043 }
2044
2045 // find histogram boundaries by locating the 1 percent levels
2046 threshold_intensity = (img.width()*img.height())/100;
2047 intense = 0;
2048 for(low=0; low < MaxRGB; ++low){
2049 intense+=histogram[low];
2050 if(intense > threshold_intensity)
2051 break;
2052 }
2053 intense=0;
2054 for(high=MaxRGB; high != 0; --high){
2055 intense+=histogram[high];
2056 if(intense > threshold_intensity)
2057 break;
2058 }
2059
2060 if (low == high){
2061 // Unreasonable contrast; use zero threshold to determine boundaries.
2062 threshold_intensity=0;
2063 intense=0;
2064 for(low=0; low < MaxRGB; ++low){
2065 intense+=histogram[low];
2066 if(intense > threshold_intensity)
2067 break;
2068 }
2069 intense=0;
2070 for(high=MaxRGB; high != 0; --high)
2071 {
2072 intense+=histogram[high];
2073 if(intense > threshold_intensity)
2074 break;
2075 }
2076 if(low == high)
2077 return; // zero span bound
2078 }
2079
2080 // Stretch the histogram to create the normalized image mapping.
2081 for(i=0; i <= MaxRGB; i++){
2082 if (i < (int) low)
2083 normalize_map[i]=0;
2084 else{
2085 if(i > (int) high)
2086 normalize_map[i]=MaxRGB;
2087 else
2088 normalize_map[i]=(MaxRGB-1)*(i-low)/(high-low);
2089 }
2090 }
2091 // Normalize
2092 if(img.depth() > 8){ // DirectClass
2093 unsigned int *data;
2094 for(y=0; y < img.height(); ++y){
2095 data = (unsigned int *)img.scanLine(y);
2096 for(x=0; x < img.width(); ++x){
2097 data[x] = qRgba(normalize_map[qRed(data[x])],
2098 normalize_map[qGreen(data[x])],
2099 normalize_map[qBlue(data[x])],
2100 qAlpha(data[x]));
2101 }
2102 }
2103 }
2104 else{ // PsudeoClass
2105 int colors = img.numColors();
2106 unsigned int *cTable = img.colorTable();
2107 for(i=0; i < colors; ++i){
2108 cTable[i] = qRgba(normalize_map[qRed(cTable[i])],
2109 normalize_map[qGreen(cTable[i])],
2110 normalize_map[qBlue(cTable[i])],
2111 qAlpha(cTable[i]));
2112 }
2113 }
2114 free(histogram);
2115 free(normalize_map);
2116}
2117
2118
2119void OImageEffect::equalize(QImage &img)
2120{
2121 int *histogram, *map, *equalize_map;
2122 int x, y, i, j;
2123
2124 unsigned int high, low;
2125
2126 // allocate histogram and maps
2127 histogram = (int *)calloc(MaxRGB+1, sizeof(int));
2128 map = (int *)malloc((MaxRGB+1)*sizeof(unsigned int));
2129 equalize_map = (int *)malloc((MaxRGB+1)*sizeof(unsigned int));
2130
2131 if(!histogram || !map || !equalize_map){
2132 qWarning("Unable to allocate equalize histogram and maps");
2133 free(histogram);
2134 free(map);
2135 free(equalize_map);
2136 return;
2137 }
2138 // form histogram
2139 if(img.depth() > 8){ // DirectClass
2140 unsigned int *data;
2141 for(y=0; y < img.height(); ++y){
2142 data = (unsigned int *)img.scanLine(y);
2143 for(x=0; x < img.width(); ++x){
2144 histogram[intensityValue(data[x])]++;
2145 }
2146 }
2147 }
2148 else{ // PsudeoClass
2149 unsigned char *data;
2150 unsigned int *cTable = img.colorTable();
2151 for(y=0; y < img.height(); ++y){
2152 data = (unsigned char *)img.scanLine(y);
2153 for(x=0; x < img.width(); ++x){
2154 histogram[intensityValue(*(cTable+data[x]))]++;
2155 }
2156 }
2157 }
2158
2159 // integrate the histogram to get the equalization map.
2160 j=0;
2161 for(i=0; i <= MaxRGB; i++){
2162 j+=histogram[i];
2163 map[i]=j;
2164 }
2165 free(histogram);
2166 if(map[MaxRGB] == 0){
2167 free(equalize_map);
2168 free(map);
2169 return;
2170 }
2171 // equalize
2172 low=map[0];
2173 high=map[MaxRGB];
2174 for(i=0; i <= MaxRGB; i++)
2175 equalize_map[i]=(unsigned int)
2176 ((((double) (map[i]-low))*MaxRGB)/QMAX(high-low,1));
2177 free(map);
2178 // stretch the histogram
2179 if(img.depth() > 8){ // DirectClass
2180 unsigned int *data;
2181 for(y=0; y < img.height(); ++y){
2182 data = (unsigned int *)img.scanLine(y);
2183 for(x=0; x < img.width(); ++x){
2184 data[x] = qRgba(equalize_map[qRed(data[x])],
2185 equalize_map[qGreen(data[x])],
2186 equalize_map[qBlue(data[x])],
2187 qAlpha(data[x]));
2188 }
2189 }
2190 }
2191 else{ // PsudeoClass
2192 int colors = img.numColors();
2193 unsigned int *cTable = img.colorTable();
2194 for(i=0; i < colors; ++i){
2195 cTable[i] = qRgba(equalize_map[qRed(cTable[i])],
2196 equalize_map[qGreen(cTable[i])],
2197 equalize_map[qBlue(cTable[i])],
2198 qAlpha(cTable[i]));
2199 }
2200 }
2201 free(equalize_map);
2202}
2203
2204QImage OImageEffect::sample(QImage &src, int w, int h)
2205{
2206 if(w == src.width() && h == src.height())
2207 return(src);
2208
2209 double *x_offset, *y_offset;
2210 int j, k, y;
2211 register int x;
2212 QImage dest(w, h, src.depth());
2213
2214 x_offset = (double *)malloc(w*sizeof(double));
2215 y_offset = (double *)malloc(h*sizeof(double));
2216 if(!x_offset || !y_offset){
2217 qWarning("Unable to allocate pixels buffer");
2218 free(x_offset);
2219 free(y_offset);
2220 return(src);
2221 }
2222
2223 // init pixel offsets
2224 for(x=0; x < w; ++x)
2225 x_offset[x] = x*src.width()/((double)w);
2226 for(y=0; y < h; ++y)
2227 y_offset[y] = y*src.height()/((double)h);
2228
2229 // sample each row
2230 if(src.depth() > 8){ // DirectClass source image
2231 unsigned int *srcData, *destData;
2232 unsigned int *pixels;
2233 pixels = (unsigned int *)malloc(src.width()*sizeof(unsigned int));
2234 if(!pixels){
2235 qWarning("Unable to allocate pixels buffer");
2236 free(pixels);
2237 free(x_offset);
2238 free(y_offset);
2239 return(src);
2240 }
2241 j = (-1);
2242 for(y=0; y < h; ++y){
2243 destData = (unsigned int *)dest.scanLine(y);
2244 if(j != y_offset[y]){
2245 // read a scan line
2246 j = (int)(y_offset[y]);
2247 srcData = (unsigned int *)src.scanLine(j);
2248 (void)memcpy(pixels, srcData, src.width()*sizeof(unsigned int));
2249 }
2250 // sample each column
2251 for(x=0; x < w; ++x){
2252 k = (int)(x_offset[x]);
2253 destData[x] = pixels[k];
2254 }
2255 }
2256 free(pixels);
2257 }
2258 else{ // PsudeoClass source image
2259 unsigned char *srcData, *destData;
2260 unsigned char *pixels;
2261 pixels = (unsigned char *)malloc(src.width()*sizeof(unsigned char));
2262 if(!pixels){
2263 qWarning("Unable to allocate pixels buffer");
2264 free(pixels);
2265 free(x_offset);
2266 free(y_offset);
2267 return(src);
2268 }
2269 // copy colortable
2270 dest.setNumColors(src.numColors());
2271 (void)memcpy(dest.colorTable(), src.colorTable(),
2272 src.numColors()*sizeof(unsigned int));
2273
2274 // sample image
2275 j = (-1);
2276 for(y=0; y < h; ++y){
2277 destData = (unsigned char *)dest.scanLine(y);
2278 if(j != y_offset[y]){
2279 // read a scan line
2280 j = (int)(y_offset[y]);
2281 srcData = (unsigned char *)src.scanLine(j);
2282 (void)memcpy(pixels, srcData, src.width()*sizeof(unsigned char));
2283 }
2284 // sample each column
2285 for(x=0; x < w; ++x){
2286 k = (int)(x_offset[x]);
2287 destData[x] = pixels[k];
2288 }
2289 }
2290 free(pixels);
2291 }
2292 free(x_offset);
2293 free(y_offset);
2294 return(dest);
2295}
2296
2297void OImageEffect::threshold(QImage &img, unsigned int threshold)
2298{
2299 int i, count;
2300 unsigned int *data;
2301 if(img.depth() > 8){ // DirectClass
2302 count = img.width()*img.height();
2303 data = (unsigned int *)img.bits();
2304 }
2305 else{ // PsudeoClass
2306 count = img.numColors();
2307 data = (unsigned int *)img.colorTable();
2308 }
2309 for(i=0; i < count; ++i)
2310 data[i] = intensityValue(data[i]) < threshold ? Qt::black.rgb() : Qt::white.rgb();
2311}
2312
2313QImage OImageEffect::charcoal(QImage &src, double factor)
2314{
2315 QImage dest(src);
2316 dest.detach();
2317 toGray(dest);
2318 dest = edge(dest, factor);
2319 dest = blur(dest, factor);
2320 normalize(dest);
2321 dest.invertPixels(false);
2322 return(dest);
2323}
2324
2325void OImageEffect::hull(const int x_offset, const int y_offset,
2326 const int polarity, const int columns,
2327 const int rows,
2328 unsigned int *f, unsigned int *g)
2329{
2330 int x, y;
2331
2332 unsigned int *p, *q, *r, *s;
2333 unsigned int v;
2334 if(f == NULL || g == NULL)
2335 return;
2336 p=f+(columns+2);
2337 q=g+(columns+2);
2338 r=p+(y_offset*(columns+2)+x_offset);
2339 for (y=0; y < rows; y++){
2340 p++;
2341 q++;
2342 r++;
2343 if(polarity > 0)
2344 for (x=0; x < columns; x++){
2345 v=(*p);
2346 if (*r > v)
2347 v++;
2348 *q=v;
2349 p++;
2350 q++;
2351 r++;
2352 }
2353 else
2354 for(x=0; x < columns; x++){
2355 v=(*p);
2356 if (v > (unsigned int) (*r+1))
2357 v--;
2358 *q=v;
2359 p++;
2360 q++;
2361 r++;
2362 }
2363 p++;
2364 q++;
2365 r++;
2366 }
2367 p=f+(columns+2);
2368 q=g+(columns+2);
2369 r=q+(y_offset*(columns+2)+x_offset);
2370 s=q-(y_offset*(columns+2)+x_offset);
2371 for(y=0; y < rows; y++){
2372 p++;
2373 q++;
2374 r++;
2375 s++;
2376 if(polarity > 0)
2377 for(x=0; x < (int) columns; x++){
2378 v=(*q);
2379 if (((unsigned int) (*s+1) > v) && (*r > v))
2380 v++;
2381 *p=v;
2382 p++;
2383 q++;
2384 r++;
2385 s++;
2386 }
2387 else
2388 for (x=0; x < columns; x++){
2389 v=(*q);
2390 if (((unsigned int) (*s+1) < v) && (*r < v))
2391 v--;
2392 *p=v;
2393 p++;
2394 q++;
2395 r++;
2396 s++;
2397 }
2398 p++;
2399 q++;
2400 r++;
2401 s++;
2402 }
2403}
2404
2405QImage OImageEffect::despeckle(QImage &src)
2406{
2407 int i, j, x, y;
2408 unsigned int *blue_channel, *red_channel, *green_channel, *buffer,
2409 *alpha_channel;
2410 int packets;
2411 static const int
2412 X[4]= {0, 1, 1,-1},
2413 Y[4]= {1, 0, 1, 1};
2414
2415 unsigned int *destData;
2416 QImage dest(src.width(), src.height(), 32);
2417
2418 packets = (src.width()+2)*(src.height()+2);
2419 red_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
2420 green_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
2421 blue_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
2422 alpha_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
2423 buffer = (unsigned int *)calloc(packets, sizeof(unsigned int));
2424 if(!red_channel || ! green_channel || ! blue_channel || ! alpha_channel ||
2425 !buffer){
2426 free(red_channel);
2427 free(green_channel);
2428 free(blue_channel);
2429 free(alpha_channel);
2430 free(buffer);
2431 return(src);
2432 }
2433
2434 // copy image pixels to color component buffers
2435 j = src.width()+2;
2436 if(src.depth() > 8){ // DirectClass source image
2437 unsigned int *srcData;
2438 for(y=0; y < src.height(); ++y){
2439 srcData = (unsigned int *)src.scanLine(y);
2440 ++j;
2441 for(x=0; x < src.width(); ++x){
2442 red_channel[j] = qRed(srcData[x]);
2443 green_channel[j] = qGreen(srcData[x]);
2444 blue_channel[j] = qBlue(srcData[x]);
2445 alpha_channel[j] = qAlpha(srcData[x]);
2446 ++j;
2447 }
2448 ++j;
2449 }
2450 }
2451 else{ // PsudeoClass source image
2452 unsigned char *srcData;
2453 unsigned int *cTable = src.colorTable();
2454 unsigned int pixel;
2455 for(y=0; y < src.height(); ++y){
2456 srcData = (unsigned char *)src.scanLine(y);
2457 ++j;
2458 for(x=0; x < src.width(); ++x){
2459 pixel = *(cTable+srcData[x]);
2460 red_channel[j] = qRed(pixel);
2461 green_channel[j] = qGreen(pixel);
2462 blue_channel[j] = qBlue(pixel);
2463 alpha_channel[j] = qAlpha(pixel);
2464 ++j;
2465 }
2466 ++j;
2467 }
2468 }
2469 // reduce speckle in red channel
2470 for(i=0; i < 4; i++){
2471 hull(X[i],Y[i],1,src.width(),src.height(),red_channel,buffer);
2472 hull(-X[i],-Y[i],1,src.width(),src.height(),red_channel,buffer);
2473 hull(-X[i],-Y[i],-1,src.width(),src.height(),red_channel,buffer);
2474 hull(X[i],Y[i],-1,src.width(),src.height(),red_channel,buffer);
2475 }
2476 // reduce speckle in green channel
2477 for (i=0; i < packets; i++)
2478 buffer[i]=0;
2479 for (i=0; i < 4; i++){
2480 hull(X[i],Y[i],1,src.width(),src.height(),green_channel,buffer);
2481 hull(-X[i],-Y[i],1,src.width(),src.height(),green_channel,buffer);
2482 hull(-X[i],-Y[i],-1,src.width(),src.height(),green_channel,buffer);
2483 hull(X[i],Y[i],-1,src.width(),src.height(),green_channel,buffer);
2484 }
2485 // reduce speckle in blue channel
2486 for (i=0; i < packets; i++)
2487 buffer[i]=0;
2488 for (i=0; i < 4; i++){
2489 hull(X[i],Y[i],1,src.width(),src.height(),blue_channel,buffer);
2490 hull(-X[i],-Y[i],1,src.width(),src.height(),blue_channel,buffer);
2491 hull(-X[i],-Y[i],-1,src.width(),src.height(),blue_channel,buffer);
2492 hull(X[i],Y[i],-1,src.width(),src.height(),blue_channel,buffer);
2493 }
2494 // copy color component buffers to despeckled image
2495 j = dest.width()+2;
2496 for(y=0; y < dest.height(); ++y)
2497 {
2498 destData = (unsigned int *)dest.scanLine(y);
2499 ++j;
2500 for (x=0; x < dest.width(); ++x)
2501 {
2502 destData[x] = qRgba(red_channel[j], green_channel[j],
2503 blue_channel[j], alpha_channel[j]);
2504 ++j;
2505 }
2506 ++j;
2507 }
2508 free(buffer);
2509 free(red_channel);
2510 free(green_channel);
2511 free(blue_channel);
2512 free(alpha_channel);
2513 return(dest);
2514}
2515
2516unsigned int OImageEffect::generateNoise(unsigned int pixel,
2517 NoiseType noise_type)
2518{
2519#define NoiseEpsilon 1.0e-5
2520#define NoiseMask 0x7fff
2521#define SigmaUniform 4.0
2522#define SigmaGaussian 4.0
2523#define SigmaImpulse 0.10
2524#define SigmaLaplacian 10.0
2525#define SigmaMultiplicativeGaussian 0.5
2526#define SigmaPoisson 0.05
2527#define TauGaussian 20.0
2528
2529 double alpha, beta, sigma, value;
2530 alpha=(double) (rand() & NoiseMask)/NoiseMask;
2531 if (alpha == 0.0)
2532 alpha=1.0;
2533 switch(noise_type){
2534 case UniformNoise:
2535 default:
2536 {
2537 value=(double) pixel+SigmaUniform*(alpha-0.5);
2538 break;
2539 }
2540 case GaussianNoise:
2541 {
2542 double tau;
2543
2544 beta=(double) (rand() & NoiseMask)/NoiseMask;
2545 sigma=sqrt(-2.0*log(alpha))*cos(2.0*M_PI*beta);
2546 tau=sqrt(-2.0*log(alpha))*sin(2.0*M_PI*beta);
2547 value=(double) pixel+
2548 (sqrt((double) pixel)*SigmaGaussian*sigma)+(TauGaussian*tau);
2549 break;
2550 }
2551 case MultiplicativeGaussianNoise:
2552 {
2553 if (alpha <= NoiseEpsilon)
2554 sigma=MaxRGB;
2555 else
2556 sigma=sqrt(-2.0*log(alpha));
2557 beta=(rand() & NoiseMask)/NoiseMask;
2558 value=(double) pixel+
2559 pixel*SigmaMultiplicativeGaussian*sigma*cos(2.0*M_PI*beta);
2560 break;
2561 }
2562 case ImpulseNoise:
2563 {
2564 if (alpha < (SigmaImpulse/2.0))
2565 value=0;
2566 else
2567 if (alpha >= (1.0-(SigmaImpulse/2.0)))
2568 value=MaxRGB;
2569 else
2570 value=pixel;
2571 break;
2572 }
2573 case LaplacianNoise:
2574 {
2575 if (alpha <= 0.5)
2576 {
2577 if (alpha <= NoiseEpsilon)
2578 value=(double) pixel-MaxRGB;
2579 else
2580 value=(double) pixel+SigmaLaplacian*log(2.0*alpha);
2581 break;
2582 }
2583 beta=1.0-alpha;
2584 if (beta <= (0.5*NoiseEpsilon))
2585 value=(double) pixel+MaxRGB;
2586 else
2587 value=(double) pixel-SigmaLaplacian*log(2.0*beta);
2588 break;
2589 }
2590 case PoissonNoise:
2591 {
2592 register int
2593 i;
2594
2595 for (i=0; alpha > exp(-SigmaPoisson*pixel); i++)
2596 {
2597 beta=(double) (rand() & NoiseMask)/NoiseMask;
2598 alpha=alpha*beta;
2599 }
2600 value=i/SigmaPoisson;
2601 break;
2602 }
2603 }
2604 if(value < 0.0)
2605 return(0);
2606 if(value > MaxRGB)
2607 return(MaxRGB);
2608 return((unsigned int) (value+0.5));
2609}
2610
2611QImage OImageEffect::addNoise(QImage &src, NoiseType noise_type)
2612{
2613 int x, y;
2614 QImage dest(src.width(), src.height(), 32);
2615 unsigned int *destData;
2616
2617 if(src.depth() > 8){ // DirectClass source image
2618 unsigned int *srcData;
2619 for(y=0; y < src.height(); ++y){
2620 srcData = (unsigned int *)src.scanLine(y);
2621 destData = (unsigned int *)dest.scanLine(y);
2622 for(x=0; x < src.width(); ++x){
2623 destData[x] = qRgba(generateNoise(qRed(srcData[x]), noise_type),
2624 generateNoise(qGreen(srcData[x]), noise_type),
2625 generateNoise(qBlue(srcData[x]), noise_type),
2626 qAlpha(srcData[x]));
2627 }
2628 }
2629 }
2630 else{ // PsudeoClass source image
2631 unsigned char *srcData;
2632 unsigned int *cTable = src.colorTable();
2633 unsigned int pixel;
2634 for(y=0; y < src.height(); ++y){
2635 srcData = (unsigned char *)src.scanLine(y);
2636 destData = (unsigned int *)dest.scanLine(y);
2637 for(x=0; x < src.width(); ++x){
2638 pixel = *(cTable+srcData[x]);
2639 destData[x] = qRgba(generateNoise(qRed(pixel), noise_type),
2640 generateNoise(qGreen(pixel), noise_type),
2641 generateNoise(qBlue(pixel), noise_type),
2642 qAlpha(pixel));
2643 }
2644 }
2645
2646 }
2647 return(dest);
2648}
2649
2650unsigned int OImageEffect::interpolateColor(QImage *image, double x_offset,
2651 double y_offset,
2652 unsigned int background)
2653{
2654 double alpha, beta;
2655 unsigned int p, q, r, s;
2656 int x, y;
2657
2658 x = (int)x_offset;
2659 y = (int)y_offset;
2660 if((x < -1) || (x >= image->width()) || (y < -1) || (y >= image->height()))
2661 return(background);
2662 if(image->depth() > 8){
2663 if((x >= 0) && (y >= 0) && (x < (image->width()-1)) && (y < (image->height()-1))) {
2664 unsigned int *t = (unsigned int *)image->scanLine(y);
2665 p = t[x];
2666 q = t[x+1];
2667 r = t[x+image->width()];
2668 s = t[x+image->width()+1];
2669 }
2670 else{
2671 unsigned int *t = (unsigned int *)image->scanLine(y);
2672 p = background;
2673 if((x >= 0) && (y >= 0)){
2674 p = t[x];
2675 }
2676 q = background;
2677 if(((x+1) < image->width()) && (y >= 0)){
2678 q = t[x+1];
2679 }
2680 r = background;
2681 if((x >= 0) && ((y+1) < image->height())){
2682 t = (unsigned int *)image->scanLine(y+1);
2683 r = t[x+image->width()];
2684 }
2685 s = background;
2686 if(((x+1) < image->width()) && ((y+1) < image->height())){
2687 t = (unsigned int *)image->scanLine(y+1);
2688 s = t[x+image->width()+1];
2689 }
2690
2691 }
2692 }
2693 else{
2694 unsigned int *colorTable = (unsigned int *)image->colorTable();
2695 if((x >= 0) && (y >= 0) && (x < (image->width()-1)) && (y < (image->height()-1))) {
2696 unsigned char *t;
2697 t = (unsigned char *)image->scanLine(y);
2698 p = *(colorTable+t[x]);
2699 q = *(colorTable+t[x+1]);
2700 t = (unsigned char *)image->scanLine(y+1);
2701 r = *(colorTable+t[x]);
2702 s = *(colorTable+t[x+1]);
2703 }
2704 else{
2705 unsigned char *t;
2706 p = background;
2707 if((x >= 0) && (y >= 0)){
2708 t = (unsigned char *)image->scanLine(y);
2709 p = *(colorTable+t[x]);
2710 }
2711 q = background;
2712 if(((x+1) < image->width()) && (y >= 0)){
2713 t = (unsigned char *)image->scanLine(y);
2714 q = *(colorTable+t[x+1]);
2715 }
2716 r = background;
2717 if((x >= 0) && ((y+1) < image->height())){
2718 t = (unsigned char *)image->scanLine(y+1);
2719 r = *(colorTable+t[x]);
2720 }
2721 s = background;
2722 if(((x+1) < image->width()) && ((y+1) < image->height())){
2723 t = (unsigned char *)image->scanLine(y+1);
2724 s = *(colorTable+t[x+1]);
2725 }
2726
2727 }
2728
2729 }
2730 x_offset -= floor(x_offset);
2731 y_offset -= floor(y_offset);
2732 alpha = 1.0-x_offset;
2733 beta = 1.0-y_offset;
2734
2735 return(qRgba((unsigned char)(beta*(alpha*qRed(p)+x_offset*qRed(q))+y_offset*(alpha*qRed(r)+x_offset*qRed(s))),
2736 (unsigned char)(beta*(alpha*qGreen(p)+x_offset*qGreen(q))+y_offset*(alpha*qGreen(r)+x_offset*qGreen(s))),
2737 (unsigned char)(beta*(alpha*qBlue(p)+x_offset*qBlue(q))+y_offset*(alpha*qBlue(r)+x_offset*qBlue(s))),
2738 (unsigned char)(beta*(alpha*qAlpha(p)+x_offset*qAlpha(q))+y_offset*(alpha*qAlpha(r)+x_offset*qAlpha(s)))));
2739}
2740
2741QImage OImageEffect::implode(QImage &src, double factor,
2742 unsigned int background)
2743{
2744 double amount, distance, radius;
2745 double x_center, x_distance, x_scale;
2746 double y_center, y_distance, y_scale;
2747 unsigned int *destData;
2748 int x, y;
2749
2750 QImage dest(src.width(), src.height(), 32);
2751
2752 // compute scaling factor
2753 x_scale = 1.0;
2754 y_scale = 1.0;
2755 x_center = (double)0.5*src.width();
2756 y_center = (double)0.5*src.height();
2757 radius=x_center;
2758 if(src.width() > src.height())
2759 y_scale = (double)src.width()/src.height();
2760 else if(src.width() < src.height()){
2761 x_scale = (double) src.height()/src.width();
2762 radius = y_center;
2763 }
2764 amount=factor/10.0;
2765 if(amount >= 0)
2766 amount/=10.0;
2767 if(src.depth() > 8){ // DirectClass source image
2768 unsigned int *srcData;
2769 for(y=0; y < src.height(); ++y){
2770 srcData = (unsigned int *)src.scanLine(y);
2771 destData = (unsigned int *)dest.scanLine(y);
2772 y_distance=y_scale*(y-y_center);
2773 for(x=0; x < src.width(); ++x){
2774 destData[x] = srcData[x];
2775 x_distance = x_scale*(x-x_center);
2776 distance= x_distance*x_distance+y_distance*y_distance;
2777 if(distance < (radius*radius)){
2778 double factor;
2779 // Implode the pixel.
2780 factor=1.0;
2781 if(distance > 0.0)
2782 factor=
2783 pow(sin(0.5000000000000001*M_PI*sqrt(distance)/radius),-amount);
2784 destData[x] = interpolateColor(&src, factor*x_distance/x_scale+x_center,
2785 factor*y_distance/y_scale+y_center,
2786 background);
2787 }
2788 }
2789 }
2790 }
2791 else{ // PsudeoClass source image
2792 unsigned char *srcData;
2793 unsigned char idx;
2794 unsigned int *cTable = src.colorTable();
2795 for(y=0; y < src.height(); ++y){
2796 srcData = (unsigned char *)src.scanLine(y);
2797 destData = (unsigned int *)dest.scanLine(y);
2798 y_distance=y_scale*(y-y_center);
2799 for(x=0; x < src.width(); ++x){
2800 idx = srcData[x];
2801 destData[x] = cTable[idx];
2802 x_distance = x_scale*(x-x_center);
2803 distance= x_distance*x_distance+y_distance*y_distance;
2804 if(distance < (radius*radius)){
2805 double factor;
2806 // Implode the pixel.
2807 factor=1.0;
2808 if(distance > 0.0)
2809 factor=
2810 pow(sin(0.5000000000000001*M_PI*sqrt(distance)/radius),-amount);
2811 destData[x] = interpolateColor(&src, factor*x_distance/x_scale+x_center,
2812 factor*y_distance/y_scale+y_center,
2813 background);
2814 }
2815 }
2816 }
2817
2818 }
2819 return(dest);
2820}
2821
2822QImage OImageEffect::rotate(QImage &img, RotateDirection r)
2823{
2824 QImage dest;
2825 int x, y;
2826 if(img.depth() > 8){
2827 unsigned int *srcData, *destData;
2828 switch(r){
2829 case Rotate90:
2830 dest.create(img.height(), img.width(), img.depth());
2831 for(y=0; y < img.height(); ++y){
2832 srcData = (unsigned int *)img.scanLine(y);
2833 for(x=0; x < img.width(); ++x){
2834 destData = (unsigned int *)dest.scanLine(x);
2835 destData[img.height()-y-1] = srcData[x];
2836 }
2837 }
2838 break;
2839 case Rotate180:
2840 dest.create(img.width(), img.height(), img.depth());
2841 for(y=0; y < img.height(); ++y){
2842 srcData = (unsigned int *)img.scanLine(y);
2843 destData = (unsigned int *)dest.scanLine(img.height()-y-1);
2844 for(x=0; x < img.width(); ++x)
2845 destData[img.width()-x-1] = srcData[x];
2846 }
2847 break;
2848 case Rotate270:
2849 dest.create(img.height(), img.width(), img.depth());
2850 for(y=0; y < img.height(); ++y){
2851 srcData = (unsigned int *)img.scanLine(y);
2852 for(x=0; x < img.width(); ++x){
2853 destData = (unsigned int *)dest.scanLine(img.width()-x-1);
2854 destData[y] = srcData[x];
2855 }
2856 }
2857 break;
2858 default:
2859 dest = img;
2860 break;
2861 }
2862 }
2863 else{
2864 unsigned char *srcData, *destData;
2865 unsigned int *srcTable, *destTable;
2866 switch(r){
2867 case Rotate90:
2868 dest.create(img.height(), img.width(), img.depth());
2869 dest.setNumColors(img.numColors());
2870 srcTable = (unsigned int *)img.colorTable();
2871 destTable = (unsigned int *)dest.colorTable();
2872 for(x=0; x < img.numColors(); ++x)
2873 destTable[x] = srcTable[x];
2874 for(y=0; y < img.height(); ++y){
2875 srcData = (unsigned char *)img.scanLine(y);
2876 for(x=0; x < img.width(); ++x){
2877 destData = (unsigned char *)dest.scanLine(x);
2878 destData[img.height()-y-1] = srcData[x];
2879 }
2880 }
2881 break;
2882 case Rotate180:
2883 dest.create(img.width(), img.height(), img.depth());
2884 dest.setNumColors(img.numColors());
2885 srcTable = (unsigned int *)img.colorTable();
2886 destTable = (unsigned int *)dest.colorTable();
2887 for(x=0; x < img.numColors(); ++x)
2888 destTable[x] = srcTable[x];
2889 for(y=0; y < img.height(); ++y){
2890 srcData = (unsigned char *)img.scanLine(y);
2891 destData = (unsigned char *)dest.scanLine(img.height()-y-1);
2892 for(x=0; x < img.width(); ++x)
2893 destData[img.width()-x-1] = srcData[x];
2894 }
2895 break;
2896 case Rotate270:
2897 dest.create(img.height(), img.width(), img.depth());
2898 dest.setNumColors(img.numColors());
2899 srcTable = (unsigned int *)img.colorTable();
2900 destTable = (unsigned int *)dest.colorTable();
2901 for(x=0; x < img.numColors(); ++x)
2902 destTable[x] = srcTable[x];
2903 for(y=0; y < img.height(); ++y){
2904 srcData = (unsigned char *)img.scanLine(y);
2905 for(x=0; x < img.width(); ++x){
2906 destData = (unsigned char *)dest.scanLine(img.width()-x-1);
2907 destData[y] = srcData[x];
2908 }
2909 }
2910 break;
2911 default:
2912 dest = img;
2913 break;
2914 }
2915
2916 }
2917 return(dest);
2918}
2919
2920void OImageEffect::solarize(QImage &img, double factor)
2921{
2922 int i, count;
2923 int threshold;
2924 unsigned int *data;
2925
2926 threshold = (int)(factor*(MaxRGB+1)/100.0);
2927 if(img.depth() < 32){
2928 data = (unsigned int *)img.colorTable();
2929 count = img.numColors();
2930 }
2931 else{
2932 data = (unsigned int *)img.bits();
2933 count = img.width()*img.height();
2934 }
2935 for(i=0; i < count; ++i){
2936 data[i] = qRgba(qRed(data[i]) > threshold ? MaxRGB-qRed(data[i]) : qRed(data[i]),
2937 qGreen(data[i]) > threshold ? MaxRGB-qGreen(data[i]) : qGreen(data[i]),
2938 qBlue(data[i]) > threshold ? MaxRGB-qBlue(data[i]) : qBlue(data[i]),
2939 qAlpha(data[i]));
2940 }
2941}
2942
2943QImage OImageEffect::spread(QImage &src, unsigned int amount)
2944{
2945 int quantum, x, y;
2946 int x_distance, y_distance;
2947 if(src.width() < 3 || src.height() < 3)
2948 return(src);
2949 QImage dest(src);
2950 dest.detach();
2951 quantum=(amount+1) >> 1;
2952 if(src.depth() > 8){ // DirectClass source image
2953 unsigned int *p, *q;
2954 for(y=0; y < src.height(); y++){
2955 q = (unsigned int *)dest.scanLine(y);
2956 for(x=0; x < src.width(); x++){
2957 x_distance = x + ((rand() & (amount+1))-quantum);
2958 y_distance = y + ((rand() & (amount+1))-quantum);
2959 x_distance = QMIN(x_distance, src.width()-1);
2960 y_distance = QMIN(y_distance, src.height()-1);
2961 if(x_distance < 0)
2962 x_distance = 0;
2963 if(y_distance < 0)
2964 y_distance = 0;
2965 p = (unsigned int *)src.scanLine(y_distance);
2966 p += x_distance;
2967 *q++=(*p);
2968 }
2969 }
2970 }
2971 else{ // PsudeoClass source image
2972 // just do colortable values
2973 unsigned char *p, *q;
2974 for(y=0; y < src.height(); y++){
2975 q = (unsigned char *)dest.scanLine(y);
2976 for(x=0; x < src.width(); x++){
2977 x_distance = x + ((rand() & (amount+1))-quantum);
2978 y_distance = y + ((rand() & (amount+1))-quantum);
2979 x_distance = QMIN(x_distance, src.width()-1);
2980 y_distance = QMIN(y_distance, src.height()-1);
2981 if(x_distance < 0)
2982 x_distance = 0;
2983 if(y_distance < 0)
2984 y_distance = 0;
2985 p = (unsigned char *)src.scanLine(y_distance);
2986 p += x_distance;
2987 *q++=(*p);
2988 }
2989 }
2990 }
2991 return(dest);
2992}
2993
2994QImage OImageEffect::swirl(QImage &src, double degrees,
2995 unsigned int background)
2996{
2997 double cosine, distance, factor, radius, sine, x_center, x_distance,
2998 x_scale, y_center, y_distance, y_scale;
2999 int x, y;
3000 unsigned int *q;
3001 QImage dest(src.width(), src.height(), 32);
3002
3003 // compute scaling factor
3004 x_center = src.width()/2.0;
3005 y_center = src.height()/2.0;
3006 radius = QMAX(x_center,y_center);
3007 x_scale=1.0;
3008 y_scale=1.0;
3009 if(src.width() > src.height())
3010 y_scale=(double)src.width()/src.height();
3011 else if(src.width() < src.height())
3012 x_scale=(double)src.height()/src.width();
3013 degrees=DegreesToRadians(degrees);
3014 // swirl each row
3015 if(src.depth() > 8){ // DirectClass source image
3016 unsigned int *p;
3017 for(y=0; y < src.height(); y++){
3018 p = (unsigned int *)src.scanLine(y);
3019 q = (unsigned int *)dest.scanLine(y);
3020 y_distance = y_scale*(y-y_center);
3021 for(x=0; x < src.width(); x++){
3022 // determine if the pixel is within an ellipse
3023 *q=(*p);
3024 x_distance = x_scale*(x-x_center);
3025 distance = x_distance*x_distance+y_distance*y_distance;
3026 if (distance < (radius*radius)){
3027 // swirl
3028 factor = 1.0-sqrt(distance)/radius;
3029 sine = sin(degrees*factor*factor);
3030 cosine = cos(degrees*factor*factor);
3031 *q = interpolateColor(&src,
3032 (cosine*x_distance-sine*y_distance)/x_scale+x_center,
3033 (sine*x_distance+cosine*y_distance)/y_scale+y_center,
3034 background);
3035 }
3036 p++;
3037 q++;
3038 }
3039 }
3040 }
3041 else{ // PsudeoClass source image
3042 unsigned char *p;
3043 unsigned int *cTable = (unsigned int *)src.colorTable();
3044 for(y=0; y < src.height(); y++){
3045 p = (unsigned char *)src.scanLine(y);
3046 q = (unsigned int *)dest.scanLine(y);
3047 y_distance = y_scale*(y-y_center);
3048 for(x=0; x < src.width(); x++){
3049 // determine if the pixel is within an ellipse
3050 *q = *(cTable+(*p));
3051 x_distance = x_scale*(x-x_center);
3052 distance = x_distance*x_distance+y_distance*y_distance;
3053 if (distance < (radius*radius)){
3054 // swirl
3055 factor = 1.0-sqrt(distance)/radius;
3056 sine = sin(degrees*factor*factor);
3057 cosine = cos(degrees*factor*factor);
3058 *q = interpolateColor(&src,
3059 (cosine*x_distance-sine*y_distance)/x_scale+x_center,
3060 (sine*x_distance+cosine*y_distance)/y_scale+y_center,
3061 background);
3062 }
3063 p++;
3064 q++;
3065 }
3066 }
3067
3068 }
3069 return(dest);
3070}
3071
3072QImage OImageEffect::wave(QImage &src, double amplitude, double wavelength,
3073 unsigned int background)
3074{
3075 double *sine_map;
3076 int x, y;
3077 unsigned int *q;
3078
3079 QImage dest(src.width(), src.height() + (int)(2*fabs(amplitude)), 32);
3080 // allocate sine map
3081 sine_map = (double *)malloc(dest.width()*sizeof(double));
3082 if(!sine_map)
3083 return(src);
3084 for(x=0; x < dest.width(); ++x)
3085 sine_map[x]=fabs(amplitude)+amplitude*sin((2*M_PI*x)/wavelength);
3086 // wave image
3087 for(y=0; y < dest.height(); ++y){
3088 q = (unsigned int *)dest.scanLine(y);
3089 for (x=0; x < dest.width(); x++){
3090 *q=interpolateColor(&src, x, (int)(y-sine_map[x]), background);
3091 ++q;
3092 }
3093 }
3094 free(sine_map);
3095 return(dest);
3096}
3097
3098QImage OImageEffect::oilPaint(QImage &src, int radius)
3099{
3100 // TODO 8bpp src!
3101 if(src.depth() < 32){
3102 qWarning("Oil Paint source image < 32bpp. Convert before using!");
3103 return(src);
3104 }
3105 int j, k, i, x, y;
3106 unsigned int *histogram;
3107 unsigned int *s;
3108 unsigned int count;
3109
3110 unsigned int *srcData, *destData;
3111
3112 QImage dest(src);
3113 dest.detach();
3114 histogram = (unsigned int *) malloc((MaxRGB+1)*sizeof(unsigned int));
3115 if(!histogram)
3116 return(src);
3117 // paint each row
3118 k=0;
3119 for(y = radius; y < src.height(); ++y){
3120 srcData = (unsigned int *)src.scanLine(y-radius);
3121 destData = (unsigned int *)dest.scanLine(y);
3122 srcData += radius*src.width()+radius;
3123 destData += radius;
3124 for(x=radius; x < src.width()-radius; ++x){
3125 // determine most frequent color
3126 count = 0;
3127 for(i=0; i < MaxRGB+1; ++i)
3128 histogram[i] = 0;
3129 for(i=0; i < radius; ++i){
3130 s = srcData-(radius-1)*src.width()-i-1;
3131 for(j =0; j < (2*i+1); ++j){
3132 k = intensityValue(*s);
3133 histogram[k]++;
3134 if(histogram[k] > count){
3135 *destData = *s;
3136 count = histogram[k];
3137 }
3138 ++s;
3139 }
3140 s = srcData+(radius-i)*src.width()-i-1;
3141 for(j =0; j < (2*i+1); ++j){
3142 k = intensityValue(*s);
3143 histogram[k]++;
3144 if(histogram[k] > count){
3145 *destData = *s;
3146 count = histogram[k];
3147 }
3148 ++s;
3149 }
3150 }
3151 s = srcData-radius;
3152 for(j =0; j < (2*i+1); ++j){
3153 k = intensityValue(*s);
3154 histogram[k]++;
3155 if(histogram[k] > count){
3156 *destData = *s;
3157 count = histogram[k];
3158 }
3159 ++s;
3160 }
3161 ++srcData;
3162 ++destData;
3163 }
3164 }
3165 free(histogram);
3166 return(dest);
3167}
3168
3169//
3170// The following methods work by computing a value from neighboring pixels
3171// (mosfet 12/28/01)
3172//
3173
3174QImage OImageEffect::edge(QImage &src, double factor)
3175{
3176#define Edge(weight) \
3177 total_red+=(weight)*qRed(*s); \
3178 total_green+=(weight)*qGreen(*s); \
3179 total_blue+=(weight)*qBlue(*s); \
3180 total_opacity+=(weight)*qAlpha(*s); \
3181 s++;
3182
3183#define Edge256(weight) \
3184 total_red+=(weight)*qRed(*(cTable+(*s))); \
3185 total_green+=(weight)*qGreen(*(cTable+(*s))); \
3186 total_blue+=(weight)*qBlue(*(cTable+(*s))); \
3187 total_opacity+=(weight)*qAlpha(*(cTable+(*s))); \
3188 s++;
3189
3190 if(src.width() < 3 || src.height() < 3)
3191 return(src);
3192
3193 double total_blue, total_green, total_opacity, total_red, weight;
3194
3195 int x, y;
3196
3197 unsigned int *q;
3198
3199 QImage dest(src.width(), src.height(), 32);
3200 weight=factor/8.0;
3201 if(src.depth() > 8){ // DirectClass source image
3202 unsigned int *p, *s;
3203 for(y=0; y < src.height(); ++y){
3204 p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
3205 q = (unsigned int *)dest.scanLine(y);
3206 // edge detect this row of pixels.
3207 *q++=(*(p+src.width()));
3208 for(x=1; x < src.width()-1; ++x){
3209 // compute weighted average of target pixel color components.
3210 total_red=0.0;
3211 total_green=0.0;
3212 total_blue=0.0;
3213 total_opacity=0.0;
3214 s=p;
3215 Edge(-weight/8); Edge(-weight/8) Edge(-weight/8);
3216 s=p+src.width();
3217 Edge(-weight/8); Edge(weight); Edge(-weight/8);
3218 s=p+2*src.width();
3219 Edge(-weight/8); Edge(-weight/8); Edge(-weight/8);
3220 *q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
3221 (unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
3222 (unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
3223 (unsigned char)((total_opacity < 0) ? 0 : (total_opacity > MaxRGB) ? MaxRGB : total_opacity));
3224 p++;
3225 q++;
3226 }
3227 p++;
3228 *q++=(*p);
3229 }
3230 }
3231 else{ // PsudeoClass source image
3232 unsigned char *p, *p2, *p3, *s;
3233 unsigned int *cTable = src.colorTable();
3234 int scanLineIdx;
3235 for(y=0; y < src.height(); ++y){
3236 scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
3237 p = (unsigned char *)src.scanLine(scanLineIdx);
3238 p2 = (unsigned char *)src.scanLine(scanLineIdx+1);
3239 p3 = (unsigned char *)src.scanLine(scanLineIdx+2);
3240 q = (unsigned int *)dest.scanLine(y);
3241 // edge detect this row of pixels.
3242 *q++=(*(cTable+(*p2)));
3243 for(x=1; x < src.width()-1; ++x){
3244 // compute weighted average of target pixel color components.
3245 total_red=0.0;
3246 total_green=0.0;
3247 total_blue=0.0;
3248 total_opacity=0.0;
3249 s=p;
3250 Edge256(-weight/8); Edge256(-weight/8) Edge256(-weight/8);
3251 s=p2;
3252 Edge256(-weight/8); Edge256(weight); Edge256(-weight/8);
3253 s=p3;
3254 Edge256(-weight/8); Edge256(-weight/8); Edge256(-weight/8);
3255 *q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
3256 (unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
3257 (unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
3258 (unsigned char)((total_opacity < 0) ? 0 : (total_opacity > MaxRGB) ? MaxRGB : total_opacity));
3259 p++;
3260 p2++;
3261 p3++;
3262 q++;
3263 }
3264 p++;
3265 *q++=(*(cTable+(*p)));
3266 }
3267 }
3268 return(dest);
3269}
3270
3271QImage OImageEffect::sharpen(QImage &src, double factor)
3272{
3273#define Sharpen(weight) \
3274 total_red+=(weight)*qRed(*s); \
3275 total_green+=(weight)*qGreen(*s); \
3276 total_blue+=(weight)*qBlue(*s); \
3277 total_opacity+=(weight)*qAlpha(*s); \
3278 s++;
3279
3280#define Sharpen256(weight) \
3281 total_red+=(weight)*qRed(*(cTable+(*s))); \
3282 total_green+=(weight)*qGreen(*(cTable+(*s))); \
3283 total_blue+=(weight)*qBlue(*(cTable+(*s))); \
3284 total_opacity+=(weight)*qAlpha(*(cTable+(*s))); \
3285 s++;
3286
3287 if(src.width() < 3 || src.height() < 3)
3288 return(src);
3289
3290 double total_blue, total_green, total_opacity, total_red;
3291 double quantum, weight;
3292 unsigned char r, g, b, a;
3293
3294 int x, y;
3295 unsigned int *q;
3296
3297 QImage dest(src.width(), src.height(), 32);
3298 weight = ((100.0-factor)/2.0+13.0);
3299 quantum = QMAX(weight-12.0, 1.0);
3300 if(src.depth() > 8){ // DirectClass source image
3301 unsigned int *p, *s;
3302 for(y=0; y < src.height(); ++y){
3303 p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
3304 q = (unsigned int *)dest.scanLine(y);
3305 // sharpen this row of pixels.
3306 *q++=(*(p+src.width()));
3307 for(x=1; x < src.width()-1; ++x){
3308 // compute weighted average of target pixel color components.
3309 total_red=0.0;
3310 total_green=0.0;
3311 total_blue=0.0;
3312 total_opacity=0.0;
3313 s=p;
3314 Sharpen(-1); Sharpen(-2); Sharpen(-1);
3315 s=p+src.width();
3316 Sharpen(-2); Sharpen(weight); Sharpen(-2);
3317 s=p+2*src.width();
3318 Sharpen(-1); Sharpen(-2); Sharpen(-1);
3319 if(total_red < 0)
3320 r=0;
3321 else if(total_red > (int)(MaxRGB*quantum))
3322 r = (unsigned char)MaxRGB;
3323 else
3324 r = (unsigned char)((total_red+(quantum/2.0))/quantum);
3325
3326 if(total_green < 0)
3327 g = 0;
3328 else if(total_green > (int)(MaxRGB*quantum))
3329 g = (unsigned char)MaxRGB;
3330 else
3331 g = (unsigned char)((total_green+(quantum/2.0))/quantum);
3332
3333 if(total_blue < 0)
3334 b = 0;
3335 else if(total_blue > (int)(MaxRGB*quantum))
3336 b = (unsigned char)MaxRGB;
3337 else
3338 b = (unsigned char)((total_blue+(quantum/2.0))/quantum);
3339
3340 if(total_opacity < 0)
3341 a = 0;
3342 else if(total_opacity > (int)(MaxRGB*quantum))
3343 a = (unsigned char)MaxRGB;
3344 else
3345 a= (unsigned char)((total_opacity+(quantum/2.0))/quantum);
3346
3347 *q = qRgba(r, g, b, a);
3348
3349 p++;
3350 q++;
3351 }
3352 p++;
3353 *q++=(*p);
3354 }
3355 }
3356 else{ // PsudeoClass source image
3357 unsigned char *p, *p2, *p3, *s;
3358 unsigned int *cTable = src.colorTable();
3359 int scanLineIdx;
3360 for(y=0; y < src.height(); ++y){
3361 scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
3362 p = (unsigned char *)src.scanLine(scanLineIdx);
3363 p2 = (unsigned char *)src.scanLine(scanLineIdx+1);
3364 p3 = (unsigned char *)src.scanLine(scanLineIdx+2);
3365 q = (unsigned int *)dest.scanLine(y);
3366 // sharpen this row of pixels.
3367 *q++=(*(cTable+(*p2)));
3368 for(x=1; x < src.width()-1; ++x){
3369 // compute weighted average of target pixel color components.
3370 total_red=0.0;
3371 total_green=0.0;
3372 total_blue=0.0;
3373 total_opacity=0.0;
3374 s=p;
3375 Sharpen256(-1); Sharpen256(-2); Sharpen256(-1);
3376 s=p2;
3377 Sharpen256(-2); Sharpen256(weight); Sharpen256(-2);
3378 s=p3;
3379 Sharpen256(-1); Sharpen256(-2); Sharpen256(-1);
3380 if(total_red < 0)
3381 r=0;
3382 else if(total_red > (int)(MaxRGB*quantum))
3383 r = (unsigned char)MaxRGB;
3384 else
3385 r = (unsigned char)((total_red+(quantum/2.0))/quantum);
3386
3387 if(total_green < 0)
3388 g = 0;
3389 else if(total_green > (int)(MaxRGB*quantum))
3390 g = (unsigned char)MaxRGB;
3391 else
3392 g = (unsigned char)((total_green+(quantum/2.0))/quantum);
3393
3394 if(total_blue < 0)
3395 b = 0;
3396 else if(total_blue > (int)(MaxRGB*quantum))
3397 b = (unsigned char)MaxRGB;
3398 else
3399 b = (unsigned char)((total_blue+(quantum/2.0))/quantum);
3400
3401 if(total_opacity < 0)
3402 a = 0;
3403 else if(total_opacity > (int)(MaxRGB*quantum))
3404 a = (unsigned char)MaxRGB;
3405 else
3406 a = (unsigned char)((total_opacity+(quantum/2.0))/quantum);
3407
3408 *q = qRgba(r, g, b, a);
3409
3410 p++;
3411 p2++;
3412 p3++;
3413 q++;
3414 }
3415 p++;
3416 *q++=(*(cTable+(*p)));
3417 }
3418 }
3419 return(dest);
3420}
3421
3422QImage OImageEffect::emboss(QImage &src)
3423{
3424#define Emboss(weight) \
3425 total_red+=(weight)*qRed(*s); \
3426 total_green+=(weight)*qGreen(*s); \
3427 total_blue+=(weight)*qBlue(*s); \
3428 s++;
3429
3430#define Emboss256(weight) \
3431 total_red+=(weight)*qRed(*(cTable+(*s))); \
3432 total_green+=(weight)*qGreen(*(cTable+(*s))); \
3433 total_blue+=(weight)*qBlue(*(cTable+(*s))); \
3434 s++;
3435
3436 if(src.width() < 3 || src.height() < 3)
3437 return(src);
3438
3439 double total_blue, total_green, total_red;
3440 int x, y;
3441 unsigned int *q;
3442
3443 QImage dest(src.width(), src.height(), 32);
3444 if(src.depth() > 8){ // DirectClass source image
3445 unsigned int *p, *s;
3446 for(y=0; y < src.height(); ++y){
3447 p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
3448 q = (unsigned int *)dest.scanLine(y);
3449 // emboss this row of pixels.
3450 *q++=(*(p+src.width()));
3451 for(x=1; x < src.width()-1; ++x){
3452 // compute weighted average of target pixel color components.
3453 total_red=0.0;
3454 total_green=0.0;
3455 total_blue=0.0;
3456 s=p;
3457 Emboss(-1); Emboss(-2); Emboss( 0);
3458 s=p+src.width();
3459 Emboss(-2); Emboss( 0); Emboss( 2);
3460 s=p+2*src.width();
3461 Emboss( 0); Emboss( 2); Emboss( 1);
3462 total_red += (MaxRGB+1)/2;
3463 total_green += (MaxRGB+1)/2;
3464 total_blue += (MaxRGB+1)/2;
3465 *q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
3466 (unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
3467 (unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
3468 255);
3469 p++;
3470 q++;
3471 }
3472 p++;
3473 *q++=(*p);
3474 }
3475 }
3476 else{ // PsudeoClass source image
3477 unsigned char *p, *p2, *p3, *s;
3478 unsigned int *cTable = src.colorTable();
3479 int scanLineIdx;
3480 for(y=0; y < src.height(); ++y){
3481 scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
3482 p = (unsigned char *)src.scanLine(scanLineIdx);
3483 p2 = (unsigned char *)src.scanLine(scanLineIdx+1);
3484 p3 = (unsigned char *)src.scanLine(scanLineIdx+2);
3485 q = (unsigned int *)dest.scanLine(y);
3486 // emboss this row of pixels.
3487 *q++=(*(cTable+(*p2)));
3488 for(x=1; x < src.width()-1; ++x){
3489 // compute weighted average of target pixel color components.
3490 total_red=0.0;
3491 total_green=0.0;
3492 total_blue=0.0;
3493 s=p;
3494 Emboss256(-1); Emboss256(-2); Emboss256(0);
3495 s=p2;
3496 Emboss256(-2); Emboss256(0); Emboss256(2);
3497 s=p3;
3498 Emboss256(0); Emboss256(2); Emboss256(1);
3499 total_red += (MaxRGB+1)/2;
3500 total_green += (MaxRGB+1)/2;
3501 total_blue += (MaxRGB+1)/2;
3502 *q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
3503 (unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
3504 (unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
3505 255);
3506 p++;
3507 p2++;
3508 p3++;
3509 q++;
3510 }
3511 p++;
3512 *q++=(*(cTable+(*p)));
3513 }
3514 }
3515 toGray(dest);
3516 normalize(dest);
3517 return(dest);
3518}
3519
3520QImage OImageEffect::shade(QImage &src, bool color_shading, double azimuth,
3521 double elevation)
3522{
3523 struct PointInfo{
3524 double x, y, z;
3525 };
3526
3527 double distance, normal_distance, shade;
3528 int x, y;
3529
3530 struct PointInfo light, normal;
3531
3532 unsigned int *q;
3533
3534 QImage dest(src.width(), src.height(), 32);
3535
3536 azimuth = DegreesToRadians(azimuth);
3537 elevation = DegreesToRadians(elevation);
3538 light.x = MaxRGB*cos(azimuth)*cos(elevation);
3539 light.y = MaxRGB*sin(azimuth)*cos(elevation);
3540 light.z = MaxRGB*sin(elevation);
3541 normal.z= 2*MaxRGB; // constant Z of surface normal
3542
3543 if(src.depth() > 8){ // DirectClass source image
3544 unsigned int *p, *s0, *s1, *s2;
3545 for(y=0; y < src.height(); ++y){
3546 p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
3547 q = (unsigned int *)dest.scanLine(y);
3548 // shade this row of pixels.
3549 *q++=(*(p+src.width()));
3550 p++;
3551 s0 = p;
3552 s1 = p + src.width();
3553 s2 = p + 2*src.width();
3554 for(x=1; x < src.width()-1; ++x){
3555 // determine the surface normal and compute shading.
3556 normal.x=intensityValue(*(s0-1))+intensityValue(*(s1-1))+intensityValue(*(s2-1))-
3557 (double) intensityValue(*(s0+1))-(double) intensityValue(*(s1+1))-
3558 (double) intensityValue(*(s2+1));
3559 normal.y=intensityValue(*(s2-1))+intensityValue(*s2)+intensityValue(*(s2+1))-
3560 (double) intensityValue(*(s0-1))-(double) intensityValue(*s0)-
3561 (double) intensityValue(*(s0+1));
3562 if((normal.x == 0) && (normal.y == 0))
3563 shade=light.z;
3564 else{
3565 shade=0.0;
3566 distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
3567 if (distance > 0.0){
3568 normal_distance=
3569 normal.x*normal.x+normal.y*normal.y+normal.z*normal.z;
3570 if(fabs(normal_distance) > 0.0000001)
3571 shade=distance/sqrt(normal_distance);
3572 }
3573 }
3574 if(!color_shading){
3575 *q = qRgba((unsigned char)(shade),
3576 (unsigned char)(shade),
3577 (unsigned char)(shade),
3578 qAlpha(*s1));
3579 }
3580 else{
3581 *q = qRgba((unsigned char)((shade*qRed(*s1))/(MaxRGB+1)),
3582 (unsigned char)((shade*qGreen(*s1))/(MaxRGB+1)),
3583 (unsigned char)((shade*qBlue(*s1))/(MaxRGB+1)),
3584 qAlpha(*s1));
3585 }
3586 ++s0;
3587 ++s1;
3588 ++s2;
3589 q++;
3590 }
3591 *q++=(*s1);
3592 }
3593 }
3594 else{ // PsudeoClass source image
3595 unsigned char *p, *s0, *s1, *s2;
3596 int scanLineIdx;
3597 unsigned int *cTable = (unsigned int *)src.colorTable();
3598 for(y=0; y < src.height(); ++y){
3599 scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
3600 p = (unsigned char *)src.scanLine(scanLineIdx);
3601 q = (unsigned int *)dest.scanLine(y);
3602 // shade this row of pixels.
3603 s0 = p;
3604 s1 = (unsigned char *) src.scanLine(scanLineIdx+1);
3605 s2 = (unsigned char *) src.scanLine(scanLineIdx+2);
3606 *q++=(*(cTable+(*s1)));
3607 ++p;
3608 ++s0;
3609 ++s1;
3610 ++s2;
3611 for(x=1; x < src.width()-1; ++x){
3612 // determine the surface normal and compute shading.
3613 normal.x=intensityValue(*(cTable+(*(s0-1))))+intensityValue(*(cTable+(*(s1-1))))+intensityValue(*(cTable+(*(s2-1))))-
3614 (double) intensityValue(*(cTable+(*(s0+1))))-(double) intensityValue(*(cTable+(*(s1+1))))-
3615 (double) intensityValue(*(cTable+(*(s2+1))));
3616 normal.y=intensityValue(*(cTable+(*(s2-1))))+intensityValue(*(cTable+(*s2)))+intensityValue(*(cTable+(*(s2+1))))-
3617 (double) intensityValue(*(cTable+(*(s0-1))))-(double) intensityValue(*(cTable+(*s0)))-
3618 (double) intensityValue(*(cTable+(*(s0+1))));
3619 if((normal.x == 0) && (normal.y == 0))
3620 shade=light.z;
3621 else{
3622 shade=0.0;
3623 distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
3624 if (distance > 0.0){
3625 normal_distance=
3626 normal.x*normal.x+normal.y*normal.y+normal.z*normal.z;
3627 if(fabs(normal_distance) > 0.0000001)
3628 shade=distance/sqrt(normal_distance);
3629 }
3630 }
3631 if(!color_shading){
3632 *q = qRgba((unsigned char)(shade),
3633 (unsigned char)(shade),
3634 (unsigned char)(shade),
3635 qAlpha(*(cTable+(*s1))));
3636 }
3637 else{
3638 *q = qRgba((unsigned char)((shade*qRed(*(cTable+(*s1))))/(MaxRGB+1)),
3639 (unsigned char)((shade*qGreen(*(cTable+(*s1))))/(MaxRGB+1)),
3640 (unsigned char)((shade*qBlue(*(cTable+(*s1))))/(MaxRGB+1)),
3641 qAlpha(*s1));
3642 }
3643 ++s0;
3644 ++s1;
3645 ++s2;
3646 q++;
3647 }
3648 *q++=(*(cTable+(*s1)));
3649 }
3650 }
3651 return(dest);
3652}
3653
3654QImage OImageEffect::blur(QImage &src, double factor)
3655{
3656
3657#define Blur(weight) \
3658 total_red+=(weight)*qRed(*s); \
3659 total_green+=(weight)*qGreen(*s); \
3660 total_blue+=(weight)*qBlue(*s); \
3661 total_opacity+=(weight)*qAlpha(*s); \
3662 s++;
3663
3664#define Blur256(weight) \
3665 total_red+=(weight)*qRed(*(cTable+(*s))); \
3666 total_green+=(weight)*qGreen(*(cTable+(*s))); \
3667 total_blue+=(weight)*qBlue(*(cTable+(*s))); \
3668 total_opacity+=(weight)*qAlpha(*(cTable+(*s))); \
3669 s++;
3670
3671 if(src.width() < 3 || src.height() < 3)
3672 return(src);
3673
3674 double quantum, total_blue, total_green, total_opacity, total_red, weight;
3675
3676 int x, y;
3677 unsigned int *q;
3678
3679 QImage dest(src.width(), src.height(), 32);
3680 weight=((100.0-factor)/2)+1;
3681 quantum = QMAX(weight+12.0, 1.0);
3682 if(src.depth() > 8){ // DirectClass source image
3683 unsigned int *p, *s;
3684 for(y=0; y < src.height(); ++y){
3685 p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
3686 q = (unsigned int *)dest.scanLine(y);
3687 // blur this row of pixels.
3688 *q++=(*(p+src.width()));
3689 for(x=1; x < src.width()-1; ++x){
3690 // compute weighted average of target pixel color components.
3691 total_red=0.0;
3692 total_green=0.0;
3693 total_blue=0.0;
3694 total_opacity=0.0;
3695 s=p;
3696 Blur(1); Blur(2); Blur(1);
3697 s=p+src.width();
3698 Blur(2); Blur(weight); Blur(2);
3699 s=p+2*src.width();
3700 Blur(1); Blur(2); Blur(1);
3701 *q = qRgba((unsigned char)((total_red+(quantum/2))/quantum),
3702 (unsigned char)((total_green+(quantum/2))/quantum),
3703 (unsigned char)((total_blue+(quantum/2))/quantum),
3704 (unsigned char)((total_opacity+(quantum/2))/quantum));
3705 p++;
3706 q++;
3707 }
3708 p++;
3709 *q++=(*p);
3710 }
3711 }
3712 else{ // PsudeoClass source image
3713 unsigned char *p, *p2, *p3, *s;
3714 unsigned int *cTable = src.colorTable();
3715 int scanLineIdx;
3716 for(y=0; y < src.height(); ++y){
3717 scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
3718 p = (unsigned char *)src.scanLine(scanLineIdx);
3719 p2 = (unsigned char *)src.scanLine(scanLineIdx+1);
3720 p3 = (unsigned char *)src.scanLine(scanLineIdx+2);
3721 q = (unsigned int *)dest.scanLine(y);
3722 // blur this row of pixels.
3723 *q++=(*(cTable+(*p2)));
3724 for(x=1; x < src.width()-1; ++x){
3725 // compute weighted average of target pixel color components.
3726 total_red=0.0;
3727 total_green=0.0;
3728 total_blue=0.0;
3729 total_opacity=0.0;
3730 s=p;
3731 Blur256(1); Blur256(2); Blur256(1);
3732 s=p2;
3733 Blur256(2); Blur256(weight); Blur256(2);
3734 s=p3;
3735 Blur256(1); Blur256(2); Blur256(1);
3736 *q = qRgba((unsigned char)((total_red+(quantum/2))/quantum),
3737 (unsigned char)((total_green+(quantum/2))/quantum),
3738 (unsigned char)((total_blue+(quantum/2))/quantum),
3739 (unsigned char)((total_opacity+(quantum/2))/quantum));
3740 p++;
3741 p2++;
3742 p3++;
3743 q++;
3744 }
3745 p++;
3746 *q++=(*(cTable+(*p)));
3747 }
3748 }
3749 return(dest);
3750}
3751
3752// High quality, expensive HSV contrast. You can do a faster one by just
3753// taking a grayscale threshold (ie: 128) and incrementing RGB color
3754// channels above it and decrementing those below it, but this gives much
3755// better results. (mosfet 12/28/01)
3756void OImageEffect::contrastHSV(QImage &img, bool sharpen)
3757{
3758 int i, sign;
3759 unsigned int *data;
3760 int count;
3761 double brightness, scale, theta;
3762 QColor c;
3763 int h, s, v;
3764
3765 sign = sharpen ? 1 : -1;
3766 scale=0.5000000000000001;
3767 if(img.depth() > 8){
3768 count = img.width()*img.height();
3769 data = (unsigned int *)img.bits();
3770 }
3771 else{
3772 count = img.numColors();
3773 data = (unsigned int *)img.colorTable();
3774 }
3775 for(i=0; i < count; ++i){
3776 c.setRgb(data[i]);
3777 c.hsv(&h, &s, &v);
3778 brightness = v/255.0;
3779 theta=(brightness-0.5)*M_PI;
3780 brightness+=scale*(((scale*((sin(theta)+1.0)))-brightness)*sign);
3781 if (brightness > 1.0)
3782 brightness=1.0;
3783 else
3784 if (brightness < 0)
3785 brightness=0.0;
3786 v = (int)(brightness*255);
3787 c.setHsv(h, s, v);
3788 data[i] = qRgba(c.red(), c.green(), c.blue(), qAlpha(data[i]));
3789 }
3790}
3791
3792
3793
3794
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 @@
1//FIXME: Revise for Opie - do we really need such fancy stuff on PDA's?
2//FIXME: Maybe not on SL5xxx, but surely on C700 :))
3
4/* This file is part of the KDE libraries
5 Copyright (C) 1998, 1999, 2001, 2002 Daniel M. Duley <mosfet@interaccess.com>
6 (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
7 (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
8
9Redistribution and use in source and binary forms, with or without
10modification, are permitted provided that the following conditions
11are met:
12
131. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
152. Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
18
19THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30*/
31
32// $Id$
33
34#ifndef OIMAGEEFFECT_H
35#define OIMAGEEFFECT_H
36
37class QImage;
38class QSize;
39class QColor;
40
41/**
42 * This class includes various @ref QImage based graphical effects.
43 *
44 * Everything is
45 * static, so there is no need to create an instance of this class. You can
46 * just call the static methods. They are encapsulated here merely to provide
47 * a common namespace.
48 */
49
50class OImageEffect
51{
52public:
53 enum GradientType { VerticalGradient, HorizontalGradient,
54 DiagonalGradient, CrossDiagonalGradient,
55 PyramidGradient, RectangleGradient,
56 PipeCrossGradient, EllipticGradient };
57 enum RGBComponent { Red, Green, Blue, Gray, All };
58
59 enum Lighting {NorthLite, NWLite, WestLite, SWLite,
60 SouthLite, SELite, EastLite, NELite};
61
62 enum ModulationType { Intensity, Saturation, HueShift, Contrast };
63
64 enum NoiseType { UniformNoise=0, GaussianNoise, MultiplicativeGaussianNoise,
65 ImpulseNoise, LaplacianNoise, PoissonNoise};
66
67 enum RotateDirection{ Rotate90, Rotate180, Rotate270 };
68
69 /**
70 * Create a gradient from color a to color b of the specified type.
71 *
72 * @param size The desired size of the gradient.
73 * @param ca Color a
74 * @param cb Color b
75 * @param type The type of gradient.
76 * @param ncols The number of colors to use when not running on a
77 * truecolor display. The gradient will be dithered to this number of
78 * colors. Pass 0 to prevent dithering.
79 */
80 static QImage gradient(const QSize &size, const QColor &ca,
81 const QColor &cb, GradientType type, int ncols=3);
82
83 /**
84 * Create an unbalanced gradient.
85
86 * An unbalanced gradient is a gradient where the transition from
87 * color a to color b is not linear, but in this case, exponential.
88 *
89 * @param size The desired size of the gradient.
90 * @param ca Color a
91 * @param cb Color b
92 * @param type The type of gradient.
93 * @param xfactor The x decay length. Use a value between -200 and 200.
94 * @param yfactor The y decay length.
95 * @param ncols The number of colors. See OPixmapEffect:gradient.
96 */
97 static QImage unbalancedGradient(const QSize &size, const QColor &ca,
98 const QColor &cb, GradientType type, int xfactor = 100,
99 int yfactor = 100, int ncols = 3);
100
101 /**
102 * Blends a color into the destination image, using an opacity
103 * value for blending one into another. Very fast direct pixel
104 * manipulation is used.
105 *
106 * @author Karol Szwed (gallium@kde.org)
107 * @param clr source color to be blended into the destination image.
108 * @param dst destination image in which the source will be blended into.
109 * @param opacity opacity (in percent) which determines how much the source
110 * color will be blended into the destination image.
111 * @return The destination image (dst) containing the result.
112 */
113 static QImage& blend(const QColor& clr, QImage& dst, float opacity);
114
115 /**
116 * Blend the src image into the destination image, using an opacity
117 * value for blending one into another. Very fast direct pixel
118 * manipulation is used.
119 *
120 * @author Karol Szwed (gallium@kde.org)
121 * @param src source image to be blended into the destination image.
122 * @param dst destination image in which the source will be blended into.
123 * @param opacity opacity (in percent) which determines how much the source
124 * image will be blended into the destination image.
125 * @return The destination image (dst) containing the result.
126 */
127 static QImage& blend(QImage& src, QImage& dst, float opacity);
128
129 /**
130 * Blend the provided image into a background of the indicated color.
131 *
132 * @param initial_intensity this parameter takes values from -1 to 1:
133 * a) if positive: how much to fade the image in its
134 * less affected spot
135 * b) if negative: roughly indicates how much of the image
136 * remains unaffected
137 * @param bgnd indicates the color of the background to blend in
138 * @param eff lets you choose what kind of blending you like
139 * @param anti_dir blend in the opposite direction (makes no much sense
140 * with concentric blending effects)
141 * @param image must be 32bpp
142 */
143 static QImage& blend(QImage &image, float initial_intensity,
144 const QColor &bgnd, GradientType eff,
145 bool anti_dir=false);
146
147 /**
148 * Blend an image into another one, using a gradient type
149 * for blending from one to another.
150 *
151 * @param image1 source1 and result of blending
152 * @param image2 source2 of blending
153 * @param gt gradient type for blending between source1 and source2
154 * @param xf x decay length for unbalanced gradient tpye
155 * @param yf y decay length for unbalanced gradient tpye
156 */
157 static QImage& blend(QImage &image1,QImage &image2,
158 GradientType gt, int xf=100, int yf=100);
159
160 /**
161 * Blend an image into another one, using a color channel of a
162 * third image for the decision of blending from one to another.
163 *
164 * @param image1 Source 1 and result of blending
165 * @param image2 Source 2 of blending
166 * @param blendImage If the gray value of of pixel is 0, the result
167 * for this pixel is that of image1; for a gray value
168 * of 1, the pixel of image2 is used; for a value
169 * inbetween, a corresponding blending is used.
170 * @param channel The RBG channel to use for the blending decision.
171 */
172 static QImage& blend(QImage &image1, QImage &image2,
173 QImage &blendImage, RGBComponent channel);
174
175 /**
176 * Blend an image into another one, using alpha in the expected way.
177 * @author Rik Hemsley (rikkus) <rik@kde.org>
178 */
179 static bool blend(const QImage & upper, const QImage & lower, QImage & output);
180// Not yet... static bool blend(const QImage & image1, const QImage & image2, QImage & output, const QRect & destRect);
181
182 /**
183 * Blend an image into another one, using alpha in the expected way and
184 * over coordinates @p x and @p y with respect to the lower image.
185 * The output is a QImage which is the @p upper image already blended
186 * with the @p lower one, so its size will be (in general) the same than
187 * @p upper instead of the same size than @p lower like the method above.
188 * In fact, the size of @p output is like upper's one only when it can be
189 * painted on lower, if there has to be some clipping, output's size will
190 * be the clipped area and x and y will be set to the correct up-left corner
191 * where the clipped rectangle begins.
192 */
193 static bool blend(int &x, int &y, const QImage & upper, const QImage & lower, QImage & output);
194 /**
195 * Blend an image into another one, using alpha in the expected way and
196 * over coordinates @p x and @p y with respect to the lower image.
197 * The output is painted in the own @p lower image. This is an optimization
198 * of the blend method above provided by convenience.
199 */
200 static bool blendOnLower(int x, int y, const QImage & upper, const QImage & lower);
201
202 /**
203 * Modifies the intensity of a pixmap's RGB channel component.
204 *
205 * @author Daniel M. Duley (mosfet)
206 * @param image The QImage to process.
207 * @param percent Percent value. Use a negative value to dim.
208 * @param channel Which channel(s) should be modified
209 * @return The @p image, provided for convenience.
210 */
211 static QImage& channelIntensity(QImage &image, float percent,
212 RGBComponent channel);
213
214 /**
215 * Fade an image to a certain background color.
216 *
217 * The number of colors will not be changed.
218 *
219 * @param image The QImage to process.
220 * @param val The strength of the effect. 0 <= val <= 1.
221 * @param color The background color.
222 * @return Returns the @ref image(), provided for convenience.
223 */
224 static QImage& fade(QImage &img, float val, const QColor &color);
225
226
227 /**
228 * This recolors a pixmap. The most dark color will become color a,
229 * the most bright one color b, and in between.
230 *
231 * @param image A QImage to process.
232 * @param ca Color a
233 * @param cb Color b
234 */
235 static QImage& flatten(QImage &image, const QColor &ca,
236 const QColor &cb, int ncols=0);
237
238 /**
239 * Build a hash on any given @ref QImage
240 *
241 * @param image The QImage to process
242 * @param lite The hash faces the indicated lighting (cardinal poles).
243 * @param spacing How many unmodified pixels inbetween hashes.
244 * @return Returns the @ref image(), provided for convenience.
245 */
246 static QImage& hash(QImage &image, Lighting lite=NorthLite,
247 unsigned int spacing=0);
248
249 /**
250 * Either brighten or dim the image by a specified percent.
251 * For example, .50 will modify the colors by 50%.
252 *
253 * @author Daniel M. Duley (mosfet)
254 * @param image The QImage to process.
255 * @param percent The percent value. Use a negative value to dim.
256 * @return Returns The @ref image(), provided for convenience.
257 */
258 static QImage& intensity(QImage &image, float percent);
259
260 /**
261 * Modulate the image with a color channel of another image.
262 *
263 * @param image The QImage to modulate and result.
264 * @param modImage The QImage to use for modulation.
265 * @param reverse Invert the meaning of image/modImage; result is image!
266 * @param type The modulation Type to use.
267 * @param factor The modulation amplitude; with 0 no effect [-200;200].
268 * @param channel The RBG channel of image2 to use for modulation.
269 * @return Returns the @ref image(), provided for convenience.
270 */
271 static QImage& modulate(QImage &image, QImage &modImage, bool reverse,
272 ModulationType type, int factor, RGBComponent channel);
273
274 /**
275 * Convert an image to grayscale.
276 *
277 * @author Daniel M. Duley (mosfet)
278 * @param image The @ref QImage to process.
279 * @param fast Set to @p true in order to use a faster but non-photographic
280 * quality algorithm. Appropriate for things such as toolbar icons.
281 * @return Returns the @ref image(), provided for convenience.
282 */
283 static QImage& toGray(QImage &image, bool fast = false);
284
285 /**
286 * Desaturate an image evenly.
287 *
288 * @param image The QImage to process.
289 * @param desat A value between 0 and 1 setting the degree of desaturation
290 * @return Returns the @ref image(), provided for convenience.
291 */
292 static QImage& desaturate(QImage &image, float desat = 0.3);
293
294 /**
295 * Fast, but low quality contrast of an image. Also see contrastHSV.
296 *
297 * @author Daniel M. Duley (mosfet)
298 * @param image The QImage to process.
299 * @param c A contrast value between -255 to 255.
300 * @return The @ref image(), provided for convenience.
301 */
302 static QImage& contrast(QImage &image, int c);
303
304 /**
305 * Dither an image using Floyd-Steinberg dithering for low-color
306 * situations.
307 *
308 * @param image The QImage to process.
309 * @param palette The color palette to use
310 * @param size The size of the palette
311 * @return Returns the @ref image(), provided for convenience.
312 */
313 static QImage& dither(QImage &img, const QColor *palette, int size);
314
315 /**
316 * Calculate the image for a selected image, for instance a selected icon
317 * on the desktop.
318 * @param img the QImage to select
319 * @param col the selected color, usually from QColorGroup::highlight().
320 */
321 static QImage& selectedImage( QImage &img, const QColor &col );
322
323 /**
324 * High quality, expensive HSV contrast. You can do a faster one by just
325 * taking a intensity threshold (ie: 128) and incrementing RGB color
326 * channels above it and decrementing those below it, but this gives much
327 * better results.
328 *
329 * @author Daniel M. Duley (mosfet)
330 * @param img The QImage to process.
331 * @param sharpen If true sharpness is increase, (spiffed). Otherwise
332 * it is decreased, (dulled).
333 */
334 static void contrastHSV(QImage &img, bool sharpen=true);
335
336 /**
337 * Normalizes the pixel values to span the full range of color values.
338 * This is a contrast enhancement technique.
339 * @author Daniel M. Duley (mosfet)
340 */
341 static void normalize(QImage &img);
342
343 /**
344 * Performs histogram equalization on the reference
345 * image.
346 * @author Daniel M. Duley (mosfet)
347 */
348 static void equalize(QImage &img);
349
350 /**
351 * Thresholds the reference image. You can also threshold images by using
352 * ThresholdDither in the various QPixmap/QImage convert methods, but this
353 * lets you specify a threshold value.
354 *
355 * @author Daniel M. Duley (mosfet)
356 * @param img The QImage to process.
357 * @param value The threshold value.
358 */
359 static void threshold(QImage &img, unsigned int value=128);
360
361 /**
362 * Produces a 'solarization' effect seen when exposing a photographic
363 * film to light during the development process.
364 *
365 * @author Daniel M. Duley (mosfet)
366 * @param img The QImage to process.
367 * @param factor The extent of the solarization (0-99.9)
368 */
369 static void solarize(QImage &img, double factor=50.0);
370
371 /**
372 * Embosses the source image. This involves highlighting the edges
373 * and applying various other enhancements in order to get a metal
374 * effect.
375 *
376 * @author Daniel M. Duley (mosfet)
377 * @param src The QImage to process.
378 * @return The embossed image. The original is not changed.
379 */
380 static QImage emboss(QImage &src);
381
382 /**
383 * Minimizes speckle noise in the source image using the 8 hull
384 * algorithm.
385 *
386 * @author Daniel M. Duley (mosfet)
387 * @param src The QImage to process.
388 * @return The despeckled image. The original is not changed.
389 */
390 static QImage despeckle(QImage &src);
391
392 /**
393 * Produces a neat little "charcoal" effect.
394 *
395 * @author Daniel M. Duley (mosfet)
396 * @param src The QImage to process.
397 * @param factor The factor for detecting lines (0-99.0).
398 * @return The charcoal image. The original is not changed.
399 */
400 static QImage charcoal(QImage &src, double factor=50.0);
401
402 /**
403 * Rotates the image by the specified amount
404 *
405 * @author Daniel M. Duley (mosfet)
406 * @param src The QImage to process.
407 * @param r The rotate direction.
408 * @return The rotated image. The original is not changed.
409 */
410 static QImage rotate(QImage &src, RotateDirection r);
411
412 /**
413 * Scales an image using simple pixel sampling. This does not produce
414 * nearly as nice a result as QImage::smoothScale(), but has the
415 * advantage of being much faster - only a few milliseconds.
416 *
417 * @author Daniel M. Duley (mosfet)
418 * @param src The QImage to process.
419 * @param w The new width.
420 * @param h The new height.
421 * @return The scaled image. The original is not changed.
422 */
423 static QImage sample(QImage &src, int w, int h);
424
425 /**
426 * Adds noise to an image.
427 *
428 * @author Daniel M. Duley (mosfet)
429 * @param src The QImage to process.
430 * @param type The algorithm used to generate the noise.
431 * @return The image with noise added. The original is not changed.
432 */
433 static QImage addNoise(QImage &src, NoiseType type = GaussianNoise);
434
435 /**
436 * Blurs an image by convolving pixel neighborhoods.
437 *
438 * @author Daniel M. Duley (mosfet)
439 * @param src The QImage to process.
440 * @param factor The percent weight to give to the center pixel.
441 * @return The blurred image. The original is not changed.
442 */
443 static QImage blur(QImage &src, double factor=50.0);
444
445 /**
446 * Detects edges in an image using pixel neighborhoods and an edge
447 * detection mask.
448 *
449 * @author Daniel M. Duley (mosfet)
450 * @param src The QImage to process.
451 * @param factor The percent weight to give to the center pixel.
452 * @return The image with edges detected. The original is not changed.
453 */
454 static QImage edge(QImage &src, double factor=50.0);
455
456 /**
457 * Implodes an image by a specified percent.
458 *
459 * @author Daniel M. Duley (mosfet)
460 * @param src The QImage to process.
461 * @param factor The extent of the implosion.
462 * @param background An RGBA value to use for the background. After the
463 * effect some pixels may be "empty". This value is used for those pixels.
464 * @return The imploded image. The original is not changed.
465 */
466 static QImage implode(QImage &src, double factor=30.0,
467 unsigned int background = 0xFFFFFFFF);
468 /**
469 * Produces an oil painting effect.
470 *
471 * @author Daniel M. Duley (mosfet)
472 * @param src The QImage to process.
473 * @param radius The radius of the pixel neighborhood used in applying the
474 * effect.
475 * @return The new image. The original is not changed.
476 */
477 static QImage oilPaint(QImage &src, int radius=3);
478
479 /**
480 * Sharpens the pixels in the image using pixel neighborhoods.
481 *
482 * @author Daniel M. Duley (mosfet)
483 * @param src The QImage to process.
484 * @param factor The percent weight to give to the center pixel.
485 * @return The sharpened image. The original is not changed.
486 */
487 static QImage sharpen(QImage &src, double factor=30.0);
488
489 /**
490 * Randomly displaces pixels.
491 *
492 * @author Daniel M. Duley (mosfet)
493 * @param src The QImage to process.
494 * @param amount The vicinity for choosing a random pixel to swap.
495 * @return The image with pixels displaced. The original is not changed.
496 */
497 static QImage spread(QImage &src, unsigned int amount=3);
498
499 /**
500 * Shades the image using a distance light source.
501 *
502 * @author Daniel M. Duley (mosfet)
503 * @param src The QImage to process.
504 * @param color_shading If true do color shading, otherwise do grayscale.
505 * @param azimuth Determines the light source and direction.
506 * @param elevation Determines the light source and direction.
507 * @return The shaded image. The original is not changed.
508 */
509 static QImage shade(QImage &src, bool color_shading=true, double azimuth=30.0,
510 double elevation=30.0);
511 /**
512 * Swirls the image by a specified amount
513 *
514 * @author Daniel M. Duley (mosfet)
515 * @param src The QImage to process.
516 * @param degrees The tightness of the swirl.
517 * @param background An RGBA value to use for the background. After the
518 * effect some pixels may be "empty". This value is used for those pixels.
519 * @return The swirled image. The original is not changed.
520 */
521 static QImage swirl(QImage &src, double degrees=50.0, unsigned int background =
522 0xFFFFFFFF);
523
524 /**
525 * Modifies the pixels along a sine wave.
526 *
527 * @author Daniel M. Duley (mosfet)
528 * @param src The QImage to process.
529 * @param amplitude The amplitude of the sine wave.
530 * @param wavelength The frequency of the sine wave.
531 * @return The new image. The original is not changed.
532 */
533 static QImage wave(QImage &src, double amplitude=25.0, double frequency=150.0,
534 unsigned int background = 0xFFFFFFFF);
535
536private:
537
538 /**
539 * Helper function to fast calc some altered (lighten, shaded) colors
540 *
541 */
542 static unsigned int lHash(unsigned int c);
543 static unsigned int uHash(unsigned int c);
544
545 /**
546 * Helper function to find the nearest color to the RBG triplet
547 */
548 static int nearestColor( int r, int g, int b, const QColor *pal, int size );
549
550 static void hull(const int x_offset, const int y_offset, const int polarity,
551 const int width, const int height,
552 unsigned int *f, unsigned int *g);
553 static unsigned int generateNoise(unsigned int pixel, NoiseType type);
554 static unsigned int interpolateColor(QImage *image, double x, double y,
555 unsigned int background);
556};
557
558#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 @@
1/*
2                 This file is part of the Opie Project
3
4 =. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 .=l.
6           .>+-=
7 _;:,     .>    :=|. This program is free software; you can
8.> <`_,   >  .   <= redistribute it and/or modify it under
9:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
10.="- .-=="i,     .._ License as published by the Free Software
11 - .   .-<_>     .<> Foundation; either version 2 of the License,
12     ._= =}       : or (at your option) any later version.
13    .%`+i>       _;_.
14    .i_,=:_.      -<s. This program is distributed in the hope that
15     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
16    : ..    .:,     . . . without even the implied warranty of
17    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
18  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.=       =       ; Library General Public License for more
20++=   -.     .`     .: details.
21 :     =  ...= . :.=-
22 -.   .:....=;==+<; You should have received a copy of the GNU
23  -_. . .   )=.  = Library General Public License along with
24    --        :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28
29*/
30
31/* QT */
32
33#include <qcolor.h>
34#include <qheader.h>
35#include <qpainter.h>
36#include <qpixmap.h>
37
38/* OPIE */
39
40#include <opie2/olistview.h>
41
42/*======================================================================================
43 * OListView
44 *======================================================================================*/
45
46OListView::OListView( QWidget *parent, const char *name )
47 :QListView( parent, name )
48{
49 //FIXME: get from global settings and calculate ==> see oglobalsettings.*
50
51 m_alternateBackground = QColor( 238, 246, 255 );
52 m_columnSeparator = QPen( QColor( 150, 160, 170 ), 0, DotLine );
53 m_fullWidth = true;
54}
55
56OListView::~OListView()
57{
58}
59
60void OListView::setFullWidth( bool fullWidth )
61{
62 m_fullWidth = m_fullWidth;
63 #if QT_VERSION > 290
64 header()->setStretchEnabled( fullWidth, columns()-1 );
65 #endif
66}
67
68bool OListView::fullWidth() const
69{
70 return m_fullWidth;
71}
72
73int OListView::addColumn( const QString& label, int width )
74{
75 int result = QListView::addColumn( label, width );
76 #if QT_VERSION > 290
77 if (m_fullWidth) {
78 header()->setStretchEnabled( false, columns()-2 );
79 header()->setStretchEnabled( true, columns()-1 );
80 }
81 #endif
82 return result;
83}
84
85int OListView::addColumn( const QIconSet& iconset, const QString& label, int width )
86{
87 int result = QListView::addColumn( iconset, label, width );
88 #if QT_VERSION > 290
89 if (m_fullWidth) {
90 header()->setStretchEnabled( false, columns()-2 );
91 header()->setStretchEnabled( true, columns()-1 );
92 }
93 #endif
94 return result;
95}
96
97void OListView::removeColumn( int index )
98{
99 QListView::removeColumn(index);
100 #if QT_VERSION > 290
101 if ( m_fullWidth && index == columns() )
102 {
103 header()->setStretchEnabled( true, columns()-1 );
104 }
105 #endif
106}
107
108const QColor& OListView::alternateBackground() const
109{
110 return m_alternateBackground;
111}
112
113void OListView::setAlternateBackground( const QColor &c )
114{
115 m_alternateBackground = c;
116 repaint();
117}
118
119const QPen& OListView::columnSeparator() const
120{
121 return m_columnSeparator;
122}
123
124void OListView::setColumnSeparator( const QPen& p )
125{
126 m_columnSeparator = p;
127 repaint();
128}
129
130OListViewItem* OListView::childFactory()
131{
132 return new OListViewItem( this );
133}
134
135#ifndef QT_NO_DATASTREAM
136void OListView::serializeTo( QDataStream& s ) const
137{
138 #warning Caution... the binary format is still under construction...
139 qDebug( "storing OListView..." );
140
141 // store number of columns and the labels
142 s << columns();
143 for ( int i = 0; i < columns(); ++i )
144 s << columnText( i );
145
146 // calculate the number of top-level items to serialize
147 int items = 0;
148 QListViewItem* item = firstChild();
149 while ( item )
150 {
151 item = item->nextSibling();
152 items++;
153 }
154
155 // store number of items and the items itself
156 s << items;
157 item = firstChild();
158 for ( int i = 0; i < items; ++i )
159 {
160 s << *static_cast<OListViewItem*>( item );
161 item = item->nextSibling();
162 }
163
164 qDebug( "OListview stored." );
165}
166
167void OListView::serializeFrom( QDataStream& s )
168{
169 #warning Caution... the binary format is still under construction...
170 qDebug( "loading OListView..." );
171
172 int cols;
173 s >> cols;
174 qDebug( "read number of columns = %d", cols );
175
176 while ( columns() < cols ) addColumn( QString::null );
177
178 for ( int i = 0; i < cols; ++i )
179 {
180 QString coltext;
181 s >> coltext;
182 qDebug( "read text '%s' for column %d", (const char*) coltext, i );
183 setColumnText( i, coltext );
184 }
185
186 int items;
187 s >> items;
188 qDebug( "read number of items = %d", items );
189
190 for ( int i = 0; i < items; ++i )
191 {
192 OListViewItem* item = childFactory();
193 s >> *item;
194 }
195
196 qDebug( "OListView loaded." );
197
198}
199
200QDataStream& operator<<( QDataStream& s, const OListView& lv )
201{
202 lv.serializeTo( s );
203}
204
205QDataStream& operator>>( QDataStream& s, OListView& lv )
206{
207 lv.serializeFrom( s );
208}
209#endif // QT_NO_DATASTREAM
210
211/*======================================================================================
212 * OListViewItem
213 *======================================================================================*/
214
215OListViewItem::OListViewItem(QListView *parent)
216 : QListViewItem(parent)
217{
218 init();
219}
220
221OListViewItem::OListViewItem(QListViewItem *parent)
222 : QListViewItem(parent)
223{
224 init();
225}
226
227OListViewItem::OListViewItem(QListView *parent, QListViewItem *after)
228 : QListViewItem(parent, after)
229{
230 init();
231}
232
233OListViewItem::OListViewItem(QListViewItem *parent, QListViewItem *after)
234 : QListViewItem(parent, after)
235{
236 init();
237}
238
239OListViewItem::OListViewItem(QListView *parent,
240 QString label1, QString label2, QString label3, QString label4,
241 QString label5, QString label6, QString label7, QString label8)
242 : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8)
243{
244 init();
245}
246
247OListViewItem::OListViewItem(QListViewItem *parent,
248 QString label1, QString label2, QString label3, QString label4,
249 QString label5, QString label6, QString label7, QString label8)
250 : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8)
251{
252 init();
253}
254
255OListViewItem::OListViewItem(QListView *parent, QListViewItem *after,
256 QString label1, QString label2, QString label3, QString label4,
257 QString label5, QString label6, QString label7, QString label8)
258 : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8)
259{
260 init();
261}
262
263OListViewItem::OListViewItem(QListViewItem *parent, QListViewItem *after,
264 QString label1, QString label2, QString label3, QString label4,
265 QString label5, QString label6, QString label7, QString label8)
266 : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8)
267{
268 init();
269}
270
271OListViewItem::~OListViewItem()
272{
273}
274
275void OListViewItem::init()
276{
277 m_known = false;
278}
279
280const QColor &OListViewItem::backgroundColor()
281{
282 return isAlternate() ? static_cast<OListView*>(listView())->alternateBackground() :
283 listView()->viewport()->colorGroup().base();
284}
285
286bool OListViewItem::isAlternate()
287{
288 OListView *lv = static_cast<OListView*>( listView() );
289
290 // check if the item above is an OListViewItem
291 OListViewItem *above = static_cast<OListViewItem*>( itemAbove() );
292 /*if (! itemAbove()->inherits( "OListViewItem" )) return false;*/
293
294 // check if we have a valid alternate background color
295 if (!(lv && lv->alternateBackground().isValid())) return false;
296
297 m_known = above ? above->m_known : true;
298 if (m_known)
299 {
300 m_odd = above ? !above->m_odd : false;
301 }
302 else
303 {
304 OListViewItem *item;
305 bool previous = true;
306 if (parent())
307 {
308 item = static_cast<OListViewItem *>(parent());
309 if ( item /*&& item->inherits( "OListViewItem" )*/ ) previous = item->m_odd;
310 item = static_cast<OListViewItem *>(parent()->firstChild());
311 /* if ( !item.inherits( "OListViewItem" ) item = 0; */
312 }
313 else
314 {
315 item = static_cast<OListViewItem *>(lv->firstChild());
316 }
317
318 while(item)
319 {
320 item->m_odd = previous = !previous;
321 item->m_known = true;
322 item = static_cast<OListViewItem *>(item->nextSibling());
323 /* if (!item.inherits( "OListViewItem" ) ) break; */
324 }
325 }
326 return m_odd;
327}
328
329void OListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment)
330{
331 QColorGroup _cg = cg;
332 const QPixmap *pm = listView()->viewport()->backgroundPixmap();
333 if (pm && !pm->isNull())
334 {
335 _cg.setBrush( QColorGroup::Base, QBrush(backgroundColor(), *pm) );
336 p->setBrushOrigin( -listView()->contentsX(), -listView()->contentsY() );
337 }
338 else if ( isAlternate() )
339 {
340 _cg.setColor( QColorGroup::Base, static_cast<OListView*>( listView() )->alternateBackground() );
341 }
342 QListViewItem::paintCell( p, _cg, column, width, alignment );
343
344 //FIXME: Use styling here!
345
346 const QPen& pen = static_cast<OListView*>( listView() )->columnSeparator();
347 p->setPen( pen );
348 p->drawLine( width-1, 0, width-1, height() );
349}
350
351OListViewItem* OListViewItem::childFactory()
352{
353 return new OListViewItem( this );
354}
355
356#ifndef QT_NO_DATASTREAM
357void OListViewItem::serializeTo( QDataStream& s ) const
358{
359 #warning Caution... the binary format is still under construction...
360 qDebug( "storing OListViewItem..." );
361
362 // store item text
363 for ( int i = 0; i < listView()->columns(); ++i )
364 {
365 s << text( i );
366 }
367
368 // calculate the number of children to serialize
369 int items = 0;
370 QListViewItem* item = firstChild();
371 while ( item )
372 {
373 item = item->nextSibling();
374 items++;
375 }
376
377 // store number of items and the items itself
378 s << items;
379 item = firstChild();
380 for ( int i = 0; i < items; ++i )
381 {
382 s << *static_cast<OListViewItem*>( item );
383 item = item->nextSibling();
384 }
385
386 qDebug( "OListviewItem stored." );
387}
388void OListViewItem::serializeFrom( QDataStream& s )
389{
390 #warning Caution... the binary format is still under construction...
391 qDebug( "loading OListViewItem..." );
392
393 for ( int i = 0; i < listView()->columns(); ++i )
394 {
395 QString coltext;
396 s >> coltext;
397 qDebug( "read text '%s' for column %d", (const char*) coltext, i );
398 setText( i, coltext );
399 }
400
401 int items;
402 s >> items;
403 qDebug( "read number of items = %d", items );
404
405 for ( int i = 0; i < items; ++i )
406 {
407 OListViewItem* item = childFactory();
408 s >> (*item);
409 }
410
411 qDebug( "OListViewItem loaded." );
412}
413
414QDataStream& operator<<( QDataStream& s, const OListViewItem& lvi )
415{
416 lvi.serializeTo( s );
417}
418
419QDataStream& operator>>( QDataStream& s, OListViewItem& lvi )
420{
421 lvi.serializeFrom( s );
422}
423#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 @@
1/*
2                 This file is part of the Opie Project
3
4 =. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 .=l.
6           .>+-=
7 _;:,     .>    :=|. This program is free software; you can
8.> <`_,   >  .   <= redistribute it and/or modify it under
9:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
10.="- .-=="i,     .._ License as published by the Free Software
11 - .   .-<_>     .<> Foundation; either version 2 of the License,
12     ._= =}       : or (at your option) any later version.
13    .%`+i>       _;_.
14    .i_,=:_.      -<s. This program is distributed in the hope that
15     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
16    : ..    .:,     . . . without even the implied warranty of
17    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
18  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.=       =       ; Library General Public License for more
20++=   -.     .`     .: details.
21 :     =  ...= . :.=-
22 -.   .:....=;==+<; You should have received a copy of the GNU
23  -_. . .   )=.  = Library General Public License along with
24    --        :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28
29*/
30
31#ifndef OLISTVIEW_H
32#define OLISTVIEW_H
33
34#include <qcolor.h>
35#include <qlistview.h>
36#include <qpen.h>
37#include <qdatastream.h>
38
39class OListViewItem;
40
41/**
42 * A @ref QListView variant featuring visual and functional enhancements
43 * like an alternate background for odd rows, an autostretch mode
44 * for the width of the widget ( >= Qt 3 only ) and persistence capabilities.
45 *
46 * @author Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
47 * @short OListView list/tree widget.
48 */
49 class OListView: public QListView
50{
51 public:
52 /**
53 * Constructor.
54 *
55 * The parameters @p parent and @p name are handled by
56 * @ref QListView, as usual.
57 */
58 OListView ( QWidget *parent = 0, const char *name = 0 );
59
60 /**
61 * Destructor.
62 */
63 virtual ~OListView();
64
65 /**
66 * Let the last column fit exactly all the available width.
67 */
68 void setFullWidth( bool fullWidth );
69
70 /**
71 * Returns whether the last column is set to fit the available width.
72 */
73 bool fullWidth() const;
74
75 /**
76 * Reimplemented for full width support
77 */
78 virtual int addColumn( const QString& label, int width = -1 );
79
80 /**
81 * Reimplemented for full width support
82 */
83 virtual int addColumn( const QIconSet& iconset, const QString& label, int width = -1 );
84
85 /**
86 * Reimplemented for full width support
87 */
88 virtual void removeColumn(int index);
89
90 /**
91 * sets the alternate background background color.
92 * This only has an effect if the items are OListViewItems
93 *
94 * @param c the color to use for every other item. Set to an invalid
95 * color to disable alternate colors.
96 */
97 void setAlternateBackground( const QColor &c );
98
99 /**
100 * sets the column separator pen.
101 *
102 * @param p the pen used to draw the column separator.
103 */
104 void setColumnSeparator( const QPen &p );
105
106 /**
107 * @return the alternate background color
108 */
109 const QColor& alternateBackground() const;
110
111 /**
112 * @return the column separator pen
113 */
114 const QPen& columnSeparator() const;
115
116 /**
117 * create a list view item as child of this object
118 * @return the new object
119 */
120 virtual OListViewItem* childFactory();
121
122 #ifndef QT_NO_DATASTREAM
123 /**
124 * serialize this object to a @ref QDataStream
125 * @param s the stream used to serialize this object.
126 */
127 virtual void serializeTo( QDataStream& s ) const;
128
129 /**
130 * serialize this object from a @ref QDataStream
131 * @param s the stream used to serialize this object.
132 */
133 virtual void serializeFrom( QDataStream& s );
134 #endif
135
136 private:
137 QColor m_alternateBackground;
138 bool m_fullWidth;
139 QPen m_columnSeparator;
140};
141
142#ifndef QT_NO_DATASTREAM
143/**
144 * \relates QListView
145 * Writes a listview to the stream and returns a reference to the stream.
146 */
147QDataStream& operator<<( QDataStream& s, const OListView& lv );
148/**
149 * \relates QListView
150 * Reads a listview from the stream and returns a reference to the stream.
151 */
152QDataStream& operator>>( QDataStream& s, OListView& lv );
153#endif // QT_NO_DATASTREAM
154
155//****************************** OListViewItem ******************************************************************
156
157class OListViewItem: public QListViewItem
158{
159 public:
160 OListViewItem( QListView * parent );
161 OListViewItem( QListViewItem * parent );
162 OListViewItem( QListView * parent, QListViewItem * after );
163 OListViewItem( QListViewItem * parent, QListViewItem * after );
164
165 OListViewItem( QListView * parent,
166 QString, QString = QString::null,
167 QString = QString::null, QString = QString::null,
168 QString = QString::null, QString = QString::null,
169 QString = QString::null, QString = QString::null );
170
171 OListViewItem( QListViewItem * parent,
172 QString, QString = QString::null,
173 QString = QString::null, QString = QString::null,
174 QString = QString::null, QString = QString::null,
175 QString = QString::null, QString = QString::null );
176
177 OListViewItem( QListView * parent, QListViewItem * after,
178 QString, QString = QString::null,
179 QString = QString::null, QString = QString::null,
180 QString = QString::null, QString = QString::null,
181 QString = QString::null, QString = QString::null );
182
183 OListViewItem( QListViewItem * parent, QListViewItem * after,
184 QString, QString = QString::null,
185 QString = QString::null, QString = QString::null,
186 QString = QString::null, QString = QString::null,
187 QString = QString::null, QString = QString::null );
188
189 virtual ~OListViewItem();
190
191 const QColor& backgroundColor();
192 bool isAlternate();
193 void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment );
194 void init();
195
196 /**
197 * create a list view item as child of this object
198 * @return the new object
199 */
200 virtual OListViewItem* childFactory();
201
202 #ifndef QT_NO_DATASTREAM
203 /**
204 * serialize this object to or from a @ref QDataStream
205 * @param s the stream used to serialize this object.
206 */
207 virtual void serializeTo( QDataStream& s ) const;
208
209 /**
210 * serialize this object to or from a @ref QDataStream
211 * @param s the stream used to serialize this object.
212 */
213 virtual void serializeFrom( QDataStream& s );
214 #endif
215
216 private:
217 bool m_known;
218 bool m_odd;
219};
220
221#ifndef QT_NO_DATASTREAM
222/**
223 * \relates QListViewItem
224 * Writes a listview item and all subitems recursively to the stream
225 * and returns a reference to the stream.
226 */
227QDataStream& operator<<( QDataStream &s, const OListViewItem& lvi );
228/**
229 * \relates QListViewItem
230 * Reads a listview item from the stream and returns a reference to the stream.
231 */
232QDataStream& operator>>( QDataStream &s, OListViewItem& lvi );
233#endif // QT_NO_DATASTREAM
234
235#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 @@
1TEMPLATE = lib
2CONFIG += qt warn_on debug
3DESTDIR = $(QTDIR)/lib
4HEADERS = ocompletionbox.h \
5 ocombobox.h \
6 oeditlistbox.h \
7 olineedit.h \
8 olistview.h \
9 oimageeffect.h \
10 opixmapeffect.h \
11 opopupmenu.h \
12 opixmapprovider.h \
13 oselector.h \
14 oversatileview.h \
15 oversatileviewitem.h \
16 #ojanuswidget.h \
17 odialog.h \
18 oseparator.h
19
20SOURCES = ocompletionbox.cpp \
21 ocombobox.cpp \
22 oeditlistbox.cpp \
23 olineedit.cpp \
24 olistview.cpp \
25 oimageeffect.cpp \
26 opixmapeffect.cpp \
27 opopupmenu.cpp \
28 opixmapprovider.cpp \
29 oselector.cpp \
30 oversatileview.cpp \
31 oversatileviewitem.cpp \
32 #ojanuswidget.cpp \
33 odialog.cpp \
34 oseparator.cpp
35
36INTERFACES =
37TARGET = opieui2
38VERSION = 1.8.1
39INCLUDEPATH += $(OPIEDIR)/include
40DEPENDPATH += $(OPIEDIR)/include
41LIBS += -lopiecore2
42MOC_DIR = moc
43OBJECTS_DIR = obj
44
45include ( $(OPIEDIR)/include.pro )
46
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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
3 (C) 1998, 1999 Daniel M. Duley <mosfet@kde.org>
4 (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
5
6*/
7
8// $Id$
9
10/* QT */
11
12#include <qimage.h>
13#include <qpainter.h>
14
15/* OPIE */
16
17#include <opie2/opixmapeffect.h>
18#include <opie2/oimageeffect.h>
19
20//======================================================================
21//
22// Gradient effects
23//
24//======================================================================
25
26
27OPixmap& OPixmapEffect::gradient(OPixmap &pixmap, const QColor &ca,
28 const QColor &cb, GradientType eff, int ncols)
29{
30 if(pixmap.depth() > 8 &&
31 (eff == VerticalGradient || eff == HorizontalGradient)) {
32
33 int rDiff, gDiff, bDiff;
34 int rca, gca, bca /*, rcb, gcb, bcb*/;
35
36 register int x, y;
37
38 rDiff = (/*rcb = */ cb.red()) - (rca = ca.red());
39 gDiff = (/*gcb = */ cb.green()) - (gca = ca.green());
40 bDiff = (/*bcb = */ cb.blue()) - (bca = ca.blue());
41
42 register int rl = rca << 16;
43 register int gl = gca << 16;
44 register int bl = bca << 16;
45
46 int rcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * rDiff;
47 int gcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * gDiff;
48 int bcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * bDiff;
49
50 QPainter p(&pixmap);
51
52 // these for-loops could be merged, but the if's in the inner loop
53 // would make it slow
54 switch(eff) {
55 case VerticalGradient:
56 for ( y = 0; y < pixmap.height(); y++ ) {
57 rl += rcdelta;
58 gl += gcdelta;
59 bl += bcdelta;
60
61 p.setPen(QColor(rl>>16, gl>>16, bl>>16));
62 p.drawLine(0, y, pixmap.width()-1, y);
63 }
64 break;
65 case HorizontalGradient:
66 for( x = 0; x < pixmap.width(); x++) {
67 rl += rcdelta;
68 gl += gcdelta;
69 bl += bcdelta;
70
71 p.setPen(QColor(rl>>16, gl>>16, bl>>16));
72 p.drawLine(x, 0, x, pixmap.height()-1);
73 }
74 break;
75 default:
76 ;
77 }
78 }
79 else {
80 QImage image = OImageEffect::gradient(pixmap.size(), ca, cb,
81 (OImageEffect::GradientType) eff, ncols);
82 pixmap.convertFromImage(image);
83 }
84
85 return pixmap;
86}
87
88
89// -----------------------------------------------------------------------------
90
91OPixmap& OPixmapEffect::unbalancedGradient(OPixmap &pixmap, const QColor &ca,
92 const QColor &cb, GradientType eff, int xfactor, int yfactor,
93 int ncols)
94{
95 QImage image = OImageEffect::unbalancedGradient(pixmap.size(), ca, cb,
96 (OImageEffect::GradientType) eff,
97 xfactor, yfactor, ncols);
98 pixmap.convertFromImage(image);
99
100 return pixmap;
101}
102
103
104//======================================================================
105//
106// Intensity effects
107//
108//======================================================================
109
110
111
112OPixmap& OPixmapEffect::intensity(OPixmap &pixmap, float percent)
113{
114 QImage image = pixmap.convertToImage();
115 OImageEffect::intensity(image, percent);
116 pixmap.convertFromImage(image);
117
118 return pixmap;
119}
120
121
122// -----------------------------------------------------------------------------
123
124OPixmap& OPixmapEffect::channelIntensity(OPixmap &pixmap, float percent,
125 RGBComponent channel)
126{
127 QImage image = pixmap.convertToImage();
128 OImageEffect::channelIntensity(image, percent,
129 (OImageEffect::RGBComponent) channel);
130 pixmap.convertFromImage(image);
131
132 return pixmap;
133}
134
135
136//======================================================================
137//
138// Blend effects
139//
140//======================================================================
141
142
143OPixmap& OPixmapEffect::blend(OPixmap &pixmap, float initial_intensity,
144 const QColor &bgnd, GradientType eff,
145 bool anti_dir, int ncols)
146{
147
148 QImage image = pixmap.convertToImage();
149 if (image.depth() <=8)
150 image = image.convertDepth(32); //Sloww..
151
152 OImageEffect::blend(image, initial_intensity, bgnd,
153 (OImageEffect::GradientType) eff, anti_dir);
154
155 unsigned int tmp;
156
157 if(pixmap.depth() <= 8 ) {
158 if ( ncols < 2 || ncols > 256 )
159 ncols = 3;
160 QColor *dPal = new QColor[ncols];
161 for (int i=0; i<ncols; i++) {
162 tmp = 0 + 255 * i / ( ncols - 1 );
163 dPal[i].setRgb ( tmp, tmp, tmp );
164 }
165 OImageEffect::dither(image, dPal, ncols);
166 pixmap.convertFromImage(image);
167 delete [] dPal;
168 }
169 else
170 pixmap.convertFromImage(image);
171
172 return pixmap;
173}
174
175
176//======================================================================
177//
178// Hash effects
179//
180//======================================================================
181
182OPixmap& OPixmapEffect::hash(OPixmap &pixmap, Lighting lite,
183 unsigned int spacing, int ncols)
184{
185 QImage image = pixmap.convertToImage();
186 OImageEffect::hash(image, (OImageEffect::Lighting) lite, spacing);
187
188 unsigned int tmp;
189
190 if(pixmap.depth() <= 8 ) {
191 if ( ncols < 2 || ncols > 256 )
192 ncols = 3;
193 QColor *dPal = new QColor[ncols];
194 for (int i=0; i<ncols; i++) {
195 tmp = 0 + 255 * i / ( ncols - 1 );
196 dPal[i].setRgb ( tmp, tmp, tmp );
197 }
198 OImageEffect::dither(image, dPal, ncols);
199 pixmap.convertFromImage(image);
200 delete [] dPal;
201 }
202 else
203 pixmap.convertFromImage(image);
204
205 return pixmap;
206}
207
208
209//======================================================================
210//
211// Pattern effects
212//
213//======================================================================
214
215#if 0
216void OPixmapEffect::pattern(OPixmap &pixmap, const QColor &ca,
217 const QColor &cb, unsigned pat[8])
218{
219 QImage img = pattern(pixmap.size(), ca, cb, pat);
220 pixmap.convertFromImage(img);
221}
222#endif
223
224// -----------------------------------------------------------------------------
225
226OPixmap OPixmapEffect::pattern(const OPixmap& pmtile, QSize size,
227 const QColor &ca, const QColor &cb, int ncols)
228{
229 if (pmtile.depth() > 8)
230 ncols = 0;
231
232 QImage img = pmtile.convertToImage();
233 OImageEffect::flatten(img, ca, cb, ncols);
234 OPixmap pixmap;
235 pixmap.convertFromImage(img);
236
237 return OPixmapEffect::createTiled(pixmap, size);
238}
239
240
241// -----------------------------------------------------------------------------
242
243OPixmap OPixmapEffect::createTiled(const OPixmap& pixmap, QSize size)
244{
245 OPixmap pix;
246
247 QPainter p(&pix);
248 p.drawTiledPixmap(0, 0, size.width(), size.height(), pixmap);
249
250 return pix;
251}
252
253
254//======================================================================
255//
256// Fade effects
257//
258//======================================================================
259
260OPixmap& OPixmapEffect::fade(OPixmap &pixmap, double val, const QColor &color)
261{
262 QImage img = pixmap.convertToImage();
263 OImageEffect::fade(img, val, color);
264 pixmap.convertFromImage(img);
265
266 return pixmap;
267}
268
269
270// -----------------------------------------------------------------------------
271OPixmap& OPixmapEffect::toGray(OPixmap &pixmap, bool fast)
272{
273 QImage img = pixmap.convertToImage();
274 OImageEffect::toGray(img, fast);
275 pixmap.convertFromImage(img);
276
277 return pixmap;
278}
279
280// -----------------------------------------------------------------------------
281OPixmap& OPixmapEffect::desaturate(OPixmap &pixmap, float desat)
282{
283 QImage img = pixmap.convertToImage();
284 OImageEffect::desaturate(img, desat);
285 pixmap.convertFromImage(img);
286
287 return pixmap;
288}
289// -----------------------------------------------------------------------------
290OPixmap& OPixmapEffect::contrast(OPixmap &pixmap, int c)
291{
292 QImage img = pixmap.convertToImage();
293 OImageEffect::contrast(img, c);
294 pixmap.convertFromImage(img);
295
296 return pixmap;
297}
298
299//======================================================================
300//
301// Dither effects
302//
303//======================================================================
304
305// -----------------------------------------------------------------------------
306OPixmap& OPixmapEffect::dither(OPixmap &pixmap, const QColor *palette, int size)
307{
308 QImage img = pixmap.convertToImage();
309 OImageEffect::dither(img, palette, size);
310 pixmap.convertFromImage(img);
311
312 return pixmap;
313}
314
315//======================================================================
316//
317// Other effects
318//
319//======================================================================
320
321OPixmap OPixmapEffect::selectedPixmap( const OPixmap &pix, const QColor &col )
322{
323 QImage img = pix.convertToImage();
324 OImageEffect::selectedImage(img, col);
325 OPixmap outPix;
326 outPix.convertFromImage(img);
327 return outPix;
328}
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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
3 (C) 1998, 1999 Daniel M. Duley <mosfet@kde.org>
4 (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
5
6*/
7
8// $Id$
9
10#ifndef __OPIXMAP_EFFECT_H
11#define __OPIXMAP_EFFECT_H
12
13
14#include <qsize.h>
15typedef QPixmap OPixmap;
16class QColor;
17
18/**
19 * This class includes various pixmap-based graphical effects.
20 *
21 * Everything is
22 * static, so there is no need to create an instance of this class. You can
23 * just call the static methods. They are encapsulated here merely to provide
24 * a common namespace.
25 */
26class OPixmapEffect
27{
28public:
29 enum GradientType { VerticalGradient, HorizontalGradient,
30 DiagonalGradient, CrossDiagonalGradient,
31 PyramidGradient, RectangleGradient,
32 PipeCrossGradient, EllipticGradient };
33 enum RGBComponent { Red, Green, Blue };
34
35 enum Lighting {NorthLite, NWLite, WestLite, SWLite,
36 SouthLite, SELite, EastLite, NELite};
37
38 /**
39 * Creates a gradient from color a to color b of the specified type.
40 *
41 * @param pixmap The pixmap to process.
42 * @param ca Color a.
43 * @param cb Color b.
44 * @param type The type of gradient.
45 * @param ncols The number of colors to use when not running on a
46 * truecolor display. The gradient will be dithered to this number of
47 * colors. Pass 0 to prevent dithering.
48 * @return Returns the generated pixmap, for convenience.
49 */
50 static OPixmap& gradient(OPixmap& pixmap, const QColor &ca, const QColor &cb,
51 GradientType type, int ncols=3);
52
53 /**
54 * Creates an unbalanced gradient.
55 *
56 * An unbalanced gradient is a gradient where the transition from
57 * color a to color b is not linear, but in this case, exponential.
58 *
59 * @param pixmap The pixmap that should be written.
60 * @param ca Color a.
61 * @param cb Color b.
62 * @param type The type of gradient.
63 * @param xfactor The x decay length. Use a value between -200 and 200.
64 * @param yfactor The y decay length.
65 * @param ncols The number of colors. See #gradient.
66 * @return The generated pixmap, for convencience.
67 */
68 static OPixmap& unbalancedGradient(OPixmap& pixmap, const QColor &ca,
69 const QColor &cb, GradientType type, int xfactor = 100,
70 int yfactor = 100, int ncols=3);
71
72 /**
73 * Creates a pixmap of a given size with the given pixmap.
74 *
75 * if the
76 * given size is bigger than the size of the pixmap, the pixmap is
77 * tiled.
78 *
79 * @param pixmap This is the source pixmap
80 * @param size The size the new pixmap should have.
81 * @return The generated, tiled pixmap.
82 */
83 static OPixmap createTiled(const OPixmap& pixmap, QSize size);
84
85 /**
86 * Either brightens or dims a pixmap by a specified ratio.
87 *
88 * @param pixmap The pixmap to process.
89 * @param ratio The ratio to use. Use negative value to dim.
90 * @return Returns The @ref pixmap(), provided for convenience.
91 */
92 static OPixmap& intensity(OPixmap& pixmap, float ratio);
93
94 /**
95 * Modifies the intensity of a pixmap's RGB channel component.
96 *
97 * @param pixmap The pixmap to process.
98 * @param ratio value. Use negative value to dim.
99 * @param channel Which channel(s) should be modified
100 * @return Returns the @ref pixmap(), provided for convenience.
101 */
102 static OPixmap& channelIntensity(OPixmap& pixmap, float ratio,
103 RGBComponent channel);
104
105 /**
106 * Blends the provided pixmap into a background of the indicated color.
107 *
108 * @param pixmap The pixmap to process.
109 * @param initial_intensity this parameter takes values from -1 to 1:
110 * @li If positive, it tells how much to fade the image in its
111 * less affected spot.
112 * @li If negative, it tells roughly indicates how much of the image
113 * remains unaffected
114 * @param bgnd Indicates the color of the background to blend in.
115 * @param eff Lets you choose what kind of blending you like.
116 * @param anti_dir Blend in the opposite direction (makes no much sense
117 * with concentric blending effects).
118 * @return Returns the @ref pixmap(), provided for convenience.
119 */
120 static OPixmap& blend(OPixmap& pixmap, float initial_intensity,
121 const QColor &bgnd, GradientType eff,
122 bool anti_dir=false, int ncols=3);
123
124 /**
125 * Builds a hash on any given pixmap.
126 *
127 * @param pixmap The pixmap to process.
128 * @param lite The hash faces the indicated lighting (cardinal poles)
129 * @param spacing How many unmodified pixels inbetween hashes.
130 * @return Returns The @ref pixmap(), provided for convenience.
131 */
132 static OPixmap& hash(OPixmap& pixmap, Lighting lite=NorthLite,
133 unsigned int spacing=0, int ncols=3);
134
135 /**
136 * Creates a pattern from a pixmap.
137 *
138 * The given pixmap is "flattened"
139 * between color a to color b.
140 *
141 * @param pixmap The pixmap to process.
142 * @param ca Color a.
143 * @param cb Color b.
144 * @param ncols The number of colors to use. The image will be
145 * dithered to this depth. Pass zero to prevent dithering.
146 * @return The @ref pixmap(), provided for convenience.
147 */
148 static OPixmap pattern(const OPixmap& pixmap, QSize size,
149 const QColor &ca, const QColor &cb, int ncols=8);
150
151 /**
152 * Recolors a pixmap.
153 *
154 * The most dark color will become color a,
155 * the most bright one color b, and in between.
156 *
157 * @param pixmap The pixmap to process.
158 * @param ca Color a.
159 * @param cb Color b.
160 * @param ncols The number of colors to use. Pass zero to prevent
161 * dithering.
162 * @return Returns the @ref pixmap(), provided for convenience.
163 */
164 static OPixmap& fade(OPixmap& pixmap, double val, const QColor &color);
165
166 /**
167 * Converts a pixmap to grayscale.
168 *
169 * @param pixmap The pixmap to process.
170 * @param fast Set to @p true in order to use a faster but non-photographic
171 * quality algorithm. Appropriate for things such as toolbar icons.
172 * @return Returns the @ref pixmap(), provided for convenience.
173 */
174 static OPixmap& toGray(OPixmap& pixmap, bool fast=false);
175
176 /**
177 * Desaturates a pixmap.
178 *
179 * @param pixmap The pixmap to process.
180 * @param desat A value between 0 and 1 setting the degree of desaturation
181 * @return Returns The @ref pixmap(), provided for convenience.
182 */
183 static OPixmap& desaturate(OPixmap& pixmap, float desat = 0.3);
184
185 /**
186 * Modifies the contrast of a pixmap.
187 *
188 * @param pixmap The pixmap to process.
189 * @param c A contrast value between -255 and 255.
190 * @return Returns the @ref pixmap(), provided for convenience.
191 */
192 static OPixmap& contrast(OPixmap& pixmap, int c);
193
194 /**
195 * Dithers a pixmap using Floyd-Steinberg dithering for low-color
196 * situations.
197 *
198 * @param pixmap The pixmap to process.
199 * @param palette The color palette to use.
200 * @param size The size of the palette.
201 * @return Returns the @ref pixmap(), provided for convenience.
202 */
203 static OPixmap& dither(OPixmap &pixmap, const QColor *palette, int size);
204
205 /**
206 * Calculate a 'selected' pixmap, for instance a selected icon
207 * on the desktop.
208 * @param pixmap the pixmap to select
209 * @param col the selected color, usually from QColorGroup::highlight().
210 */
211 static OPixmap selectedPixmap( const OPixmap &pixmap, const QColor &col );
212};
213
214
215#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 @@
1/* This file is part of the KDE libraries
2
3 Copyright (c) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License (LGPL) as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21#include <opie2/opixmapprovider.h>
22
23OPixmapProvider::~OPixmapProvider() {}
24
25void OPixmapProvider::virtual_hook( int , void* )
26{ /*BASE::virtual_hook( id, data );*/ }
27
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 @@
1/* This file is part of the KDE libraries
2
3 Copyright (c) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License (LGPL) as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21#ifndef OPIXMAPPROVIDER_H
22#define OPIXMAPPROVIDER_H
23
24#include <qpixmap.h>
25
26/**
27 * A tiny abstract class with just one method:
28 * @ref pixmapFor()
29 *
30 * It will be called whenever an icon is searched for @p text.
31 *
32 * Used e.g. by @ref KHistoryCombo
33 *
34 * @author Carsten Pfeiffer <pfeiffer@kde.org>
35 * @short an abstract interface for looking up icons
36 */
37class OPixmapProvider
38{
39public:
40 virtual ~OPixmapProvider();
41 /**
42 * You may subclass this and return a pixmap of size @p size for @p text.
43 * @param text the text that is associated with the pixmap
44 * @param size the size of the icon in pixels, 0 for defaylt size.
45 * See @ref KIcon::StdSize.
46 * @return the pixmap for the arguments, or null if there is none
47 */
48 virtual QPixmap pixmapFor( const QString& text, int size = 0 ) = 0;
49protected:
50 virtual void virtual_hook( int id, void* data );
51};
52
53
54#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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 2000 Daniel M. Duley <mosfet@kde.org>
3 Copyright (C) 2002 Hamish Rodda <meddie@yoyo.its.monash.edu.au>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20/* QT */
21
22#include <qapplication.h>
23#include <qcursor.h>
24#include <qpainter.h>
25#include <qdrawutil.h>
26#include <qtimer.h>
27#include <qfont.h>
28#include <qfontmetrics.h>
29#include <qregexp.h>
30#include <qstyle.h>
31
32/* OPIE */
33
34#include <opie2/opopupmenu.h>
35#include <opie2/oconfig.h>
36
37OPopupTitle::OPopupTitle(QWidget *parent, const char *name)
38 : QWidget(parent, name)
39{
40 setMinimumSize(16, fontMetrics().height()+8);
41}
42
43OPopupTitle::OPopupTitle(OPixmapEffect::GradientType /* gradient */,
44 const QColor &/* color */, const QColor &/* textColor */,
45 QWidget *parent, const char *name)
46 : QWidget(parent, name)
47{
48 setMinimumSize(16, fontMetrics().height()+8);
49}
50
51OPopupTitle::OPopupTitle(const OPixmap & /* background */, const QColor &/* color */,
52 const QColor &/* textColor */, QWidget *parent,
53 const char *name)
54 : QWidget(parent, name)
55{
56 setMinimumSize(16, fontMetrics().height()+8);
57}
58
59void OPopupTitle::setTitle(const QString &text, const QPixmap *icon)
60{
61 titleStr = text;
62 if (icon)
63 miniicon = *icon;
64 else
65 miniicon.resize(0, 0);
66
67 int w = miniicon.width()+fontMetrics().width(titleStr);
68 int h = QMAX( fontMetrics().height(), miniicon.height() );
69 setMinimumSize( w+16, h+8 );
70}
71
72void OPopupTitle::setText( const QString &text )
73{
74 titleStr = text;
75 int w = miniicon.width()+fontMetrics().width(titleStr);
76 int h = QMAX( fontMetrics().height(), miniicon.height() );
77 setMinimumSize( w+16, h+8 );
78}
79
80void OPopupTitle::setIcon( const QPixmap &pix )
81{
82 miniicon = pix;
83 int w = miniicon.width()+fontMetrics().width(titleStr);
84 int h = QMAX( fontMetrics().height(), miniicon.height() );
85 setMinimumSize( w+16, h+8 );
86}
87
88void OPopupTitle::paintEvent(QPaintEvent *)
89{
90 QRect r(rect());
91 QPainter p(this);
92 #if QT_VERSION > 290
93 qApp->style().drawPrimitive(QStyle::PE_HeaderSection, &p, r, palette().active());
94 #else
95 #warning OPopupMenu is not fully functional on Qt2
96 #endif
97
98 if (!miniicon.isNull())
99 p.drawPixmap(4, (r.height()-miniicon.height())/2, miniicon);
100
101 if (!titleStr.isNull())
102 {
103 p.setPen(palette().active().text());
104 QFont f = p.font();
105 f.setBold(true);
106 p.setFont(f);
107 if(!miniicon.isNull())
108 {
109 p.drawText(miniicon.width()+8, 0, width()-(miniicon.width()+8),
110 height(), AlignLeft | AlignVCenter | SingleLine,
111 titleStr);
112 }
113 else
114 {
115 p.drawText(0, 0, width(), height(),
116 AlignCenter | SingleLine, titleStr);
117 }
118 }
119
120 p.setPen(palette().active().highlight());
121 p.drawLine(0, 0, r.right(), 0);
122}
123
124QSize OPopupTitle::sizeHint() const
125{
126 return(minimumSize());
127}
128
129class OPopupMenu::OPopupMenuPrivate
130{
131public:
132 OPopupMenuPrivate ()
133 : noMatches(false)
134 , shortcuts(false)
135 , autoExec(false)
136 , lastHitIndex(-1)
137 , m_ctxMenu(0)
138 {}
139
140 ~OPopupMenuPrivate ()
141 {
142 delete m_ctxMenu;
143 }
144
145 QString m_lastTitle;
146
147 // variables for keyboard navigation
148 QTimer clearTimer;
149
150 bool noMatches : 1;
151 bool shortcuts : 1;
152 bool autoExec : 1;
153
154 QString keySeq;
155 QString originalText;
156
157 int lastHitIndex;
158
159 // support for RMB menus on menus
160 QPopupMenu* m_ctxMenu;
161 static bool s_continueCtxMenuShow;
162 static int s_highlightedItem;
163 static OPopupMenu* s_contextedMenu;
164};
165
166int OPopupMenu::OPopupMenuPrivate::s_highlightedItem(-1);
167OPopupMenu* OPopupMenu::OPopupMenuPrivate::s_contextedMenu(0);
168bool OPopupMenu::OPopupMenuPrivate::s_continueCtxMenuShow(true);
169
170OPopupMenu::OPopupMenu(QWidget *parent, const char *name)
171 : QPopupMenu(parent, name)
172{
173 d = new OPopupMenuPrivate;
174 resetKeyboardVars();
175 connect(&(d->clearTimer), SIGNAL(timeout()), SLOT(resetKeyboardVars()));
176}
177
178OPopupMenu::~OPopupMenu()
179{
180 if (OPopupMenuPrivate::s_contextedMenu == this)
181 {
182 OPopupMenuPrivate::s_contextedMenu = 0;
183 OPopupMenuPrivate::s_highlightedItem = -1;
184 }
185
186 delete d;
187}
188
189int OPopupMenu::insertTitle(const QString &text, int id, int index)
190{
191 OPopupTitle *titleItem = new OPopupTitle();
192 titleItem->setTitle(text);
193 int ret = insertItem(titleItem, id, index);
194 setItemEnabled(id, false);
195 return ret;
196}
197
198int OPopupMenu::insertTitle(const QPixmap &icon, const QString &text, int id,
199 int index)
200{
201 OPopupTitle *titleItem = new OPopupTitle();
202 titleItem->setTitle(text, &icon);
203 int ret = insertItem(titleItem, id, index);
204 setItemEnabled(id, false);
205 return ret;
206}
207
208void OPopupMenu::changeTitle(int id, const QString &text)
209{
210 QMenuItem *item = findItem(id);
211 if(item){
212 if(item->widget())
213 ((OPopupTitle *)item->widget())->setTitle(text);
214#ifndef NDEBUG
215 else
216 qWarning( "KPopupMenu: changeTitle() called with non-title id %d", id );
217#endif
218 }
219#ifndef NDEBUG
220 else
221 qWarning( "KPopupMenu: changeTitle() called with invalid id %d", id );
222#endif
223}
224
225void OPopupMenu::changeTitle(int id, const QPixmap &icon, const QString &text)
226{
227 QMenuItem *item = findItem(id);
228 if(item){
229 if(item->widget())
230 ((OPopupTitle *)item->widget())->setTitle(text, &icon);
231#ifndef NDEBUG
232 else
233 qWarning( "KPopupMenu: changeTitle() called with non-title id %d", id );
234#endif
235 }
236#ifndef NDEBUG
237 else
238 qWarning( "KPopupMenu: changeTitle() called with invalid id %d", id );
239#endif
240}
241
242QString OPopupMenu::title(int id) const
243{
244 if(id == -1) // obsolete
245 return(d->m_lastTitle);
246 QMenuItem *item = findItem(id);
247 if(item){
248 if(item->widget())
249 return(((OPopupTitle *)item->widget())->title());
250 else
251 qWarning("OPopupMenu: title() called with non-title id %d.", id);
252 }
253 else
254 qWarning("OPopupMenu: title() called with invalid id %d.", id);
255 return(QString::null);
256}
257
258QPixmap OPopupMenu::titlePixmap(int id) const
259{
260 QMenuItem *item = findItem(id);
261 if(item){
262 if(item->widget())
263 return(((OPopupTitle *)item->widget())->icon());
264 else
265 qWarning("KPopupMenu: titlePixmap() called with non-title id %d.", id);
266 }
267 else
268 qWarning("KPopupMenu: titlePixmap() called with invalid id %d.", id);
269 QPixmap tmp;
270 return(tmp);
271}
272
273/**
274 * This is re-implemented for keyboard navigation.
275 */
276void OPopupMenu::closeEvent(QCloseEvent*e)
277{
278 if (d->shortcuts)
279 resetKeyboardVars();
280 QPopupMenu::closeEvent(e);
281}
282
283void OPopupMenu::keyPressEvent(QKeyEvent* e)
284{
285 if (!d->shortcuts) {
286 // continue event processing by Qpopup
287 //e->ignore();
288 QPopupMenu::keyPressEvent(e);
289 return;
290 }
291
292 int i = 0;
293 bool firstpass = true;
294 QString keyString = e->text();
295
296 // check for common commands dealt with by QPopup
297 int key = e->key();
298 if (key == Key_Escape || key == Key_Return || key == Key_Enter
299 || key == Key_Up || key == Key_Down || key == Key_Left
300 || key == Key_Right || key == Key_F1) {
301
302 resetKeyboardVars();
303 // continue event processing by Qpopup
304 //e->ignore();
305 QPopupMenu::keyPressEvent(e);
306 return;
307 }
308
309 // check to see if the user wants to remove a key from the sequence (backspace)
310 // or clear the sequence (delete)
311 if (!d->keySeq.isNull()) {
312
313 if (key == Key_Backspace) {
314
315 if (d->keySeq.length() == 1) {
316 resetKeyboardVars();
317 return;
318 }
319
320 // keep the last sequence in keyString
321 keyString = d->keySeq.left(d->keySeq.length() - 1);
322
323 // allow sequence matching to be tried again
324 resetKeyboardVars();
325
326 } else if (key == Key_Delete) {
327 resetKeyboardVars();
328
329 // clear active item
330 setActiveItem(0);
331 return;
332
333 } else if (d->noMatches) {
334 // clear if there are no matches
335 resetKeyboardVars();
336
337 // clear active item
338 setActiveItem(0);
339
340 } else {
341 // the key sequence is not a null string
342 // therefore the lastHitIndex is valid
343 i = d->lastHitIndex;
344 }
345 } else if (key == Key_Backspace && parentMenu) {
346 // backspace with no chars in the buffer... go back a menu.
347 hide();
348 resetKeyboardVars();
349 return;
350 }
351
352 d->keySeq += keyString;
353 int seqLen = d->keySeq.length();
354
355 for (; i < (int)count(); i++) {
356 // compare typed text with text of this entry
357 int j = idAt(i);
358
359 // don't search disabled entries
360 if (!isItemEnabled(j))
361 continue;
362
363 QString thisText;
364
365 // retrieve the right text
366 // (the last selected item one may have additional ampersands)
367 if (i == d->lastHitIndex)
368 thisText = d->originalText;
369 else
370 thisText = text(j);
371
372 // if there is an accelerator present, remove it
373 if ((int)accel(j) != 0)
374 thisText = thisText.replace(QRegExp("&"), "");
375
376 // chop text to the search length
377 thisText = thisText.left(seqLen);
378
379 // do the search
380 if (thisText.find(d->keySeq, 0, false) == 0) {
381
382 if (firstpass) {
383 // match
384 setActiveItem(i);
385
386 // check to see if we're underlining a different item
387 if (d->lastHitIndex != i)
388 // yes; revert the underlining
389 changeItem(idAt(d->lastHitIndex), d->originalText);
390
391 // set the original text if it's a different item
392 if (d->lastHitIndex != i || d->lastHitIndex == -1)
393 d->originalText = text(j);
394
395 // underline the currently selected item
396 changeItem(j, underlineText(d->originalText, d->keySeq.length()));
397
398 // remeber what's going on
399 d->lastHitIndex = i;
400
401 // start/restart the clear timer
402 d->clearTimer.start(5000, true);
403
404 // go around for another try, to see if we can execute
405 firstpass = false;
406 } else {
407 // don't allow execution
408 return;
409 }
410 }
411
412 // fall through to allow execution
413 }
414
415 if (!firstpass) {
416 if (d->autoExec) {
417 // activate anything
418 activateItemAt(d->lastHitIndex);
419 resetKeyboardVars();
420
421 } else if (findItem(idAt(d->lastHitIndex)) &&
422 findItem(idAt(d->lastHitIndex))->popup()) {
423 // only activate sub-menus
424 activateItemAt(d->lastHitIndex);
425 resetKeyboardVars();
426 }
427
428 return;
429 }
430
431 // no matches whatsoever, clean up
432 resetKeyboardVars(true);
433 //e->ignore();
434 QPopupMenu::keyPressEvent(e);
435}
436
437QString OPopupMenu::underlineText(const QString& text, uint length)
438{
439 QString ret = text;
440 for (uint i = 0; i < length; i++) {
441 if (ret[2*i] != '&')
442 ret.insert(2*i, "&");
443 }
444 return ret;
445}
446
447void OPopupMenu::resetKeyboardVars(bool noMatches /* = false */)
448{
449 // Clean up keyboard variables
450 if (d->lastHitIndex != -1) {
451 changeItem(idAt(d->lastHitIndex), d->originalText);
452 d->lastHitIndex = -1;
453 }
454
455 if (!noMatches) {
456 d->keySeq = QString::null;
457 }
458
459 d->noMatches = noMatches;
460}
461
462void OPopupMenu::setKeyboardShortcutsEnabled(bool enable)
463{
464 d->shortcuts = enable;
465}
466
467void OPopupMenu::setKeyboardShortcutsExecute(bool enable)
468{
469 d->autoExec = enable;
470}
471/**
472 * End keyboard navigation.
473 */
474
475/**
476 * RMB menus on menus
477 */
478QPopupMenu* OPopupMenu::contextMenu()
479{
480 if (!d->m_ctxMenu)
481 {
482 d->m_ctxMenu = new QPopupMenu(this);
483 installEventFilter(this);
484 connect(d->m_ctxMenu, SIGNAL(aboutToHide()), this, SLOT(ctxMenuHiding()));
485 }
486
487 return d->m_ctxMenu;
488}
489
490void OPopupMenu::cancelContextMenuShow()
491{
492 OPopupMenuPrivate::s_continueCtxMenuShow = false;
493}
494
495int OPopupMenu::contextMenuFocusItem()
496{
497 return OPopupMenuPrivate::s_highlightedItem;
498}
499
500OPopupMenu* OPopupMenu::contextMenuFocus()
501{
502 return OPopupMenuPrivate::s_contextedMenu;
503}
504
505void OPopupMenu::itemHighlighted(int /* whichItem */)
506{
507 if (!d->m_ctxMenu || !d->m_ctxMenu->isVisible())
508 {
509 return;
510 }
511
512 d->m_ctxMenu->hide();
513 showCtxMenu(mapFromGlobal(QCursor::pos()));
514}
515
516void OPopupMenu::showCtxMenu(QPoint pos)
517{
518 OPopupMenuPrivate::s_highlightedItem = idAt(pos);
519
520 if (OPopupMenuPrivate::s_highlightedItem == -1)
521 {
522 OPopupMenuPrivate::s_contextedMenu = 0;
523 return;
524 }
525
526 emit aboutToShowContextMenu(this, OPopupMenuPrivate::s_highlightedItem, d->m_ctxMenu);
527
528 if (!OPopupMenuPrivate::s_continueCtxMenuShow)
529 {
530 OPopupMenuPrivate::s_continueCtxMenuShow = true;
531 return;
532 }
533
534 OPopupMenuPrivate::s_contextedMenu = this;
535 d->m_ctxMenu->popup(this->mapToGlobal(pos));
536 connect(this, SIGNAL(highlighted(int)), this, SLOT(itemHighlighted(int)));
537}
538
539void OPopupMenu::ctxMenuHiding()
540{
541 disconnect(this, SIGNAL(highlighted(int)), this, SLOT(itemHighlighted(int)));
542 OPopupMenuPrivate::s_continueCtxMenuShow = true;
543}
544
545bool OPopupMenu::eventFilter(QObject* obj, QEvent* event)
546{
547 if (d->m_ctxMenu && obj == this)
548 {
549 if (event->type() == QEvent::MouseButtonRelease)
550 {
551 if (d->m_ctxMenu->isVisible())
552 {
553 return true;
554 }
555 }
556 #if QT_VERSION > 290
557 else if (event->type() == QEvent::ContextMenu)
558 #else
559 else if ( (event->type() == QEvent::MouseButtonPress) &&
560 ( (QMouseEvent*) event )->button() == QMouseEvent::RightButton )
561 #endif
562 {
563 showCtxMenu(mapFromGlobal(QCursor::pos()));
564 return true;
565 }
566 }
567
568 return QWidget::eventFilter(obj, event);
569}
570
571void OPopupMenu::hideEvent(QHideEvent*)
572{
573 if (d->m_ctxMenu)
574 {
575 d->m_ctxMenu->hide();
576 }
577}
578/**
579 * end of RMB menus on menus support
580 */
581
582// Obsolete
583OPopupMenu::OPopupMenu(const QString& title, QWidget *parent, const char *name)
584 : QPopupMenu(parent, name)
585{
586 d = new OPopupMenuPrivate;
587 setTitle(title);
588}
589
590// Obsolete
591void OPopupMenu::setTitle(const QString &title)
592{
593 OPopupTitle *titleItem = new OPopupTitle();
594 titleItem->setTitle(title);
595 insertItem(titleItem);
596 d->m_lastTitle = title;
597}
598
599void OPopupTitle::virtual_hook( int, void* )
600{ /*BASE::virtual_hook( id, data );*/ }
601
602void OPopupMenu::virtual_hook( int, void* )
603{ /*BASE::virtual_hook( id, data );*/ }
604
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 @@
1/* This file is part of the ODE libraries
2 Copyright (C) 2000 Daniel M. Duley <mosfet@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 Boston, MA 02111-1307, USA.
17*/
18#ifndef _OPOPUP_H
19#define _OPOPUP_H
20
21#define INCLUDE_MENUITEM_DEF
22
23/* QT */
24
25#include <qpopupmenu.h>
26
27/* OPIE */
28
29#include <opie2/opixmapeffect.h>
30
31/**
32 * Title widget for use in @ref OPopupMenu.
33 *
34 * You usually don't have to create this manually since
35 * @ref OPopupMenu::insertTitle will do it for you, but it is allowed if
36 * you wish to customize it's look.
37 *
38 * @author Daniel M. Duley <mosfet@kde.org>
39 * @short OPopupMenu title widget.
40 */
41class OPopupTitle : public QWidget
42{
43 Q_OBJECT
44
45public:
46 /**
47 * Constructs a title widget with the user specified gradient, pixmap,
48 * and colors.
49 */
50 OPopupTitle(QWidget *parent=0, const char *name=0);
51 /**
52 * @deprecated
53 * Constructs a title widget with the specified gradient and colors.
54 */
55 OPopupTitle(OPixmapEffect::GradientType gradient, const QColor &color,
56 const QColor &textColor, QWidget *parent=0,
57 const char *name=0);
58 /**
59 * @deprecated
60 * Constructs a title widget with the specified pixmap and colors.
61 */
62 OPopupTitle(const OPixmap &background, const QColor &color,
63 const QColor &textColor, QWidget *parent=0,
64 const char *name=0);
65 /**
66 * Sets the title string and optional icon for the title widget.
67 *
68 * You will want to call this before inserting into a menu.
69 */
70 void setTitle(const QString &text, const QPixmap *icon=NULL);
71 /**
72 * Returns the current title.
73 */
74 QString title() const { return(titleStr); }
75 /**
76 * Returns the current icon.
77 */
78 QPixmap icon() const { return(miniicon); }
79
80 QSize sizeHint() const;
81
82public slots:
83 /// @since 3.1
84 void setText( const QString &text );
85 /// @since 3.1
86 void setIcon( const QPixmap &pix );
87
88protected:
89 void paintEvent(QPaintEvent *ev);
90
91 QString titleStr;
92 QPixmap miniicon;
93
94 // Remove in KDE4
95 OPixmapEffect::GradientType grType;
96 QPixmap fill;
97 QColor fgColor, bgColor, grHigh, grLow;
98 bool useGradient;
99
100protected:
101 virtual void virtual_hook( int id, void* data );
102private:
103 class OPopupTitlePrivate;
104 OPopupTitlePrivate *d;
105};
106
107/**
108 * OPopupMenu is a class for menus with standard title items and keyboard
109 * accessibility for popups with many options and/or varying options. It acts
110 * identically to QPopupMenu, with the addition of insertTitle(),
111 * changeTitle(), setKeyboardShortcutsEnabled() and
112 * setKeyboardShortcutsExecute() methods.
113 *
114 * The titles support a text string, an icon, plus user defined gradients,
115 * colors, and background pixmaps.
116 *
117 * The keyboard search algorithm is incremental with additional underlining
118 * for user feedback.
119 *
120 * @short A menu with title items.
121 * @author Daniel M. Duley <mosfet@kde.org>
122 * @author Hamish Rodda <meddie@yoyo.its.monash.edu.au>
123 */
124class OPopupMenu : public QPopupMenu {
125 Q_OBJECT
126public:
127 /**
128 * Constructs a OPopupMenu.
129 */
130 OPopupMenu(QWidget *parent=0, const char *name=0);
131
132 /**
133 * Destructs the object
134 */
135 ~OPopupMenu();
136
137 /**
138 * Inserts a title item with no icon.
139 */
140 int insertTitle(const QString &text, int id=-1, int index=-1);
141 /**
142 * Inserts a title item with the given icon and title.
143 */
144 int insertTitle(const QPixmap &icon, const QString &text, int id=-1,
145 int index=-1);
146 /**
147 * Changes the title of the item at the specified id. If a icon was
148 * previously set it is cleared.
149 */
150 void changeTitle(int id, const QString &text);
151 /**
152 * Changes the title and icon of the title item at the specified id.
153 */
154 void changeTitle(int id, const QPixmap &icon, const QString &text);
155 /**
156 * Returns the title of the title item at the specified id. The default
157 * id of -1 is for backwards compatibility only, you should always specify
158 * the id.
159 */
160 QString title(int id=-1) const;
161 /**
162 * Returns the icon of the title item at the specified id.
163 */
164 QPixmap titlePixmap(int id) const;
165
166 /**
167 * Enables keyboard navigation by searching for the entered key sequence.
168 * Also underlines the currently selected item, providing feedback on the search.
169 *
170 * Defaults to off.
171 *
172 * WARNING: calls to text() of currently keyboard-selected items will
173 * contain additional ampersand characters.
174 *
175 * WARNING: though pre-existing keyboard shortcuts will not interfere with the
176 * operation of this feature, they may be confusing to the user as the existing
177 * shortcuts will not work.
178 * @since 3.1
179 */
180 void setKeyboardShortcutsEnabled(bool enable);
181
182 /**
183 * Enables execution of the menu item once it is uniquely specified.
184 * Defaults to off.
185 * @since 3.1
186 */
187 void setKeyboardShortcutsExecute(bool enable);
188
189 /**
190 * Obsolete method provided for backwards compatibility only. Use the
191 * normal constructor and insertTitle instead.
192 */
193 OPopupMenu(const QString &title, QWidget *parent=0, const char *name=0);
194 /**
195 * Obsolete method provided for backwards compatibility only. Use
196 * insertTitle and changeTitle instead.
197 */
198 void setTitle(const QString &title);
199
200 /**
201 * Returns the context menu associated with this menu
202 * @since 3.2
203 */
204 QPopupMenu* contextMenu();
205
206 /**
207 * Hides the context menu if shown
208 * @since 3.2
209 */
210 void cancelContextMenuShow();
211
212 /**
213 * Returns the OPopupMenu associated with the current context menu
214 * @since 3.2
215 */
216 static OPopupMenu* contextMenuFocus();
217
218 /**
219 * returns the ID of the menuitem associated with the current context menu
220 * @since 3.2
221 */
222 static int contextMenuFocusItem();
223
224signals:
225 /**
226 * connect to this signal to be notified when a context menu is about to be shown
227 * @param menu The menu that the context menu is about to be shown for
228 * @param menuItem The menu item that the context menu is currently on
229 * @param ctxMenu The context menu itself
230 * @since 3.2
231 */
232 void aboutToShowContextMenu(OPopupMenu* menu, int menuItem, QPopupMenu* ctxMenu);
233
234protected:
235 virtual void closeEvent(QCloseEvent *);
236 virtual void keyPressEvent(QKeyEvent* e);
237 virtual bool eventFilter(QObject* obj, QEvent* event);
238 virtual void hideEvent(QHideEvent*);
239
240 virtual void virtual_hook( int id, void* data );
241
242protected slots:
243 /// @since 3.1
244 QString underlineText(const QString& text, uint length);
245 /// @since 3.1
246 void resetKeyboardVars(bool noMatches = false);
247 void itemHighlighted(int whichItem);
248 void showCtxMenu(QPoint pos);
249 void ctxMenuHiding();
250
251private:
252 class OPopupMenuPrivate;
253 OPopupMenuPrivate *d;
254};
255
256#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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1997 Martin Jones (mjones@kde.org)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20/* QT */
21
22#include <qimage.h>
23#include <qpainter.h>
24#include <qdrawutil.h>
25
26/* OPIE */
27
28#include <opie2/oimageeffect.h>
29#include <opie2/oselector.h>
30
31#define STORE_W 8
32#define STORE_W2 STORE_W * 2
33
34//-----------------------------------------------------------------------------
35/*
36 * 2D value selector.
37 * The contents of the selector are drawn by derived class.
38 */
39
40OXYSelector::OXYSelector( QWidget *parent, const char *name )
41 : QWidget( parent, name )
42{
43 xPos = 0;
44 yPos = 0;
45 minX = 0;
46 minY = 0;
47 maxX = 100;
48 maxY = 100;
49 store.setOptimization( QPixmap::BestOptim );
50 store.resize( STORE_W2, STORE_W2 );
51}
52
53
54OXYSelector::~OXYSelector()
55{}
56
57
58void OXYSelector::setRange( int _minX, int _minY, int _maxX, int _maxY )
59{
60 px = 2;
61 py = 2;
62 minX = _minX;
63 minY = _minY;
64 maxX = _maxX;
65 maxY = _maxY;
66}
67
68void OXYSelector::setValues( int _xPos, int _yPos )
69{
70 xPos = _xPos;
71 yPos = _yPos;
72
73 if ( xPos > maxX )
74 xPos = maxX;
75 else if ( xPos < minX )
76 xPos = minX;
77
78 if ( yPos > maxY )
79 yPos = maxY;
80 else if ( yPos < minY )
81 yPos = minY;
82
83 int xp = 2 + (width() - 4) * xPos / (maxX - minX);
84 int yp = height() - 2 - (height() - 4) * yPos / (maxY - minY);
85
86 setPosition( xp, yp );
87}
88
89QRect OXYSelector::contentsRect() const
90{
91 return QRect( 2, 2, width()-4, height()-4 );
92}
93
94void OXYSelector::paintEvent( QPaintEvent *ev )
95{
96 QRect cursorRect( px - STORE_W, py - STORE_W, STORE_W2, STORE_W2);
97 QRect paintRect = ev->rect();
98
99 QPainter painter;
100 painter.begin( this );
101
102 QBrush brush;
103 qDrawShadePanel( &painter, 0, 0, width(), height(), colorGroup(),
104 TRUE, 2, &brush );
105
106 drawContents( &painter );
107 if (paintRect.contains(cursorRect))
108 {
109 bitBlt( &store, 0, 0, this, px - STORE_W, py - STORE_W,
110 STORE_W2, STORE_W2, CopyROP );
111 drawCursor( &painter, px, py );
112 }
113 else if (paintRect.intersects(cursorRect))
114 {
115 repaint( cursorRect, false);
116 }
117
118 painter.end();
119}
120
121void OXYSelector::mousePressEvent( QMouseEvent *e )
122{
123 int xVal, yVal;
124 valuesFromPosition( e->pos().x() - 2, e->pos().y() - 2, xVal, yVal );
125 setValues( xVal, yVal );
126
127 emit valueChanged( xPos, yPos );
128}
129
130void OXYSelector::mouseMoveEvent( QMouseEvent *e )
131{
132 int xVal, yVal;
133 valuesFromPosition( e->pos().x() - 2, e->pos().y() - 2, xVal, yVal );
134 setValues( xVal, yVal );
135
136 emit valueChanged( xPos, yPos );
137}
138
139void OXYSelector::wheelEvent( QWheelEvent *e )
140{
141 #if QT_VERSION > 290
142 if ( e->orientation() == Qt::Horizontal )
143 setValues( xValue() + e->delta()/120, yValue() );
144 else
145 setValues( xValue(), yValue() + e->delta()/120 );
146
147 emit valueChanged( xPos, yPos );
148 #endif
149}
150
151void OXYSelector::valuesFromPosition( int x, int y, int &xVal, int &yVal ) const
152{
153 xVal = ( (maxX-minX) * (x-2) ) / ( width()-4 );
154 yVal = maxY - ( ( (maxY-minY) * (y-2) ) / ( height()-4 ) );
155
156 if ( xVal > maxX )
157 xVal = maxX;
158 else if ( xVal < minX )
159 xVal = minX;
160
161 if ( yVal > maxY )
162 yVal = maxY;
163 else if ( yVal < minY )
164 yVal = minY;
165}
166
167void OXYSelector::setPosition( int xp, int yp )
168{
169 if ( xp < 2 )
170 xp = 2;
171 else if ( xp > width() - 2 )
172 xp = width() - 2;
173
174 if ( yp < 2 )
175 yp = 2;
176 else if ( yp > height() - 2 )
177 yp = height() - 2;
178
179 QPainter painter;
180 painter.begin( this );
181
182 bitBlt( this, px - STORE_W, py - STORE_W, &store, 0, 0,
183 STORE_W2, STORE_W2, CopyROP );
184 bitBlt( &store, 0, 0, this, xp - STORE_W, yp - STORE_W,
185 STORE_W2, STORE_W2, CopyROP );
186 drawCursor( &painter, xp, yp );
187 px = xp;
188 py = yp;
189
190 painter.end();
191}
192
193void OXYSelector::drawContents( QPainter * )
194{}
195
196
197void OXYSelector::drawCursor( QPainter *p, int xp, int yp )
198{
199 p->setPen( QPen( white ) );
200
201 p->drawLine( xp - 6, yp - 6, xp - 2, yp - 2 );
202 p->drawLine( xp - 6, yp + 6, xp - 2, yp + 2 );
203 p->drawLine( xp + 6, yp - 6, xp + 2, yp - 2 );
204 p->drawLine( xp + 6, yp + 6, xp + 2, yp + 2 );
205}
206
207//-----------------------------------------------------------------------------
208/*
209 * 1D value selector with contents drawn by derived class.
210 * See OColorDialog for example.
211 */
212
213
214OSelector::OSelector( QWidget *parent, const char *name )
215 : QWidget( parent, name ), QRangeControl()
216{
217 _orientation = Horizontal;
218 _indent = TRUE;
219}
220
221OSelector::OSelector( Orientation o, QWidget *parent, const char *name )
222 : QWidget( parent, name ), QRangeControl()
223{
224 _orientation = o;
225 _indent = TRUE;
226}
227
228
229OSelector::~OSelector()
230{}
231
232
233QRect OSelector::contentsRect() const
234{
235 if ( orientation() == Vertical )
236 return QRect( 2, 5, width()-9, height()-10 );
237 else
238 return QRect( 5, 2, width()-10, height()-9 );
239}
240
241void OSelector::paintEvent( QPaintEvent * )
242{
243 QPainter painter;
244
245 painter.begin( this );
246
247 drawContents( &painter );
248
249 QBrush brush;
250
251 if ( indent() )
252 {
253 if ( orientation() == Vertical )
254 qDrawShadePanel( &painter, 0, 3, width()-5, height()-6,
255 colorGroup(), TRUE, 2, &brush );
256 else
257 qDrawShadePanel( &painter, 3, 0, width()-6, height()-5,
258 colorGroup(), TRUE, 2, &brush );
259 }
260
261 QPoint pos = calcArrowPos( value() );
262 drawArrow( &painter, TRUE, pos );
263
264 painter.end();
265}
266
267void OSelector::mousePressEvent( QMouseEvent *e )
268{
269 moveArrow( e->pos() );
270}
271
272void OSelector::mouseMoveEvent( QMouseEvent *e )
273{
274 moveArrow( e->pos() );
275}
276
277void OSelector::wheelEvent( QWheelEvent *e )
278{
279 int val = value() + e->delta()/120;
280 emit valueChanged( val );
281 setValue( val );
282}
283
284void OSelector::valueChange()
285{
286 QPainter painter;
287 QPoint pos;
288
289 painter.begin( this );
290
291 pos = calcArrowPos( prevValue() );
292 drawArrow( &painter, FALSE, pos );
293
294 pos = calcArrowPos( value() );
295 drawArrow( &painter, TRUE, pos );
296
297 painter.end();
298}
299
300void OSelector::moveArrow( const QPoint &pos )
301{
302 int val;
303
304 if ( orientation() == Vertical )
305 val = ( maxValue() - minValue() ) * (height()-pos.y()-3)
306 / (height()-10) + minValue();
307 else
308 val = ( maxValue() - minValue() ) * (width()-pos.x()-3)
309 / (width()-10) + minValue();
310
311 if ( val > maxValue() )
312 val = maxValue();
313 if ( val < minValue() )
314 val = minValue();
315
316 emit valueChanged( val );
317 setValue( val );
318}
319
320QPoint OSelector::calcArrowPos( int val )
321{
322 QPoint p;
323
324 if ( orientation() == Vertical )
325 {
326 p.setY( height() - ( (height()-10) * val
327 / ( maxValue() - minValue() ) + 5 ) );
328 p.setX( width() - 5 );
329 }
330 else
331 {
332 p.setX( width() - ( (width()-10) * val
333 / ( maxValue() - minValue() ) + 5 ) );
334 p.setY( height() - 5 );
335 }
336
337 return p;
338}
339
340void OSelector::drawContents( QPainter * )
341{}
342
343void OSelector::drawArrow( QPainter *painter, bool show, const QPoint &pos )
344{
345 if ( show )
346 {
347 QPointArray array(3);
348
349 painter->setPen( QPen() );
350 painter->setBrush( QBrush( colorGroup().buttonText() ) );
351 if ( orientation() == Vertical )
352 {
353 array.setPoint( 0, pos.x()+0, pos.y()+0 );
354 array.setPoint( 1, pos.x()+5, pos.y()+5 );
355 array.setPoint( 2, pos.x()+5, pos.y()-5 );
356 }
357 else
358 {
359 array.setPoint( 0, pos.x()+0, pos.y()+0 );
360 array.setPoint( 1, pos.x()+5, pos.y()+5 );
361 array.setPoint( 2, pos.x()-5, pos.y()+5 );
362 }
363
364 painter->drawPolygon( array );
365 }
366 else
367 {
368 if ( orientation() == Vertical )
369 {
370 repaint(pos.x(), pos.y()-5, 6, 11, true);
371 }
372 else
373 {
374 repaint(pos.x()-5, pos.y(), 11, 6, true);
375 }
376 }
377}
378
379//----------------------------------------------------------------------------
380
381OGradientSelector::OGradientSelector( QWidget *parent, const char *name )
382 : OSelector( parent, name )
383{
384 init();
385}
386
387
388OGradientSelector::OGradientSelector( Orientation o, QWidget *parent,
389 const char *name )
390 : OSelector( o, parent, name )
391{
392 init();
393}
394
395
396OGradientSelector::~OGradientSelector()
397{}
398
399
400void OGradientSelector::init()
401{
402 color1.setRgb( 0, 0, 0 );
403 color2.setRgb( 255, 255, 255 );
404
405 text1 = text2 = "";
406}
407
408
409void OGradientSelector::drawContents( QPainter *painter )
410{
411 QImage image( contentsRect().width(), contentsRect().height(), 32 );
412
413 QColor col;
414 float scale;
415
416 int redDiff = color2.red() - color1.red();
417 int greenDiff = color2.green() - color1.green();
418 int blueDiff = color2.blue() - color1.blue();
419
420 if ( orientation() == Vertical )
421 {
422 for ( int y = 0; y < image.height(); y++ )
423 {
424 scale = 1.0 * y / image.height();
425 col.setRgb( color1.red() + int(redDiff*scale),
426 color1.green() + int(greenDiff*scale),
427 color1.blue() + int(blueDiff*scale) );
428
429 unsigned int *p = (uint *) image.scanLine( y );
430 for ( int x = 0; x < image.width(); x++ )
431 *p++ = col.rgb();
432 }
433 }
434 else
435 {
436 unsigned int *p = (uint *) image.scanLine( 0 );
437
438 for ( int x = 0; x < image.width(); x++ )
439 {
440 scale = 1.0 * x / image.width();
441 col.setRgb( color1.red() + int(redDiff*scale),
442 color1.green() + int(greenDiff*scale),
443 color1.blue() + int(blueDiff*scale) );
444 *p++ = col.rgb();
445 }
446
447 for ( int y = 1; y < image.height(); y++ )
448 memcpy( image.scanLine( y ), image.scanLine( y - 1),
449 sizeof( unsigned int ) * image.width() );
450 }
451
452 QColor ditherPalette[8];
453
454 for ( int s = 0; s < 8; s++ )
455 ditherPalette[s].setRgb( color1.red() + redDiff * s / 8,
456 color1.green() + greenDiff * s / 8,
457 color1.blue() + blueDiff * s / 8 );
458
459 OImageEffect::dither( image, ditherPalette, 8 );
460
461 QPixmap p;
462 p.convertFromImage( image );
463
464 painter->drawPixmap( contentsRect().x(), contentsRect().y(), p );
465
466 if ( orientation() == Vertical )
467 {
468 int yPos = contentsRect().top() + painter->fontMetrics().ascent() + 2;
469 int xPos = contentsRect().left() + (contentsRect().width() -
470 painter->fontMetrics().width( text2 )) / 2;
471 QPen pen( color2 );
472 painter->setPen( pen );
473 painter->drawText( xPos, yPos, text2 );
474
475 yPos = contentsRect().bottom() - painter->fontMetrics().descent() - 2;
476 xPos = contentsRect().left() + (contentsRect().width() -
477 painter->fontMetrics().width( text1 )) / 2;
478 pen.setColor( color1 );
479 painter->setPen( pen );
480 painter->drawText( xPos, yPos, text1 );
481 }
482 else
483 {
484 int yPos = contentsRect().bottom()-painter->fontMetrics().descent()-2;
485
486 QPen pen( color2 );
487 painter->setPen( pen );
488 painter->drawText( contentsRect().left() + 2, yPos, text1 );
489
490 pen.setColor( color1 );
491 painter->setPen( pen );
492 painter->drawText( contentsRect().right() -
493 painter->fontMetrics().width( text2 ) - 2, yPos, text2 );
494 }
495}
496
497//-----------------------------------------------------------------------------
498
499static QColor *standardPalette = 0;
500
501#define STANDARD_PAL_SIZE 17
502
503OColor::OColor()
504: QColor()
505{
506 r = 0; g = 0; b = 0; h = 0; s = 0; v = 0;
507};
508
509OColor::OColor( const OColor &col)
510: QColor( col )
511{
512 h = col.h; s = col.s; v = col.v;
513 r = col.r; g = col.g; b = col.b;
514};
515
516OColor::OColor( const QColor &col)
517: QColor( col )
518{
519 QColor::rgb(&r, &g, &b);
520 QColor::hsv(&h, &s, &v);
521};
522
523bool OColor::operator==(const OColor& col) const
524{
525 return (h == col.h) && (s == col.s) && (v == col.v) &&
526 (r == col.r) && (g == col.g) && (b == col.b);
527}
528
529OColor& OColor::operator=(const OColor& col)
530{
531 *(QColor *)this = col;
532 h = col.h; s = col.s; v = col.v;
533 r = col.r; g = col.g; b = col.b;
534 return *this;
535}
536
537void
538OColor::setHsv(int _h, int _s, int _v)
539{
540 h = _h; s = _s; v = _v;
541 QColor::setHsv(h, s, v);
542 QColor::rgb(&r, &g, &b);
543};
544
545void
546OColor::setRgb(int _r, int _g, int _b)
547{
548 r = _r; g = _g; b = _b;
549 QColor::setRgb(r, g, b);
550 QColor::hsv(&h, &s, &v);
551}
552
553void
554OColor::rgb(int *_r, int *_g, int *_b) const
555{
556 *_r = r; *_g = g; *_b = b;
557}
558
559void
560OColor::hsv(int *_h, int *_s, int *_v) const
561{
562 *_h = h; *_s = s; *_v = v;
563}
564
565static void createStandardPalette()
566{
567 if ( standardPalette )
568 return;
569
570 standardPalette = new QColor[STANDARD_PAL_SIZE];
571
572 int i = 0;
573
574 standardPalette[i++] = Qt::red;
575 standardPalette[i++] = Qt::green;
576 standardPalette[i++] = Qt::blue;
577 standardPalette[i++] = Qt::cyan;
578 standardPalette[i++] = Qt::magenta;
579 standardPalette[i++] = Qt::yellow;
580 standardPalette[i++] = Qt::darkRed;
581 standardPalette[i++] = Qt::darkGreen;
582 standardPalette[i++] = Qt::darkBlue;
583 standardPalette[i++] = Qt::darkCyan;
584 standardPalette[i++] = Qt::darkMagenta;
585 standardPalette[i++] = Qt::darkYellow;
586 standardPalette[i++] = Qt::white;
587 standardPalette[i++] = Qt::lightGray;
588 standardPalette[i++] = Qt::gray;
589 standardPalette[i++] = Qt::darkGray;
590 standardPalette[i++] = Qt::black;
591}
592
593
594OHSSelector::OHSSelector( QWidget *parent, const char *name )
595 : OXYSelector( parent, name )
596{
597 setRange( 0, 0, 359, 255 );
598}
599
600void OHSSelector::updateContents()
601{
602 drawPalette(&pixmap);
603}
604
605void OHSSelector::resizeEvent( QResizeEvent * )
606{
607 updateContents();
608}
609
610void OHSSelector::drawContents( QPainter *painter )
611{
612 painter->drawPixmap( contentsRect().x(), contentsRect().y(), pixmap );
613}
614
615void OHSSelector::drawPalette( QPixmap *pixmap )
616{
617 int xSize = contentsRect().width(), ySize = contentsRect().height();
618 QImage image( xSize, ySize, 32 );
619 QColor col;
620 int h, s;
621 uint *p;
622
623 for ( s = ySize-1; s >= 0; s-- )
624 {
625 p = (uint *) image.scanLine( ySize - s - 1 );
626 for( h = 0; h < xSize; h++ )
627 {
628 col.setHsv( 359*h/(xSize-1), 255*s/(ySize-1), 192 );
629 *p = col.rgb();
630 p++;
631 }
632 }
633
634 if ( QColor::numBitPlanes() <= 8 )
635 {
636 createStandardPalette();
637 OImageEffect::dither( image, standardPalette, STANDARD_PAL_SIZE );
638 }
639 pixmap->convertFromImage( image );
640}
641
642
643//-----------------------------------------------------------------------------
644
645OValueSelector::OValueSelector( QWidget *parent, const char *name )
646 : OSelector( OSelector::Vertical, parent, name ), _hue(0), _sat(0)
647{
648 setRange( 0, 255 );
649 pixmap.setOptimization( QPixmap::BestOptim );
650}
651
652OValueSelector::OValueSelector(Orientation o, QWidget *parent, const char *name
653 )
654 : OSelector( o, parent, name), _hue(0), _sat(0)
655{
656 setRange( 0, 255 );
657 pixmap.setOptimization( QPixmap::BestOptim );
658}
659
660void OValueSelector::updateContents()
661{
662 drawPalette(&pixmap);
663}
664
665void OValueSelector::resizeEvent( QResizeEvent * )
666{
667 updateContents();
668}
669
670void OValueSelector::drawContents( QPainter *painter )
671{
672 painter->drawPixmap( contentsRect().x(), contentsRect().y(), pixmap );
673}
674
675void OValueSelector::drawPalette( QPixmap *pixmap )
676{
677 int xSize = contentsRect().width(), ySize = contentsRect().height();
678 QImage image( xSize, ySize, 32 );
679 QColor col;
680 uint *p;
681 QRgb rgb;
682
683 if ( orientation() == OSelector::Horizontal )
684 {
685 for ( int v = 0; v < ySize; v++ )
686 {
687 p = (uint *) image.scanLine( ySize - v - 1 );
688
689 for( int x = 0; x < xSize; x++ )
690 {
691 col.setHsv( _hue, _sat, 255*x/(xSize-1) );
692 rgb = col.rgb();
693 *p++ = rgb;
694 }
695 }
696 }
697
698 if( orientation() == OSelector::Vertical )
699 {
700 for ( int v = 0; v < ySize; v++ )
701 {
702 p = (uint *) image.scanLine( ySize - v - 1 );
703 col.setHsv( _hue, _sat, 255*v/(ySize-1) );
704 rgb = col.rgb();
705 for ( int i = 0; i < xSize; i++ )
706 *p++ = rgb;
707 }
708 }
709
710 if ( QColor::numBitPlanes() <= 8 )
711 {
712 createStandardPalette();
713 OImageEffect::dither( image, standardPalette, STANDARD_PAL_SIZE );
714 }
715 pixmap->convertFromImage( image );
716}
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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1997 Martin Jones (mjones@kde.org)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19//-----------------------------------------------------------------------------
20// Selector widgets for KDE Color Selector, but probably useful for other
21// stuff also.
22
23#ifndef __OSELECT_H__
24#define __OSELECT_H__
25
26#include <qwidget.h>
27#include <qrangecontrol.h>
28#include <qpixmap.h>
29
30/**
31 * OXYSelector is the base class for other widgets which
32 * provides the ability to choose from a two-dimensional
33 * range of values. The currently chosen value is indicated
34 * by a cross. An example is the @ref OHSSelector which
35 * allows to choose from a range of colors, and which is
36 * used in OColorDialog.
37 *
38 * A custom drawing routine for the widget surface has
39 * to be provided by the subclass.
40 */
41class OXYSelector : public QWidget
42{
43 Q_OBJECT
44
45public:
46 /**
47 * Constructs a two-dimensional selector widget which
48 * has a value range of [0..100] in both directions.
49 */
50 OXYSelector( QWidget *parent=0, const char *name=0 );
51 /**
52 * Destructs the widget.
53 */
54 ~OXYSelector();
55
56 /**
57 * Sets the current values in horizontal and
58 * vertical direction.
59 */
60 void setValues( int xPos, int yPos );
61 /**
62 * Sets the range of possible values.
63 */
64 void setRange( int minX, int minY, int maxX, int maxY );
65
66 /**
67 * @return the current value in horizontal direction.
68 */
69 int xValue() const {return xPos; }
70 /**
71 * @return the current value in vertical direction.
72 */
73 int yValue() const {return yPos; }
74
75 /**
76 * @return the rectangle on which subclasses should draw.
77 */
78 QRect contentsRect() const;
79
80signals:
81 /**
82 * This signal is emitted whenever the user chooses a value,
83 * e.g. by clicking with the mouse on the widget.
84 */
85 void valueChanged( int x, int y );
86
87protected:
88 /**
89 * Override this function to draw the contents of the widget.
90 * The default implementation does nothing.
91 *
92 * Draw within @ref contentsRect() only.
93 */
94 virtual void drawContents( QPainter * );
95 /**
96 * Override this function to draw the cursor which
97 * indicates the currently selected value pair.
98 */
99 virtual void drawCursor( QPainter *p, int xp, int yp );
100 /**
101 * @reimplemented
102 */
103 virtual void paintEvent( QPaintEvent *e );
104 /**
105 * @reimplemented
106 */
107 virtual void mousePressEvent( QMouseEvent *e );
108 /**
109 * @reimplemented
110 */
111 virtual void mouseMoveEvent( QMouseEvent *e );
112 /**
113 * @reimplemented
114 */
115 virtual void wheelEvent( QWheelEvent * );
116 /**
117 * Converts a pixel position to its corresponding values.
118 */
119 void valuesFromPosition( int x, int y, int& xVal, int& yVal ) const;
120
121private:
122 void setPosition( int xp, int yp );
123 int px;
124 int py;
125 int xPos;
126 int yPos;
127 int minX;
128 int maxX;
129 int minY;
130 int maxY;
131 QPixmap store;
132
133private:
134 class OXYSelectorPrivate;
135 OXYSelectorPrivate *d;
136};
137
138
139/**
140 * OSelector is the base class for other widgets which
141 * provides the ability to choose from a one-dimensional
142 * range of values. An example is the @ref OGradientSelector
143 * which allows to choose from a range of colors.
144 *
145 * A custom drawing routine for the widget surface has
146 * to be provided by the subclass.
147 */
148class OSelector : public QWidget, public QRangeControl
149{
150 Q_OBJECT
151 Q_PROPERTY( int value READ value WRITE setValue )
152 Q_PROPERTY( int minValue READ minValue WRITE setMinValue )
153 Q_PROPERTY( int maxValue READ maxValue WRITE setMaxValue )
154public:
155
156 /**
157 * Constructs a horizontal one-dimensional selection widget.
158 */
159 OSelector( QWidget *parent=0, const char *name=0 );
160 /**
161 * Constructs a one-dimensional selection widget with
162 * a given orientation.
163 */
164 OSelector( Orientation o, QWidget *parent = 0L, const char *name = 0L );
165 /*
166 * Destructs the widget.
167 */
168 ~OSelector();
169
170 /**
171 * @return the orientation of the widget.
172 */
173 Orientation orientation() const
174 {return _orientation; }
175
176 /**
177 * @return the rectangle on which subclasses should draw.
178 */
179 QRect contentsRect() const;
180
181 /**
182 * Sets the indent option of the widget to i.
183 * This determines whether a shaded frame is drawn.
184 */
185 void setIndent( bool i )
186 {_indent = i; }
187 /**
188 * @return whether the indent option is set.
189 */
190 bool indent() const
191 {return _indent; }
192
193 /**
194 * Sets the value.
195 */
196 void setValue(int value)
197 { QRangeControl::setValue(value); }
198
199 /**
200 * @returns the value.
201 */
202 int value() const
203 { return QRangeControl::value(); }
204
205 /**
206 * Sets the min value.
207 */
208 #if ( QT_VERSION > 290 )
209 void setMinValue(int value) { QRangeControl::setMinValue(value); }
210 #else
211 void setMinValue(int value) { QRangeControl::setRange(value,QRangeControl::maxValue()); }
212 #endif
213
214 /**
215 * @return the min value.
216 */
217 int minValue() const
218 { return QRangeControl::minValue(); }
219
220 /**
221 * Sets the max value.
222 */
223 #if ( QT_VERSION > 290 )
224 void setMaxValue(int value) { QRangeControl::setMaxValue(value); }
225 #else
226 void setMaxValue(int value) { QRangeControl::setRange(QRangeControl::minValue(),value); }
227 #endif
228
229 /**
230 * @return the max value.
231 */
232 int maxValue() const
233 { return QRangeControl::maxValue(); }
234
235signals:
236 /**
237 * This signal is emitted whenever the user chooses a value,
238 * e.g. by clicking with the mouse on the widget.
239 */
240 void valueChanged( int value );
241
242protected:
243 /**
244 * Override this function to draw the contents of the control.
245 * The default implementation does nothing.
246 *
247 * Draw only within contentsRect().
248 */
249 virtual void drawContents( QPainter * );
250 /**
251 * Override this function to draw the cursor which
252 * indicates the current value. This function is
253 * always called twice, once with argument show=false
254 * to clear the old cursor, once with argument show=true
255 * to draw the new one.
256 */
257 virtual void drawArrow( QPainter *painter, bool show, const QPoint &pos );
258
259 /**
260 * @reimplemented
261 */
262 virtual void valueChange();
263 /**
264 * @reimplemented
265 */
266 virtual void paintEvent( QPaintEvent * );
267 /**
268 * @reimplemented
269 */
270 virtual void mousePressEvent( QMouseEvent *e );
271 /**
272 * @reimplemented
273 */
274 virtual void mouseMoveEvent( QMouseEvent *e );
275 /**
276 * @reimplemented
277 */
278 virtual void wheelEvent( QWheelEvent * );
279
280private:
281 QPoint calcArrowPos( int val );
282 void moveArrow( const QPoint &pos );
283
284 Orientation _orientation;
285 bool _indent;
286
287private:
288 class OSelectorPrivate;
289 OSelectorPrivate *d;
290};
291
292
293/**
294 * The OGradientSelector widget allows the user to choose
295 * from a one-dimensional range of colors which is given as a
296 * gradient between two colors provided by the programmer.
297 */
298class OGradientSelector : public OSelector
299{
300 Q_OBJECT
301
302 Q_PROPERTY( QColor firstColor READ firstColor WRITE setFirstColor )
303 Q_PROPERTY( QColor secondColor READ secondColor WRITE setSecondColor )
304 Q_PROPERTY( QString firstText READ firstText WRITE setFirstText )
305 Q_PROPERTY( QString secondText READ secondText WRITE setSecondText )
306
307public:
308 /**
309 * Constructs a horizontal color selector which
310 * contains a gradient between white and black.
311 */
312 OGradientSelector( QWidget *parent=0, const char *name=0 );
313 /**
314 * Constructs a colors selector with orientation o which
315 * contains a gradient between white and black.
316 */
317 OGradientSelector( Orientation o, QWidget *parent=0, const char *name=0 );
318 /**
319 * Destructs the widget.
320 */
321 ~OGradientSelector();
322 /**
323 * Sets the two colors which span the gradient.
324 */
325 void setColors( const QColor &col1, const QColor &col2 )
326 {color1 = col1; color2 = col2; update();}
327 void setText( const QString &t1, const QString &t2 )
328 {text1 = t1; text2 = t2; update(); }
329
330 /**
331 * Set each color on its own.
332 */
333 void setFirstColor( const QColor &col )
334 { color1 = col; update(); }
335 void setSecondColor( const QColor &col )
336 { color2 = col; update(); }
337
338 /**
339 * Set each description on its own
340 */
341 void setFirstText( const QString &t )
342 { text1 = t; update(); }
343 void setSecondText( const QString &t )
344 { text2 = t; update(); }
345
346 const QColor firstColor() const
347 { return color1; }
348 const QColor secondColor() const
349 { return color2; }
350
351 const QString firstText() const
352 { return text1; }
353 const QString secondText() const
354 { return text2; }
355
356protected:
357 /**
358 * @reimplemented
359 */
360 virtual void drawContents( QPainter * );
361
362 /**
363 * @reimplemented
364 */
365 virtual QSize minimumSize() const
366 { return sizeHint(); }
367
368private:
369 void init();
370 QColor color1;
371 QColor color2;
372 QString text1;
373 QString text2;
374
375private:
376 class OGradientSelectorPrivate;
377 OGradientSelectorPrivate *d;
378};
379
380/**
381 * Widget for Hue/Saturation selection.
382 * The actual values can be fetched using the inherited xValue and yValue
383 * methods.
384 *
385 * @see OXYSelector, OValueSelector, OColorDialog
386 * @author Martin Jones (mjones@kde.org)
387 * @version $Id$
388*/
389class OHSSelector : public OXYSelector
390{
391 Q_OBJECT
392
393public:
394 /**
395 * Constructs a hue/saturation selection widget.
396 */
397 OHSSelector( QWidget *parent=0, const char *name=0 );
398
399protected:
400 /**
401 * Draws the contents of the widget on a pixmap,
402 * which is used for buffering.
403 */
404 virtual void drawPalette( QPixmap *pixmap );
405 /**
406 * @reimplemented
407 */
408 virtual void resizeEvent( QResizeEvent * );
409 /**
410 * Reimplemented from OXYSelector. This drawing is
411 * buffered in a pixmap here. As real drawing
412 * routine, drawPalette() is used.
413 */
414 virtual void drawContents( QPainter *painter );
415
416private:
417 void updateContents();
418 QPixmap pixmap;
419
420private:
421 class OHSSelectorPrivate;
422 OHSSelectorPrivate *d;
423};
424
425
426class OValueSelectorPrivate;
427/**
428 * Widget for color value selection.
429 *
430 * @see OHSSelector, OColorDialog
431 * @author Martin Jones (mjones@kde.org)
432 * @version $Id$
433 */
434class OValueSelector : public OSelector
435{
436 Q_OBJECT
437
438public:
439 /**
440 * Constructs a widget for color selection.
441 */
442 OValueSelector( QWidget *parent=0, const char *name=0 );
443 /**
444 * Constructs a widget for color selection with a given orientation
445 */
446 OValueSelector( Orientation o, QWidget *parent = 0, const char *name = 0 );
447
448 int hue() const
449 { return _hue; }
450 void setHue( int h )
451 { _hue = h; }
452 int saturation() const
453 { return _sat; }
454 void setSaturation( int s )
455 { _sat = s; }
456
457 void updateContents();
458protected:
459 /**
460 * Draws the contents of the widget on a pixmap,
461 * which is used for buffering.
462 */
463 virtual void drawPalette( QPixmap *pixmap );
464 /**
465 * @reimplemented
466 */
467 virtual void resizeEvent( QResizeEvent * );
468 /**
469 * Reimplemented from OSelector. The drawing is
470 * buffered in a pixmap here. As real drawing
471 * routine, drawPalette() is used.
472 */
473 virtual void drawContents( QPainter *painter );
474
475private:
476 int _hue;
477 int _sat;
478 QPixmap pixmap;
479
480private:
481 class OValueSelectorPrivate;
482 OValueSelectorPrivate *d;
483};
484
485
486class OColor : public QColor
487{
488public:
489 OColor();
490 OColor( const OColor &col);
491 OColor( const QColor &col);
492
493 OColor& operator=( const OColor& col);
494
495 bool operator==( const OColor& col) const;
496
497 void setHsv(int _h, int _s, int _v);
498 void setRgb(int _r, int _g, int _b);
499
500 void rgb(int *_r, int *_g, int *_b) const;
501 void hsv(int *_h, int *_s, int *_v) const;
502protected:
503 int h;
504 int s;
505 int v;
506 int r;
507 int g;
508 int b;
509
510private:
511 class OColorPrivate;
512 OColorPrivate *d;
513};
514
515
516
517 #endif // __OSELECT_H__
518
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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 Copyright (C) 1997 Michael Roth <mroth@wirlweb.de>
6 =.
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33/* QT */
34
35#include <qstyle.h>
36
37/* OPIE */
38
39#include <opie2/oseparator.h>
40
41OSeparator::OSeparator(QWidget* parent, const char* name, WFlags f)
42 : QFrame(parent, name, f)
43{
44 setLineWidth(1);
45 setMidLineWidth(0);
46 setOrientation( HLine );
47}
48
49
50
51OSeparator::OSeparator(int orientation, QWidget* parent, const char* name, WFlags f)
52 : QFrame(parent, name, f)
53{
54 setLineWidth(1);
55 setMidLineWidth(0);
56 setOrientation( orientation );
57}
58
59
60
61void OSeparator::setOrientation(int orientation)
62{
63 switch(orientation)
64 {
65 case Vertical:
66 case VLine:
67 setFrameStyle( QFrame::VLine | QFrame::Sunken );
68 setMinimumSize(2, 0);
69 break;
70
71 default:
72 qWarning( "OSeparator::setOrientation(): invalid orientation, using default orientation HLine" );
73
74 case Horizontal:
75 case HLine:
76 setFrameStyle( QFrame::HLine | QFrame::Sunken );
77 setMinimumSize(0, 2);
78 break;
79 }
80}
81
82
83
84int OSeparator::orientation() const
85{
86 if ( frameStyle() & VLine )
87 return VLine;
88
89 if ( frameStyle() & HLine )
90 return HLine;
91
92 return 0;
93}
94
95void OSeparator::drawFrame(QPainter *p)
96{
97 QPointp1, p2;
98 QRectr = frameRect();
99 const QColorGroup & g = colorGroup();
100
101 if ( frameStyle() & HLine ) {
102 p1 = QPoint( r.x(), r.height()/2 );
103 p2 = QPoint( r.x()+r.width(), p1.y() );
104 }
105 else {
106 p1 = QPoint( r.x()+r.width()/2, 0 );
107 p2 = QPoint( p1.x(), r.height() );
108 }
109
110#if QT_VERSION < 300
111 style().drawSeparator( p, p1.x(), p1.y(), p2.x(), p2.y(), g, true, 1, midLineWidth() );
112#else
113 QStyleOption opt( lineWidth(), midLineWidth() );
114 style().drawPrimitive( QStyle::PE_Separator, p, QRect( p1, p2 ), g, QStyle::Style_Sunken, opt );
115#endif
116}
117
118
119QSize OSeparator::sizeHint() const
120{
121 if ( frameStyle() & VLine )
122 return QSize(2, 0);
123
124 if ( frameStyle() & HLine )
125 return QSize(0, 2);
126
127 return QSize(-1, -1);
128}
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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 Copyright (C) 1997 Michael Roth <mroth@wirlweb.de>
6 =.
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33#ifndef OSEPARATOR_H
34#define OSEPARATOR_H
35
36#include <qframe.h>
37
38/**
39 * Standard horizontal or vertical separator.
40 *
41 * @author Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
42 * @author Michael Roth <mroth@wirlweb.de>
43 * @version $Id$
44*/
45class OSeparator : public QFrame
46{
47 Q_OBJECT
48 Q_PROPERTY( int orientation READ orientation WRITE setOrientation )
49 public:
50 /**
51 * Constructor.
52 **/
53 OSeparator(QWidget* parent=0, const char* name=0, WFlags f=0);
54 /**
55 * Constructor.
56 *
57 * @param orientation Set the orientation of the separator.
58 * Possible values are HLine or Horizontal and VLine or Vertical.
59 **/
60 OSeparator(int orientation, QWidget* parent=0, const char* name=0,
61 WFlags f=0);
62
63 /**
64 * Returns the orientation of the separator.
65 *
66 * Possible values are VLine and HLine.
67 **/
68 int orientation() const;
69
70 /**
71 * Set the orientation of the separator to @p orient
72 *
73 * Possible values are VLine and HLine.
74 */
75 void setOrientation(int orient);
76
77 /**
78 * The recommended height (width) for a horizontal (vertical) separator.
79 **/
80 virtual QSize sizeHint() const;
81
82protected:
83 virtual void drawFrame( QPainter * );
84
85private:
86 class OSeparatorPrivate* d;
87};
88
89
90#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 @@
1/*
2                 This file is part of the Opie Project
3
4 =. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 .=l.
6           .>+-=
7 _;:,     .>    :=|. This program is free software; you can
8.> <`_,   >  .   <= redistribute it and/or modify it under
9:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
10.="- .-=="i,     .._ License as published by the Free Software
11 - .   .-<_>     .<> Foundation; either version 2 of the License,
12     ._= =}       : or (at your option) any later version.
13    .%`+i>       _;_.
14    .i_,=:_.      -<s. This program is distributed in the hope that
15     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
16    : ..    .:,     . . . without even the implied warranty of
17    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
18  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.=       =       ; Library General Public License for more
20++=   -.     .`     .: details.
21 :     =  ...= . :.=-
22 -.   .:....=;==+<; You should have received a copy of the GNU
23  -_. . .   )=.  = Library General Public License along with
24    --        :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28
29*/
30
31/* QT */
32
33#include <qaction.h>
34#include <qbrush.h>
35#include <qfont.h>
36#include <qiconset.h>
37#include <qiconview.h>
38#include <qlistview.h>
39#include <qpalette.h>
40#include <qpoint.h>
41#include <qpopupmenu.h>
42#include <qrect.h>
43#include <qsize.h>
44#include <qstring.h>
45#include <qwidgetstack.h>
46
47/* OPIE */
48
49#include <opie2/oversatileview.h>
50#include <opie2/oversatileviewitem.h>
51#include <opie2/olistview.h>
52
53/* XPM */
54static const char * view_icon_xpm[] = {
55"16 16 16 1",
56 " c None",
57 ".c #87BD88",
58 "+c #8BBE8B",
59 "@c #81BA81",
60 "#c #6DAF6D",
61 "$c #87BD87",
62 "%c #FCFDFC",
63 "&c #AED0AE",
64 "*c #4E9C4C",
65 "=c #91BD91",
66 "-c #72B172",
67 ";c #448643",
68 ">c #519F50",
69 ",c #499247",
70 "'c #356A35",
71 ")c #686868",
72" ",
73" .+@# .+@# ",
74" $%&* $%&* ",
75" @=-; @=-; ",
76" #>,' #>,' ",
77" ",
78" )))))) )))))) ",
79" ",
80" ",
81" .+@# .+@# ",
82" $%&* $%&* ",
83" @=-; @=-; ",
84" #>,' #>,' ",
85" ",
86" )))))) )))))) ",
87" "};
88
89/* XPM */
90static const char * view_tree_xpm[] = {
91"16 16 17 1",
92 " c None",
93 ".c #3A3A3A",
94 "+c #87BD88",
95 "@c #8BBE8B",
96 "#c #81BA81",
97 "$c #6DAF6D",
98 "%c #87BD87",
99 "&c #FCFDFC",
100 "*c #AED0AE",
101 "=c #4E9C4C",
102 "-c #91BD91",
103 ";c #72B172",
104 ">c #448643",
105 ",c #686868",
106 "'c #519F50",
107 ")c #499247",
108 "!c #356A35",
109" . ",
110" . ",
111" . +@#$ ",
112" . %&*= ",
113" .. #-;> ,, ,,,",
114" . $')! ",
115" . ",
116" . ",
117" . ",
118" . +@#$ ",
119" . %&*= ",
120" .. #-;> ,, ,,,",
121" $')! ",
122" ",
123" ",
124" "};
125
126OVersatileView::OVersatileView( QWidget* parent, const char* name, int mode )
127 :QWidgetStack( parent, name ),
128 _viewmode( mode ), _warningpolicy( None ),
129 _treeleaf(), _treeopened(), _treeclosed(),
130 _iconleaf(), _iconopened(), _iconclosed()
131{
132 //
133 // Create child widgets and set some reasonable default styles
134 //
135
136 _listview = new OListView( this, "oversatileview embedded listview" );
137 _iconview = new QIconView( this, "oversatileview embedded iconview" );
138
139 _listview->setAllColumnsShowFocus( true );
140 _listview->setRootIsDecorated( true );
141 _listview->setShowSortIndicator( true );
142 _iconview->setGridX( 90 );
143 _iconview->setGridY( 42 );
144 _iconview->setAutoArrange( true );
145
146 #ifdef QWS // TODO: Let this depend on current geometry (rotation)
147 _iconview->setArrangement( QIconView::TopToBottom );
148 #else
149 _iconview->setArrangement( QIconView::LeftToRight );
150 #endif
151
152 _iconview->setResizeMode( QIconView::Adjust );
153
154 // qt-embedded: map stylus right on hold to right button press
155
156 #ifdef QWS
157 ( (QPEApplication*) qApp)->setStylusOperation( _iconview->viewport(), QPEApplication::RightOnHold );
158 ( (QPEApplication*) qApp)->setStylusOperation( _listview->viewport(), QPEApplication::RightOnHold );
159 #endif
160
161 setViewMode( mode ); // TODO: Read last style from config
162 // setSynchronization( true ); // TODO: Implement this
163
164 // create context menu allowing to switch between the views
165
166 _contextmenu = new QPopupMenu( 0, "oversatileview contextmenu" );
167 _contextmenu->setCaption( "Style" );
168 _contextmenu->setCheckable( true );
169 QActionGroup* ag = new QActionGroup( _contextmenu, "style option group" );
170 QAction* a1 = new QAction( "View Items in Icon Style", QIconSet( QPixmap( view_icon_xpm ) ),
171 "View Icons", 0, ag, "viewicon action", true );
172 QAction* a2 = new QAction( "View Items in Tree Style", QIconSet( QPixmap( view_tree_xpm ) ),
173 "View Tree", 0, ag, "viewtree action", true );
174 ag->addTo( _contextmenu );
175 if ( mode == Icons )
176 a1->setOn( true );
177 else if ( mode == Tree )
178 a2->setOn( true );
179 connect( a1, SIGNAL( activated() ), this, SLOT( setIconViewMode() ) );
180 connect( a2, SIGNAL( activated() ), this, SLOT( setTreeViewMode() ) );
181
182 #if (QT_VERSION >= 0x030000)
183 connect( _listview, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint&, int ) ), this, SLOT( contextMenuRequested( QListViewItem*, const QPoint&, int ) ) );
184 connect( _iconview, SIGNAL( contextMenuRequested( QIconViewItem*, const QPoint& ) ), this, SLOT( contextMenuRequested( QIconViewItem*, const QPoint& ) ) );
185 #else
186 connect( _listview, SIGNAL( rightButtonPressed( QListViewItem*, const QPoint&, int ) ), this, SLOT( contextMenuRequested( QListViewItem*, const QPoint&, int ) ) );
187 connect( _iconview, SIGNAL( rightButtonPressed( QIconViewItem*, const QPoint& ) ), this, SLOT( contextMenuRequested( QIconViewItem*, const QPoint& ) ) );
188 #endif
189
190 //
191 // signal forwarders
192 //
193 // unfortunately we can't short-circuit all the QListView and QIconView signals
194 // to OVersatileView signals, because the signal/slot mechanism doesn't allow
195 // type-conversion :-(
196
197 // common signals for listview
198
199 connect( _listview, SIGNAL( selectionChanged() ), this, SIGNAL( selectionChanged() ) );
200 connect( _listview, SIGNAL( selectionChanged( QListViewItem * ) ), this, SLOT( selectionChanged( QListViewItem * ) ) );
201 connect( _listview, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( currentChanged( QListViewItem * ) ) );
202 connect( _listview, SIGNAL( clicked( QListViewItem * ) ), this, SLOT( clicked( QListViewItem * ) ) );
203 connect( _listview, SIGNAL( pressed( QListViewItem * ) ), this, SLOT( pressed( QListViewItem * ) ) );
204
205 connect( _listview, SIGNAL( doubleClicked( QListViewItem * ) ), this, SLOT( doubleClicked( QListViewItem * ) ) );
206 connect( _listview, SIGNAL( returnPressed( QListViewItem * ) ), this, SLOT( returnPressed( QListViewItem * ) ) );
207
208 connect( _listview, SIGNAL( onItem( QListViewItem * ) ), this, SLOT( onItem( QListViewItem * ) ) );
209 connect( _listview, SIGNAL( onViewport() ), this, SIGNAL( onViewport() ) );
210
211 // common signals for iconview
212
213 connect( _iconview, SIGNAL( selectionChanged() ), this, SIGNAL( selectionChanged() ) );
214 connect( _iconview, SIGNAL( selectionChanged( QIconViewItem * ) ), this, SLOT( selectionChanged( QIconViewItem * ) ) );
215 connect( _iconview, SIGNAL( currentChanged( QIconViewItem * ) ), this, SLOT( currentChanged( QIconViewItem * ) ) );
216 connect( _iconview, SIGNAL( clicked( QIconViewItem * ) ), this, SLOT( clicked( QIconViewItem * ) ) );
217 connect( _iconview, SIGNAL( pressed( QIconViewItem * ) ), this, SLOT( pressed( QIconViewItem * ) ) );
218
219 connect( _iconview, SIGNAL( doubleClicked( QIconViewItem * ) ), this, SLOT( doubleClicked( QIconViewItem * ) ) );
220 connect( _iconview, SIGNAL( returnPressed( QIconViewItem * ) ), this, SLOT( returnPressed( QIconViewItem * ) ) );
221
222 connect( _iconview, SIGNAL( onItem( QIconViewItem * ) ), this, SLOT( onItem( QIconViewItem * ) ) );
223 connect( _iconview, SIGNAL( onViewport() ), this, SIGNAL( onViewport() ) );
224
225 // listview only signals
226
227 connect( _listview, SIGNAL( expanded( QListViewItem * ) ), this, SLOT( expanded( QListViewItem * ) ) );
228 connect( _listview, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( collapsed( QListViewItem * ) ) );
229
230 // iconview only signals
231
232 connect( _iconview, SIGNAL( moved() ), this, SIGNAL( moved() ) );
233}
234
235OVersatileView::~OVersatileView()
236{
237}
238
239QPopupMenu* OVersatileView::contextMenu() const
240{
241 return _contextmenu;
242}
243
244void OVersatileView::contextMenuRequested( QListViewItem* item, const QPoint& pos, int col )
245{
246 // can't use QObject::inherits here, because ListViewItems, beit Q, O or K,
247 // do not inherit from QObject - assuming here the programmer is
248 // disciplined enough to only add OVersatileViewItems to an OVersatileView
249 popupContextMenu( static_cast<OVersatileViewItem*>( item ), pos, col );
250}
251
252void OVersatileView::contextMenuRequested( QIconViewItem* item, const QPoint& pos )
253{
254 // see above
255 popupContextMenu( static_cast<OVersatileViewItem*>( item ), pos, -1 );
256}
257
258void OVersatileView::popupContextMenu( OVersatileViewItem* item, const QPoint& pos, int col )
259{
260 if ( not item )
261 _contextmenu->exec( pos );
262 else
263 emit( contextMenuRequested( item, pos, col ) );
264}
265
266void OVersatileView::setSynchronization( bool sync )
267{
268 _synchronization = sync;
269}
270
271bool OVersatileView::synchronization()
272{
273 return _synchronization;
274}
275
276void OVersatileView::setDefaultPixmaps( int mode, QPixmap& leaf, QPixmap& opened, QPixmap& closed )
277{
278 if ( mode == Tree )
279 {
280 _treeleaf = leaf;
281 _treeopened = opened;
282 _treeclosed = closed;
283 }
284 else if ( mode == Icons )
285 {
286 _iconleaf = leaf;
287 _iconopened = opened;
288 _iconclosed = closed;
289 }
290 else
291 {
292 qDebug( "OVersatileView::setDefaultPixmaps(): invalid mode" );
293 }
294}
295
296QIconView* OVersatileView::iconView() const
297{
298 return _iconview;
299}
300
301OListView* OVersatileView::listView() const
302{
303 return _listview;
304}
305
306void OVersatileView::setViewMode( int mode )
307{
308 if ( mode == Tree )
309 {
310 _viewmode = mode;
311 raiseWidget( _listview );
312 }
313 else if ( mode == Icons )
314 {
315 _viewmode = mode;
316 raiseWidget( _iconview );
317 }
318 else
319 {
320 qDebug( "OVersatileView::setViewMode(): invalid mode" );
321 }
322}
323
324void OVersatileView::setIconViewMode()
325{
326 setViewMode( Icons );
327}
328
329void OVersatileView::setTreeViewMode()
330{
331 setViewMode( Tree );
332}
333
334bool OVersatileView::isValidViewMode( int mode ) const
335{
336 switch ( _warningpolicy )
337 {
338 case OVersatileView::None:
339 {
340 return true;
341 }
342 case OVersatileView::Warn:
343 {
344 if ( _viewmode != mode )
345 {
346 qDebug( "OVersatileView::isValidViewMode(): Requested operation not valid in current mode." );
347 return true;
348 }
349 }
350 case OVersatileView::WarnReturn:
351 {
352 if ( _viewmode != mode )
353 {
354 qDebug( "OVersatileView::isValidViewMode(): Requested operation not valid in current mode." );
355 return false;
356 }
357 }
358 default:
359 {
360 qWarning( "OVersatileView::isValidViewMode(): Inconsistent object state!" );
361 return true;
362 }
363 }
364}
365void OVersatileView::setWarningPolicy( int policy ) const
366{
367 _warningpolicy = policy;
368}
369bool OVersatileView::warningPolicy() const
370{
371 return _warningpolicy;
372}
373//==============================================================================================//
374// Stupid Signal forwarders...
375// Folks, this is why I like python with its dynamic typing:
376// I can code the following dozens of lines C++ in four Python lines...
377//==============================================================================================//
378
379void OVersatileView::selectionChanged( QListViewItem * item )
380{
381 emit( selectionChanged( static_cast<OVersatileViewItem*>( item ) ) );
382}
383
384void OVersatileView::selectionChanged( QIconViewItem * item )
385{
386 emit( selectionChanged( static_cast<OVersatileViewItem*>( item ) ) );
387}
388
389void OVersatileView::currentChanged( QListViewItem * item )
390{
391 emit( currentChanged( static_cast<OVersatileViewItem*>( item ) ) );
392}
393
394void OVersatileView::currentChanged( QIconViewItem * item )
395{
396 emit( currentChanged( static_cast<OVersatileViewItem*>( item ) ) );
397}
398
399void OVersatileView::clicked( QListViewItem * item )
400{
401 emit( clicked( static_cast<OVersatileViewItem*>( item ) ) );
402}
403
404void OVersatileView::clicked( QIconViewItem * item )
405{
406 emit( clicked( static_cast<OVersatileViewItem*>( item ) ) );
407}
408
409void OVersatileView::pressed( QListViewItem * item )
410{
411 emit( pressed( static_cast<OVersatileViewItem*>( item ) ) );
412}
413
414void OVersatileView::pressed( QIconViewItem * item )
415{
416 emit( pressed( static_cast<OVersatileViewItem*>( item ) ) );
417}
418
419void OVersatileView::doubleClicked( QListViewItem * item )
420{
421 emit( doubleClicked( static_cast<OVersatileViewItem*>( item ) ) );
422}
423
424void OVersatileView::doubleClicked( QIconViewItem * item )
425{
426 emit( doubleClicked( static_cast<OVersatileViewItem*>( item ) ) );
427}
428
429void OVersatileView::returnPressed( QListViewItem * item )
430{
431 emit( returnPressed( static_cast<OVersatileViewItem*>( item ) ) );
432}
433
434void OVersatileView::returnPressed( QIconViewItem * item )
435{
436 emit( returnPressed( static_cast<OVersatileViewItem*>( item ) ) );
437}
438
439void OVersatileView::onItem( QListViewItem * item )
440{
441 emit( onItem( static_cast<OVersatileViewItem*>( item ) ) );
442}
443
444void OVersatileView::onItem( QIconViewItem * item )
445{
446 emit( onItem( static_cast<OVersatileViewItem*>( item ) ) );
447}
448
449void OVersatileView::expanded( QListViewItem *item ) // QListView
450{
451 //qDebug( "OVersatileView::expanded(): opening tree..." );
452 if ( not _treeopened.isNull() )
453 item->setPixmap( 0, _treeopened );
454 emit( expanded( static_cast<OVersatileViewItem*>( item ) ) );
455}
456void OVersatileView::collapsed( QListViewItem *item ) // QListView
457{
458 if ( not _treeclosed.isNull() )
459 item->setPixmap( 0, _treeclosed );
460 emit( collapsed( static_cast<OVersatileViewItem*>( item ) ) );
461}
462
463//=============================================================================================//
464// OVersatileView Case I - API only existing in QListView or QIconView but not in both!
465//==============================================================================================//
466
467int OVersatileView::treeStepSize() const // QListView
468{
469 if ( not isValidViewMode( Tree ) )
470 {
471 return -1;
472 }
473 return _listview->treeStepSize();
474}
475 void OVersatileView::setTreeStepSize( int size ) // QListView
476{
477 if ( not isValidViewMode( Tree ) )
478 {
479 return;
480 }
481 _listview->setTreeStepSize( size );
482}
483
484QHeader * OVersatileView::header() const // QListView
485{
486 if ( not isValidViewMode( Tree ) )
487 {
488 return 0;
489 }
490 return _listview->header();
491}
492
493 int OVersatileView::addColumn( const QString &label, int size ) // QListView
494{
495 if ( not isValidViewMode( Tree ) )
496 {
497 return -1;
498 }
499 return _listview->addColumn( label, size );
500}
501
502 int OVersatileView::addColumn( const QIconSet& iconset, const QString &label, int size ) // QListView
503{
504 if ( not isValidViewMode( Tree ) )
505 {
506 return -1;
507 }
508 return _listview->addColumn( iconset, label, size );
509}
510
511void OVersatileView::removeColumn( int index ) // QListView
512{
513 if ( not isValidViewMode( Tree ) )
514 {
515 return;
516 }
517 _listview->removeColumn( index );
518}
519 void OVersatileView::setColumnText( int column, const QString &label ) // QListView
520{
521 if ( not isValidViewMode( Tree ) )
522 {
523 return;
524 }
525 _listview->setColumnText( column, label );
526}
527 void OVersatileView::setColumnText( int column, const QIconSet& iconset, const QString &label ) // QListView
528{
529 if ( not isValidViewMode( Tree ) )
530 {
531 return;
532 }
533 _listview->setColumnText( column, iconset, label );
534}
535QString OVersatileView::columnText( int column ) const // QListView
536{
537 if ( not isValidViewMode( Tree ) )
538 {
539 return QString::null;
540 }
541 return _listview->columnText( column );
542}
543 void OVersatileView::setColumnWidth( int column, int width ) // QListView
544{
545 if ( not isValidViewMode( Tree ) )
546 {
547 return;
548 }
549 _listview->setColumnWidth( column, width );
550}
551int OVersatileView::columnWidth( int column ) const // QListView
552{
553 if ( not isValidViewMode( Tree ) )
554 {
555 return -1;
556 }
557 return _listview->columnWidth( column );
558}
559 void OVersatileView::setColumnWidthMode( int column, WidthMode mode ) // QListView
560{
561 if ( not isValidViewMode( Tree ) )
562 {
563 return;
564 }
565 _listview->setColumnWidth( column, mode );
566}
567int OVersatileView::columns() const // QListView
568{
569 if ( not isValidViewMode( Tree ) )
570 {
571 return -1;
572 }
573 return _listview->columns();
574}
575
576 void OVersatileView::setColumnAlignment( int column, int align ) // QListView
577{
578 if ( not isValidViewMode( Tree ) )
579 {
580 return;
581 }
582 _listview->setColumnAlignment( column, align );
583}
584int OVersatileView::columnAlignment( int column ) const // QListView
585{
586 if ( not isValidViewMode( Tree ) )
587 {
588 return -1;
589 }
590 return _listview->columnAlignment( column );
591}
592
593OVersatileViewItem * OVersatileView::itemAt( const QPoint & screenPos ) const // QListView
594{
595 if ( not isValidViewMode( Tree ) )
596 {
597 return 0;
598 }
599 return static_cast<OVersatileViewItem*>( _listview->itemAt( screenPos ) );
600}
601QRect OVersatileView::itemRect( const OVersatileViewItem * item ) const // QListView
602{
603 if ( not isValidViewMode( Tree ) )
604 {
605 return QRect( -1, -1, -1, -1 );
606 }
607 return _listview->itemRect( item );
608}
609int OVersatileView::itemPos( const OVersatileViewItem * item ) // QListView
610{
611 if ( not isValidViewMode( Tree ) )
612 {
613 return -1;
614 }
615 return _listview->itemPos( item );
616}
617
618bool OVersatileView::isSelected( const OVersatileViewItem * item ) const // QListView // also in QIconViewItem but !in QIconView *shrug*
619{
620 if ( not isValidViewMode( Tree ) )
621 {
622 return false;
623 }
624 return _listview->isSelected( item );
625}
626
627 void OVersatileView::setMultiSelection( bool enable )
628{
629 _listview->setMultiSelection( enable );
630}
631bool OVersatileView::isMultiSelection() const
632{
633 return _listview->isMultiSelection();
634}
635
636OVersatileViewItem * OVersatileView::selectedItem() const // QListView
637{
638 if ( not isValidViewMode( Tree ) )
639 {
640 return 0;
641 }
642 return static_cast<OVersatileViewItem*>( _listview->selectedItem() );
643}
644 void OVersatileView::setOpen( OVersatileViewItem * item, bool open ) // QListView
645{
646 if ( not isValidViewMode( Tree ) )
647 {
648 return;
649 }
650 _listview->setOpen( item, open );
651}
652bool OVersatileView::isOpen( const OVersatileViewItem * item ) const // QListView
653{
654 if ( not isValidViewMode( Tree ) )
655 {
656 return false;
657 }
658 return _listview->isOpen( item );
659}
660
661OVersatileViewItem * OVersatileView::firstChild() const // QListView
662{
663 if ( not isValidViewMode( Tree ) )
664 {
665 return 0;
666 }
667 return static_cast<OVersatileViewItem*>( _listview->firstChild() );
668}
669int OVersatileView::childCount() const // QListView
670{
671 if ( not isValidViewMode( Tree ) )
672 {
673 return -1;
674 }
675 return _listview->childCount();
676}
677
678 void OVersatileView::setAllColumnsShowFocus( bool focus ) // QListView
679{
680 if ( not isValidViewMode( Tree ) )
681 {
682 return;
683 }
684 _listview->setAllColumnsShowFocus( focus );
685}
686bool OVersatileView::allColumnsShowFocus() const // QListView
687{
688 if ( not isValidViewMode( Tree ) )
689 {
690 return false;
691 }
692 return _listview->allColumnsShowFocus();
693}
694
695 void OVersatileView::setItemMargin( int margin ) // QListView
696{
697 if ( not isValidViewMode( Tree ) )
698 {
699 return;
700 }
701 _listview->setItemMargin( margin );
702}
703int OVersatileView::itemMargin() const // QListView
704{
705 if ( not isValidViewMode( Tree ) )
706 {
707 return -1;
708 }
709 return _listview->itemMargin();
710}
711
712 void OVersatileView::setRootIsDecorated( bool decorate ) // QListView
713{
714 if ( not isValidViewMode( Tree ) )
715 {
716 return;
717 }
718 _listview->setRootIsDecorated( decorate );
719}
720bool OVersatileView::rootIsDecorated() const // QListView
721{
722 if ( not isValidViewMode( Tree ) )
723 {
724 return false;
725 }
726 return _listview->rootIsDecorated();
727}
728
729void OVersatileView::setShowSortIndicator( bool show ) // QListView
730{
731 if ( not isValidViewMode( Tree ) )
732 {
733 return;
734 }
735 _listview->setShowSortIndicator( show );
736}
737bool OVersatileView::showSortIndicator() const // QListView
738{
739 if ( not isValidViewMode( Tree ) )
740 {
741 return false;
742 }
743 return _listview->showSortIndicator();
744}
745
746void OVersatileView::triggerUpdate() // QListView
747{
748 if ( not isValidViewMode( Tree ) )
749 {
750 return;
751 }
752 _listview->triggerUpdate();
753}
754
755//
756// only in QIconView
757//
758
759uint OVersatileView::count() const // QIconView
760{
761 if ( not isValidViewMode( Icons ) )
762 {
763 return 0;
764 }
765 return _iconview->count();
766}
767
768int OVersatileView::index( const OVersatileViewItem *item ) const // QIconView
769{
770 if ( not isValidViewMode( Icons ) )
771 {
772 return -1;
773 }
774 return _iconview->index( item );
775}
776
777OVersatileViewItem* OVersatileView::firstItem() const // QIconView
778{
779 if ( not isValidViewMode( Icons ) )
780 {
781 return 0;
782 }
783 return static_cast<OVersatileViewItem*>( _iconview->firstItem() );
784}
785OVersatileViewItem* OVersatileView::lastItem() const // QIconView
786{
787 if ( not isValidViewMode( Icons ) )
788 {
789 return 0;
790 }
791 return static_cast<OVersatileViewItem*>( _iconview->lastItem() );
792}
793
794OVersatileViewItem* OVersatileView::findItem( const QPoint &pos ) const // QIconView
795{
796 if ( not isValidViewMode( Icons ) )
797 {
798 return 0;
799 }
800 return static_cast<OVersatileViewItem*>( _iconview->findItem( pos ) );
801}
802OVersatileViewItem* OVersatileView::findItem( const QString &text ) const // QIconView
803{
804 if ( not isValidViewMode( Icons ) )
805 {
806 return 0;
807 }
808 return static_cast<OVersatileViewItem*>( _iconview->findItem( text ) );
809}
810
811OVersatileViewItem* OVersatileView::findFirstVisibleItem( const QRect &r ) const // QIconView
812{
813 if ( not isValidViewMode( Icons ) )
814 {
815 return 0;
816 }
817 return static_cast<OVersatileViewItem*>( _iconview->findFirstVisibleItem( r ) );
818}
819OVersatileViewItem* OVersatileView::findLastVisibleItem( const QRect &r ) const // QIconView
820{
821 if ( not isValidViewMode( Icons ) )
822 {
823 return 0;
824 }
825 return static_cast<OVersatileViewItem*>( _iconview->findLastVisibleItem( r ) );
826}
827
828 void OVersatileView::setGridX( int rx ) // QIconView
829{
830 if ( not isValidViewMode( Icons ) )
831 {
832 return;
833 }
834 _iconview->setGridX( rx );
835}
836 void OVersatileView::setGridY( int ry ) // QIconView
837{
838 if ( not isValidViewMode( Icons ) )
839 {
840 return;
841 }
842 _iconview->setGridY( ry );
843}
844int OVersatileView::gridX() const // QIconView
845{
846 if ( not isValidViewMode( Icons ) )
847 {
848 return -1;
849 }
850 return _iconview->gridX();
851}
852int OVersatileView::gridY() const // QIconView
853{
854 if ( not isValidViewMode( Icons ) )
855 {
856 return -1;
857 }
858 return _iconview->gridY();
859}
860 void OVersatileView::setSpacing( int sp ) // QIconView
861{
862 if ( not isValidViewMode( Icons ) )
863 {
864 return;
865 }
866 _iconview->setSpacing( sp );
867}
868int OVersatileView::spacing() const // QIconView
869{
870 if ( not isValidViewMode( Icons ) )
871 {
872 return -1;
873 }
874 return _iconview->spacing();
875}
876 void OVersatileView::setItemTextPos( QIconView::ItemTextPos pos ) // QIconView
877{
878 if ( not isValidViewMode( Icons ) )
879 {
880 return;
881 }
882 _iconview->setItemTextPos( pos );
883}
884QIconView::ItemTextPos OVersatileView::itemTextPos() const // QIconView
885{
886 if ( not isValidViewMode( Icons ) )
887 {
888 return (QIconView::ItemTextPos) -1;
889 }
890 return _iconview->itemTextPos();
891}
892 void OVersatileView::setItemTextBackground( const QBrush &b ) // QIconView
893{
894 if ( not isValidViewMode( Icons ) )
895 {
896 return;
897 }
898 _iconview->setItemTextBackground( b );
899}
900QBrush OVersatileView::itemTextBackground() const // QIconView
901{
902 if ( not isValidViewMode( Icons ) )
903 {
904 return QBrush();
905 }
906 return _iconview->itemTextBackground();
907}
908 void OVersatileView::setArrangement( QIconView::Arrangement am ) // QIconView
909{
910 if ( not isValidViewMode( Icons ) )
911 {
912 return;
913 }
914 _iconview->setArrangement( am );
915}
916QIconView::Arrangement OVersatileView::arrangement() const // QIconView
917{
918 if ( not isValidViewMode( Icons ) )
919 {
920 return (QIconView::Arrangement) -1;
921 }
922 return _iconview->arrangement();
923}
924 void OVersatileView::setResizeMode( QIconView::ResizeMode am ) // QIconView
925{
926 if ( not isValidViewMode( Icons ) )
927 {
928 return;
929 }
930 _iconview->setResizeMode( am );
931}
932QIconView::ResizeMode OVersatileView::resizeMode() const // QIconView
933{
934 if ( not isValidViewMode( Icons ) )
935 {
936 return (QIconView::ResizeMode) -1;
937 }
938 return _iconview->resizeMode();
939}
940 void OVersatileView::setMaxItemWidth( int w ) // QIconView
941{
942 if ( not isValidViewMode( Icons ) )
943 {
944 return;
945 }
946 _iconview->setMaxItemWidth( w );
947}
948int OVersatileView::maxItemWidth() const // QIconView
949{
950 if ( not isValidViewMode( Icons ) )
951 {
952 return -1;
953 }
954 return _iconview->maxItemWidth();
955}
956 void OVersatileView::setMaxItemTextLength( int w ) // QIconView
957{
958 if ( not isValidViewMode( Icons ) )
959 {
960 return;
961 }
962 _iconview->setMaxItemTextLength( w );
963}
964int OVersatileView::maxItemTextLength() const // QIconView
965{
966 if ( not isValidViewMode( Icons ) )
967 {
968 return -1;
969 }
970 return _iconview->maxItemTextLength();
971}
972 void OVersatileView::setAutoArrange( bool b ) // QIconView
973{
974 if ( not isValidViewMode( Icons ) )
975 {
976 return;
977 }
978 _iconview->setAutoArrange( b );
979}
980bool OVersatileView::autoArrange() const // QIconView
981{
982 if ( not isValidViewMode( Icons ) )
983 {
984 return false;
985 }
986 return _iconview->autoArrange();
987}
988 void OVersatileView::setShowToolTips( bool b ) // QIconView
989{
990 if ( not isValidViewMode( Icons ) )
991 {
992 return;
993 }
994 _iconview->setShowToolTips( b );
995}
996bool OVersatileView::showToolTips() const // QIconView
997{
998 if ( not isValidViewMode( Icons ) )
999 {
1000 return false;
1001 }
1002 return _iconview->showToolTips();
1003}
1004
1005bool OVersatileView::sorting() const // QIconView
1006{
1007 if ( not isValidViewMode( Icons ) )
1008 {
1009 return false;
1010 }
1011 return _iconview->sorting();
1012}
1013bool OVersatileView::sortDirection() const // QIconView
1014{
1015 if ( not isValidViewMode( Icons ) )
1016 {
1017 return false;
1018 }
1019 return _iconview->sortDirection();
1020}
1021
1022 void OVersatileView::setItemsMovable( bool b ) // QIconView
1023{
1024 if ( not isValidViewMode( Icons ) )
1025 {
1026 return;
1027 }
1028 _iconview->setItemsMovable( b );
1029}
1030bool OVersatileView::itemsMovable() const // QIconView
1031{
1032 if ( not isValidViewMode( Icons ) )
1033 {
1034 return false;
1035 }
1036 return _iconview->itemsMovable();
1037}
1038void OVersatileView::setWordWrapIconText( bool b ) // QIconView
1039{
1040 if ( not isValidViewMode( Icons ) )
1041 {
1042 return;
1043 }
1044 _iconview->setWordWrapIconText( b );
1045}
1046bool OVersatileView::wordWrapIconText() const // QIconView
1047{
1048 if ( not isValidViewMode( Icons ) )
1049 {
1050 return false;
1051 }
1052 return _iconview->wordWrapIconText();
1053}
1054
1055void OVersatileView::arrangeItemsInGrid( const QSize &grid, bool update ) // QIconView
1056{
1057 if ( not isValidViewMode( Icons ) )
1058 {
1059 return;
1060 }
1061 _iconview->arrangeItemsInGrid( grid, update );
1062}
1063void OVersatileView::arrangeItemsInGrid( bool update ) // QIconView
1064{
1065 if ( not isValidViewMode( Icons ) )
1066 {
1067 return;
1068 }
1069 _iconview->arrangeItemsInGrid( update );
1070}
1071void OVersatileView::updateContents() // QIconView
1072{
1073 if ( not isValidViewMode( Icons ) )
1074 {
1075 return;
1076 }
1077 _iconview->updateContents();
1078}
1079
1080//==============================================================================================//
1081// OVersatileView Case II - QListView / QIconView common API
1082//==============================================================================================//
1083
1084void OVersatileView::clear()
1085{
1086 _iconview->clear();
1087 _listview->clear();
1088}
1089
1090void OVersatileView::setFont( const QFont & font )
1091{
1092 _iconview->setFont( font );
1093 _listview->setFont( font );
1094}
1095void OVersatileView::setPalette( const QPalette & palette )
1096{
1097 _iconview->setPalette( palette );
1098 _listview->setPalette( palette );
1099}
1100
1101void OVersatileView::takeItem( OVersatileViewItem * item )
1102{
1103 _iconview->takeItem( item );
1104 _listview->takeItem( item );
1105}
1106
1107void OVersatileView::setSelectionMode( SelectionMode mode )
1108{
1109 _iconview->setSelectionMode( (QIconView::SelectionMode) mode );
1110 _listview->setSelectionMode( (QListView::SelectionMode) mode );
1111}
1112OVersatileView::SelectionMode OVersatileView::selectionMode() const
1113{
1114 return (OVersatileView::SelectionMode) _iconview->selectionMode();
1115}
1116
1117void OVersatileView::selectAll( bool select )
1118{
1119 _iconview->selectAll( select );
1120}
1121void OVersatileView::clearSelection()
1122{
1123 _iconview->clearSelection();
1124 _listview->clearSelection();
1125}
1126void OVersatileView::invertSelection()
1127{
1128 _iconview->invertSelection();
1129 _listview->invertSelection();
1130}
1131
1132void OVersatileView::ensureItemVisible( const OVersatileViewItem * item )
1133{
1134 _iconview->ensureItemVisible( const_cast<OVersatileViewItem*>( item ) );
1135 _listview->ensureItemVisible( item );
1136}
1137void OVersatileView::repaintItem( const OVersatileViewItem * item ) const
1138{
1139 _iconview->repaintItem( const_cast<OVersatileViewItem*>( item ) );
1140 _listview->repaintItem( item );
1141}
1142
1143void OVersatileView::setCurrentItem( OVersatileViewItem * item )
1144{
1145 _iconview->setCurrentItem( item );
1146 _listview->setCurrentItem( item );
1147}
1148OVersatileViewItem * OVersatileView::currentItem() const
1149{
1150 return static_cast<OVersatileViewItem*>( _listview->currentItem() );
1151}
1152
1153// bool eventFilter( QObject * o, QEvent * ) // use QWidgetStack implementation
1154
1155// QSize minimumSizeHint() const // use QWidgetStack implementation
1156// QSizePolicy sizePolicy() const // use QWidgetStack implementation
1157// QSize sizeHint() const // use QWidgetStack implementation
1158
1159//==============================================================================================//
1160// OVersatileView Case III - APIs which differ slightly
1161//==============================================================================================//
1162
1163/*
1164
1165 void OVersatileView::insertItem( OVersatileViewItem * ) // QListView
1166 void OVersatileView::insertItem( OVersatileViewItem *item, OVersatileViewItem *after = 0L ) // QIconView
1167
1168 void OVersatileView::setSelected( OVersatileViewItem *, bool ) // QListView
1169 void OVersatileView::setSelected( OVersatileViewItem *item, bool s, bool cb = FALSE ) // QIconView
1170
1171 void OVersatileView::setSorting( int column, bool increasing = TRUE ) // QListView
1172void OVersatileView::setSorting( bool sort, bool ascending = TRUE ) // QIconView
1173
1174void OVersatileView::sort() // #### make in next major release // QListView
1175 void OVersatileView::sort( bool ascending = TRUE ) // QIconView
1176
1177*/
1178
1179
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 @@
1/*
2                 This file is part of the Opie Project
3
4 =. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 .=l.
6           .>+-=
7 _;:,     .>    :=|. This program is free software; you can
8.> <`_,   >  .   <= redistribute it and/or modify it under
9:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
10.="- .-=="i,     .._ License as published by the Free Software
11 - .   .-<_>     .<> Foundation; either version 2 of the License,
12     ._= =}       : or (at your option) any later version.
13    .%`+i>       _;_.
14    .i_,=:_.      -<s. This program is distributed in the hope that
15     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
16    : ..    .:,     . . . without even the implied warranty of
17    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
18  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.=       =       ; Library General Public License for more
20++=   -.     .`     .: details.
21 :     =  ...= . :.=-
22 -.   .:....=;==+<; You should have received a copy of the GNU
23  -_. . .   )=.  = Library General Public License along with
24    --        :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28
29*/
30
31#ifndef OVERSATILEVIEW_H
32#define OVERSATILEVIEW_H
33
34/* QT */
35
36#include <qwidgetstack.h>
37#include <qiconview.h>
38
39/* OPIE */
40
41#include <qpe/qpeapplication.h>
42
43/* FORWARDS */
44
45class QHeader;
46class QIconSet;
47class QIconViewItem;
48class OListView;
49class QListViewItem;
50class QPopupMenu;
51class QString;
52
53#ifndef QT_NO_DRAGANDDROP
54class QIconDragItem;
55#endif
56
57class OVersatileView : public QWidgetStack
58{
59 Q_OBJECT
60
61 friend class OVersatileViewItem;
62
63 //==============================================================================================//
64 // OVersatileView High Level API
65 //==============================================================================================//
66
67 public:
68 OVersatileView( QWidget* parent = 0, const char* name = 0, int mode = 0 );
69 ~OVersatileView();
70
71 QPopupMenu* contextMenu() const;
72
73 void setSynchronization( bool sync );
74 bool synchronization();
75
76 enum ViewMode { Tree = 0, Icons };
77 int viewMode();
78
79 QIconView* iconView() const;
80 OListView* listView() const;
81
82 enum WarningPolicy { None = 0, Warn, WarnReturn };
83
84 void setWarningPolicy( int ) const; // warn, if calling a method which doesn't apply to the current viewmode
85 bool warningPolicy() const;
86
87 void setDefaultPixmaps( int mode, QPixmap& leaf, QPixmap& opened, QPixmap& closed );
88
89 public slots:
90 void setViewMode( int mode );
91 void setIconViewMode();
92 void setTreeViewMode();
93
94 protected:
95 virtual bool isValidViewMode( int mode ) const;
96 virtual void popupContextMenu( OVersatileViewItem* item, const QPoint& pos, int col = 0 );
97
98 private:
99 int _viewmode;
100 bool _synchronization;
101 mutable int _warningpolicy;
102
103 OListView* _listview;
104 QIconView* _iconview;
105
106 QPixmap _treeleaf;
107 QPixmap _treeopened;
108 QPixmap _treeclosed;
109
110 QPixmap _iconleaf;
111 QPixmap _iconopened;
112 QPixmap _iconclosed;
113
114 QPopupMenu* _contextmenu;
115
116 int _iconstyle;
117 int _treestyle;
118
119 private slots:
120
121 void contextMenuRequested( QListViewItem*, const QPoint&, int );
122 void contextMenuRequested( QIconViewItem*, const QPoint& );
123
124 // type converting signal forwarders
125
126 void selectionChanged( QListViewItem * );
127 void currentChanged( QListViewItem * );
128 void clicked( QListViewItem * );
129 void pressed( QListViewItem * );
130 void doubleClicked( QListViewItem * );
131 void returnPressed( QListViewItem * );
132 void onItem( QListViewItem * );
133
134 void selectionChanged( QIconViewItem * );
135 void currentChanged( QIconViewItem * );
136 void clicked( QIconViewItem * );
137 void pressed( QIconViewItem * );
138 void doubleClicked( QIconViewItem * );
139 void returnPressed( QIconViewItem * );
140 void onItem( QIconViewItem * );
141
142 void expanded( QListViewItem * item ); // QListView
143 void collapsed( QListViewItem * item ); // QListView
144
145 signals:
146
147 void contextMenuRequested( OVersatileViewItem * item, const QPoint& pos, int col );
148
149 /*#ifndef QT_NO_DRAGANDDROP
150 void dropped( QDropEvent *e, const QValueList<QIconDragItem> &lst ); // QIconView
151 #endif
152 void itemRenamed( OVersatileViewItem *item, const QString & ); // QIconView
153 void itemRenamed( OVersatileViewItem *item ); // QIconView
154 */
155
156 //==============================================================================================//
157 // "Derived" API - Case 1: Methods existing either only in QListView or only in QIconView
158 //==============================================================================================//
159
160public:
161
162 /*
163 enum Arrangement { // QIconView
164 LeftToRight = 0,
165 TopToBottom
166 };
167 enum ResizeMode { // QIconView
168 Fixed = 0,
169 Adjust
170 };
171 enum ItemTextPos { // QIconView
172 Bottom = 0,
173 Right
174 };
175 */
176
177 //
178 // only in QListView
179 //
180
181 int treeStepSize() const; // QListView
182 virtual void setTreeStepSize( int ); // QListView
183
184 QHeader * header() const; // QListView
185
186 virtual int addColumn( const QString &label, int size = -1); // QListView
187 virtual int addColumn( const QIconSet& iconset, const QString &label, int size = -1); // QListView
188 void removeColumn( int index ); // #### make virtual in next major release! // QListView
189 virtual void setColumnText( int column, const QString &label ); // QListView
190 virtual void setColumnText( int column, const QIconSet& iconset, const QString &label ); // QListView
191 QString columnText( int column ) const; // QListView
192 virtual void setColumnWidth( int column, int width ); // QListView
193 int columnWidth( int column ) const; // QListView
194 enum WidthMode { Manual, Maximum }; // QListView
195 virtual void setColumnWidthMode( int column, WidthMode ); // QListView
196 WidthMode columnWidthMode( int column ) const; // QListView
197 int columns() const; // QListView
198
199 virtual void setColumnAlignment( int, int ); // QListView
200 int columnAlignment( int ) const; // QListView
201
202 OVersatileViewItem * itemAt( const QPoint & screenPos ) const; // QListView
203 QRect itemRect( const OVersatileViewItem * ) const; // QListView
204 int itemPos( const OVersatileViewItem * ); // QListView
205
206 bool isSelected( const OVersatileViewItem * ) const; // QListView // also in QIconViewItem but not in QIconView *shrug*
207
208 virtual void setMultiSelection( bool enable ); // QListView
209 bool isMultiSelection() const; // QListView
210
211 OVersatileViewItem * selectedItem() const; // QListView
212 virtual void setOpen( OVersatileViewItem *, bool ); // QListView
213 bool isOpen( const OVersatileViewItem * ) const; // QListView
214
215 OVersatileViewItem * firstChild() const; // QListView
216 int childCount() const; // QListView
217
218 virtual void setAllColumnsShowFocus( bool ); // QListView
219 bool allColumnsShowFocus() const; // QListView
220
221 virtual void setItemMargin( int ); // QListView
222 int itemMargin() const; // QListView
223
224 virtual void setRootIsDecorated( bool ); // QListView
225 bool rootIsDecorated() const; // QListView
226
227 void setShowSortIndicator( bool show ); // QListView
228 bool showSortIndicator() const; // QListView
229
230 int index( const OVersatileViewItem *item ) const; // QIconView
231
232 public slots:
233 void triggerUpdate(); // QListView
234
235 signals:
236 void expanded( OVersatileViewItem *item ); // QListView
237 void collapsed( OVersatileViewItem *item ); // QListView
238
239 //
240 // only in QIconView
241 //
242
243 public:
244 uint count() const; // QIconView
245
246 OVersatileViewItem *firstItem() const; // QIconView
247 OVersatileViewItem *lastItem() const; // QIconView
248
249 OVersatileViewItem *findItem( const QPoint &pos ) const; // QIconView
250 OVersatileViewItem *findItem( const QString &text ) const; // QIconView
251
252 OVersatileViewItem* findFirstVisibleItem( const QRect &r ) const; // QIconView
253 OVersatileViewItem* findLastVisibleItem( const QRect &r ) const; // QIconView
254
255 virtual void setGridX( int rx ); // QIconView
256 virtual void setGridY( int ry ); // QIconView
257 int gridX() const; // QIconView
258 int gridY() const; // QIconView
259 virtual void setSpacing( int sp ); // QIconView
260 int spacing() const; // QIconView
261 virtual void setItemTextPos( QIconView::ItemTextPos pos ); // QIconView
262 QIconView::ItemTextPos itemTextPos() const; // QIconView
263 virtual void setItemTextBackground( const QBrush &b ); // QIconView
264 QBrush itemTextBackground() const; // QIconView
265 virtual void setArrangement( QIconView::Arrangement am ); // QIconView
266 QIconView::Arrangement arrangement() const; // QIconView
267 virtual void setResizeMode( QIconView::ResizeMode am ); // QIconView
268 QIconView::ResizeMode resizeMode() const; // QIconView
269 virtual void setMaxItemWidth( int w ); // QIconView
270 int maxItemWidth() const; // QIconView
271 virtual void setMaxItemTextLength( int w ); // QIconView
272 int maxItemTextLength() const; // QIconView
273 virtual void setAutoArrange( bool b ); // QIconView
274 bool autoArrange() const; // QIconView
275 virtual void setShowToolTips( bool b ); // QIconView
276 bool showToolTips() const; // QIconView
277
278 bool sorting() const; // QIconView
279 bool sortDirection() const; // QIconView
280
281 virtual void setItemsMovable( bool b ); // QIconView
282 bool itemsMovable() const; // QIconView
283 virtual void setWordWrapIconText( bool b ); // QIconView
284 bool wordWrapIconText() const; // QIconView
285
286 public slots:
287 virtual void arrangeItemsInGrid( const QSize &grid, bool update = TRUE ); // QIconView
288 virtual void arrangeItemsInGrid( bool update = TRUE ); // QIconView
289 virtual void updateContents(); // QIconView
290
291 signals:
292 /*#ifndef QT_NO_DRAGANDDROP
293 void dropped( QDropEvent *e, const QValueList<QIconDragItem> &lst ); // QIconView
294 #endif
295 */
296 void moved(); // QIconView
297 void itemRenamed( OVersatileViewItem *item, const QString & ); // QIconView
298 void itemRenamed( OVersatileViewItem *item ); // QIconView
299
300 //==============================================================================================//
301 // "Derived" API - Case 2: Methods existing in QListView and QIconView with the same signatures
302 //==============================================================================================//
303
304 public:
305 enum SelectionMode {
306 Single = 0,
307 Multi,
308 Extended,
309 NoSelection
310 };
311
312 virtual void clear();
313
314 virtual void setFont( const QFont & );
315 virtual void setPalette( const QPalette & );
316
317 virtual void takeItem( OVersatileViewItem * );
318
319 void setSelectionMode( SelectionMode mode );
320 SelectionMode selectionMode() const;
321
322 virtual void selectAll( bool select );
323 virtual void clearSelection();
324 virtual void invertSelection();
325
326 void ensureItemVisible( const OVersatileViewItem * );
327 virtual void repaintItem( const OVersatileViewItem * ) const;
328
329 virtual void setCurrentItem( OVersatileViewItem * );
330 OVersatileViewItem * currentItem() const;
331
332 // bool eventFilter( QObject * o, QEvent * ); // use QWidgetStack implementation
333
334 // QSize minimumSizeHint() const; // use QWidgetStack implementation
335 // QSizePolicy sizePolicy() const; // use QWidgetStack implementation
336 // QSize sizeHint() const; // use QWidgetStack implementation
337
338 signals:
339 void selectionChanged();
340 void selectionChanged( OVersatileViewItem * );
341 void currentChanged( OVersatileViewItem * );
342 void clicked( OVersatileViewItem * );
343 void pressed( OVersatileViewItem * );
344
345 void doubleClicked( OVersatileViewItem * );
346 void returnPressed( OVersatileViewItem * );
347
348 void onItem( OVersatileViewItem * );
349 void onViewport();
350
351 //==============================================================================================//
352 // "Derived" API - Case 2: Methods existing in QListView and QIconView with differing signatures
353 //==============================================================================================//
354
355 /*
356
357 public:
358 virtual void insertItem( OVersatileViewItem * ); // QListView
359 virtual void insertItem( OVersatileViewItem *item, OVersatileViewItem *after = 0L ); // QIconView
360
361 virtual void setSelected( OVersatileViewItem *, bool ); // QListView
362 virtual void setSelected( OVersatileViewItem *item, bool s, bool cb = FALSE ); // QIconView
363
364 virtual void setSorting( int column, bool increasing = TRUE ); // QListView
365 void setSorting( bool sort, bool ascending = TRUE ); // QIconView
366
367 void sort(); // #### make virtual in next major release // QListView
368 virtual void sort( bool ascending = TRUE ); // QIconView
369
370 */
371
372 signals:
373 void clicked( OVersatileViewItem *, const QPoint &, int ); // QListView
374 void clicked( OVersatileViewItem *, const QPoint & ); // QIconView
375
376 void pressed( OVersatileViewItem *, const QPoint &, int ); // QListView
377 void pressed( OVersatileViewItem *, const QPoint & ); // QIconView
378
379 void rightButtonClicked( OVersatileViewItem* item, const QPoint& pos ); // QIconView
380 void rightButtonClicked( OVersatileViewItem *, const QPoint&, int ); // QListView
381
382 void rightButtonPressed( OVersatileViewItem* item, const QPoint& pos ); // QIconView
383 void rightButtonPressed( OVersatileViewItem *, const QPoint&, int ); // QListView
384
385 void mouseButtonPressed( int, OVersatileViewItem *, const QPoint& , int ); // QListView
386 void mouseButtonPressed( int button, OVersatileViewItem* item, const QPoint& pos ); // QIconView
387
388 void mouseButtonClicked( int, OVersatileViewItem *, const QPoint&, int ); // QListView
389 void mouseButtonClicked( int button, OVersatileViewItem* item, const QPoint& pos ); // QIconView
390
391};
392
393#endif
394
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 @@
1/*
2                 This file is part of the Opie Project
3
4 =. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 .=l.
6           .>+-=
7 _;:,     .>    :=|. This program is free software; you can
8.> <`_,   >  .   <= redistribute it and/or modify it under
9:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
10.="- .-=="i,     .._ License as published by the Free Software
11 - .   .-<_>     .<> Foundation; either version 2 of the License,
12     ._= =}       : or (at your option) any later version.
13    .%`+i>       _;_.
14    .i_,=:_.      -<s. This program is distributed in the hope that
15     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
16    : ..    .:,     . . . without even the implied warranty of
17    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
18  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.=       =       ; Library General Public License for more
20++=   -.     .`     .: details.
21 :     =  ...= . :.=-
22 -.   .:....=;==+<; You should have received a copy of the GNU
23  -_. . .   )=.  = Library General Public License along with
24    --        :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28
29*/
30
31#include <opie2/oversatileviewitem.h>
32#include <opie2/oversatileview.h>
33
34OVersatileViewItem::OVersatileViewItem( OVersatileView * parent )
35 :OListViewItem( parent->_listview ), QIconViewItem( parent->_iconview ),
36 _versatileview( parent )
37{
38 init();
39}
40
41OVersatileViewItem::OVersatileViewItem( OVersatileView * parent, OVersatileViewItem * after )
42 :OListViewItem( parent->_listview, after ), QIconViewItem( parent->_iconview, after ),
43 _versatileview( parent )
44{
45 init();
46}
47
48OVersatileViewItem::OVersatileViewItem( OVersatileView * parent,
49 QString a, QString b, QString c, QString d,
50 QString e, QString f, QString g, QString h )
51 :OListViewItem( parent->_listview, a, b, c, d, e, f, g, h ),
52 QIconViewItem( parent->_iconview, a ),
53 _versatileview( parent )
54{
55 init();
56}
57
58OVersatileViewItem::OVersatileViewItem( OVersatileView * parent, OVersatileViewItem* after,
59 QString a, QString b, QString c, QString d,
60 QString e, QString f, QString g, QString h )
61 :OListViewItem( parent->_listview, after, a, b, c, d, e, f, g, h ),
62 QIconViewItem( parent->_iconview, after, a ),
63 _versatileview( parent )
64{
65 init();
66}
67
68OVersatileViewItem::OVersatileViewItem( OVersatileViewItem * parent,
69 QString a, QString b, QString c, QString d,
70 QString e, QString f, QString g, QString h )
71 :OListViewItem( parent, a, b, c, d, e, f, g, h ),
72 QIconViewItem( parent->_versatileview->_iconview, a ),
73 _versatileview( parent->_versatileview )
74{
75 init();
76}
77
78OVersatileViewItem::OVersatileViewItem( OVersatileViewItem * parent, OVersatileViewItem* after,
79 QString a, QString b, QString c, QString d,
80 QString e, QString f, QString g, QString h )
81 :OListViewItem( parent, after, a, b, c, d, e, f, g, h ),
82 QIconViewItem( parent->_versatileview->_iconview, after, a ),
83 _versatileview( parent->_versatileview )
84{
85 init();
86}
87
88OVersatileViewItem::~OVersatileViewItem()
89{
90}
91
92OVersatileView* OVersatileViewItem::versatileView() const
93{
94 return _versatileview;
95}
96
97void OVersatileViewItem::init()
98{
99 if ( not firstChild() )
100 {
101 // I'm a sweet yellow and browne autumn leaf
102
103 OListViewItem::setPixmap( 0, _versatileview->_treeleaf );
104 QIconViewItem::setPixmap( _versatileview->_iconleaf );
105 }
106 else
107 {
108 // I'm a node and I have a little baby child
109
110 if ( isOpen() )
111 {
112 OListViewItem::setPixmap( 0, _versatileview->_treeopened );
113 QIconViewItem::setPixmap( _versatileview->_iconopened );
114 }
115 else
116 {
117 OListViewItem::setPixmap( 0, _versatileview->_treeclosed );
118 QIconViewItem::setPixmap( _versatileview->_iconclosed );
119 }
120 }
121
122}
123
124void OVersatileViewItem::setRenameEnabled( bool allow )
125{
126 #if (QT_VERSION >= 0x030000)
127 OListViewItem::setRenameEnabled( 0, allow ); // TODO: Backport to Qt-Embedded 2.x?
128 #endif
129 QIconViewItem::setRenameEnabled( allow );
130}
131
132
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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#ifndef OVERSATILEVIEWITEM_H
33#define OVERSATILEVIEWITEM_H
34
35/* QT */
36
37#include <qiconview.h>
38
39/* OPIE */
40
41#include <opie2/olistview.h>
42
43class OVersatileView;
44
45class OVersatileViewItem : public OListViewItem, public QIconViewItem
46{
47 public:
48 OVersatileViewItem( OVersatileView * parent );
49
50 OVersatileViewItem( OVersatileView * parent, OVersatileViewItem * after );
51
52 OVersatileViewItem( OVersatileViewItem * parent, OVersatileViewItem * after );
53
54 OVersatileViewItem( OVersatileView * parent, QString,
55 QString = QString::null, QString = QString::null,
56 QString = QString::null, QString = QString::null,
57 QString = QString::null, QString = QString::null,
58 QString = QString::null );
59
60 OVersatileViewItem( OVersatileViewItem * parent, QString,
61 QString = QString::null, QString = QString::null,
62 QString = QString::null, QString = QString::null,
63 QString = QString::null, QString = QString::null,
64 QString = QString::null );
65
66 OVersatileViewItem( OVersatileView * parent, OVersatileViewItem * after, QString,
67 QString = QString::null, QString = QString::null,
68 QString = QString::null, QString = QString::null,
69 QString = QString::null, QString = QString::null,
70 QString = QString::null );
71
72 OVersatileViewItem( OVersatileViewItem * parent, OVersatileViewItem * after, QString,
73 QString = QString::null, QString = QString::null,
74 QString = QString::null, QString = QString::null,
75 QString = QString::null, QString = QString::null,
76 QString = QString::null );
77
78 virtual ~OVersatileViewItem();
79
80 OVersatileView* versatileView() const;
81
82 // TODO: Implement the remaining constructors from QIconView
83
84 /* OIconViewItem( QIconView *parent, const QString &text, const QPixmap &icon );
85 OIconViewItem( QIconView *parent, QIconViewItem *after, const QString &text, const QPixmap &icon );
86 */
87
88 virtual void setRenameEnabled( bool );
89
90 // TODO: Implement the remaining method multiplexers
91
92 private:
93 OVersatileView* _versatileview;
94
95 private:
96 void init();
97
98};
99
100#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 @@
1/* XPM */
2static char * view_icon_xpm[] = {
3"16 16 16 1",
4 " c None",
5 ".c #87BD88",
6 "+c #8BBE8B",
7 "@c #81BA81",
8 "#c #6DAF6D",
9 "$c #87BD87",
10 "%c #FCFDFC",
11 "&c #AED0AE",
12 "*c #4E9C4C",
13 "=c #91BD91",
14 "-c #72B172",
15 ";c #448643",
16 ">c #519F50",
17 ",c #499247",
18 "'c #356A35",
19 ")c #686868",
20" ",
21" .+@# .+@# ",
22" $%&* $%&* ",
23" @=-; @=-; ",
24" #>,' #>,' ",
25" ",
26" )))))) )))))) ",
27" ",
28" ",
29" .+@# .+@# ",
30" $%&* $%&* ",
31" @=-; @=-; ",
32" #>,' #>,' ",
33" ",
34" )))))) )))))) ",
35" "};
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 @@
1/* XPM */
2static char * view_tree_xpm[] = {
3"16 16 17 1",
4 " c None",
5 ".c #3A3A3A",
6 "+c #87BD88",
7 "@c #8BBE8B",
8 "#c #81BA81",
9 "$c #6DAF6D",
10 "%c #87BD87",
11 "&c #FCFDFC",
12 "*c #AED0AE",
13 "=c #4E9C4C",
14 "-c #91BD91",
15 ";c #72B172",
16 ">c #448643",
17 ",c #686868",
18 "'c #519F50",
19 ")c #499247",
20 "!c #356A35",
21" . ",
22" . ",
23" . +@#$ ",
24" . %&*= ",
25" .. #-;> ,, ,,,",
26" . $')! ",
27" . ",
28" . ",
29" . ",
30" . +@#$ ",
31" . %&*= ",
32" .. #-;> ,, ,,,",
33" $')! ",
34" ",
35" ",
36" "};
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 @@
1/*
2                 This file is part of the Opie Project
3 Originally part of the KDE Project
4 Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29*/
30
31#include <opie2/ocompletion.h>
32
33class OCompTreeNode;
34
35/**************************************************************************************************/
36/* OCompTreeNodeList
37/**************************************************************************************************/
38
39class OCompTreeNodeList
40{
41public:
42 OCompTreeNodeList() : first(0), last(0), m_count(0) {}
43 OCompTreeNode *begin() const { return first; }
44 OCompTreeNode *end() const { return last; }
45
46 OCompTreeNode *at(uint index) const;
47 void append(OCompTreeNode *item);
48 void prepend(OCompTreeNode *item);
49 void insert(OCompTreeNode *after, OCompTreeNode *item);
50 OCompTreeNode *remove(OCompTreeNode *item);
51 uint count() const { return m_count; }
52
53private:
54 OCompTreeNode *first, *last;
55 uint m_count;
56};
57
58typedef OCompTreeNodeList OCompTreeChildren;
59typedef OSortableValueList<QString> OCompletionMatchesList;
60
61/**
62 * A helper class for OCompletion. Implements a tree of QChar.
63 *
64 * The tree looks like this (containing the items "kde", "kde-ui",
65 * "kde-core" and "pfeiffer". Every item is delimited with QChar( 0x0 )
66 *
67 * some_root_node
68 * / \
69 * k p
70 * | |
71 * d f
72 * | |
73 * e e
74 * /| |
75 * 0x0 - i
76 * / \ |
77 * u c f
78 * | | |
79 * i o f
80 * | | |
81 * 0x0 r e
82 * | |
83 * e r
84 * | |
85 * 0x0 0x0
86 *
87 * @author Carsten Pfeiffer <pfeiffer@kde.org>
88 * @internal
89 */
90
91/**************************************************************************************************/
92/* OCompTreeNode
93/**************************************************************************************************/
94
95class OCompTreeNode : public QChar
96{
97public:
98 OCompTreeNode():QChar(), myWeight(0) {}
99 OCompTreeNode( const QChar& ch, uint weight = 0 ):QChar( ch ), myWeight( weight ) {}
100 ~OCompTreeNode();
101
102 // FIXME: Do we need this for Opie? [see also the static ZoneAllocater below]
103 //void * operator new( size_t s ) {
104 // return alloc.allocate( s );
105 //}
106 //void operator delete( void * s ) {
107 // alloc.deallocate( s );
108 //}
109
110 // Returns a child of this node matching ch, if available.
111 // Otherwise, returns 0L
112 inline OCompTreeNode * find( const QChar& ch ) const {
113 OCompTreeNode * cur = myChildren.begin();
114 while (cur && (*cur != ch)) cur = cur->next;
115 return cur;
116 }
117
118 OCompTreeNode * insert( const QChar&, bool sorted );
119 void remove( const QString& );
120
121 inline int childrenCount() const { return myChildren.count(); };
122
123 // weighting
124 inline void confirm() { myWeight++; };
125 inline void confirm(uint w) { myWeight += w; };
126 inline void decline() { myWeight--; };
127 inline uint weight() const { return myWeight; };
128
129 inline const OCompTreeChildren * children() const { return &myChildren; };
130 inline const OCompTreeNode * childAt(int index) const { return myChildren.at(index); };
131 inline const OCompTreeNode * firstChild() const { return myChildren.begin(); };
132 inline const OCompTreeNode * lastChild() const { return myChildren.end(); };
133
134 /* We want to handle a list of OCompTreeNodes on our own, to not
135 need to use QValueList<>. And to make it even more fast we don't
136 use an accessor, but just a public member. */
137 OCompTreeNode *next;
138
139private:
140 uint myWeight;
141 OCompTreeNodeListmyChildren;
142 //static OZoneAllocator alloc; // FIXME: Do we need this for Opie?
143};
144
145/**************************************************************************************************/
146/* OCompletionMatchesWrapper
147/**************************************************************************************************/
148
149class OCompletionMatchesWrapper
150{
151public:
152 OCompletionMatchesWrapper( bool sort = false )
153 : sortedList( sort ? new OCompletionMatchesList : 0L ),
154 dirty( false )
155 {}
156 ~OCompletionMatchesWrapper() {
157 delete sortedList;
158 }
159
160 void setSorting( bool sort ) {
161 if ( sort && !sortedList )
162 sortedList = new OCompletionMatchesList;
163 else if ( !sort ) {
164 delete sortedList;
165 sortedList = 0L;
166 }
167 stringList.clear();
168 dirty = false;
169 }
170
171 bool sorting() const {
172 return sortedList != 0L;
173 }
174
175 void append( int i, const QString& string ) {
176 if ( sortedList )
177 sortedList->insert( i, string );
178 else
179 stringList.append( string );
180 dirty = true;
181 }
182
183 void clear() {
184 if ( sortedList )
185 sortedList->clear();
186 stringList.clear();
187 dirty = false;
188 }
189
190 uint count() const {
191 if ( sortedList )
192 return sortedList->count();
193 return stringList.count();
194 }
195
196 bool isEmpty() const {
197 return count() == 0;
198 }
199
200 QString first() const {
201 return list().first();
202 }
203
204 QString last() const {
205 return list().last();
206 }
207
208 QStringList list() const;
209
210 mutable QStringList stringList;
211 OCompletionMatchesList *sortedList;
212 mutable bool dirty;
213};
214
215/**************************************************************************************************/
216/* OCompletionPrivate
217/**************************************************************************************************/
218
219class OCompletionPrivate
220{
221public:
222 // not a member to avoid #including kcompletion_private.h from kcompletion.h
223 // list used for nextMatch() and previousMatch()
224 OCompletionMatchesWrapper matches;
225};
226
227/**************************************************************************************************/
228/* OCompletion
229/**************************************************************************************************/
230
231OCompletion::OCompletion()
232{
233 d = new OCompletionPrivate;
234
235 myCompletionMode = OGlobalSettings::completionMode();
236 myTreeRoot = new OCompTreeNode;
237 myBeep = true;
238 myIgnoreCase = false;
239 myHasMultipleMatches = false;
240 myRotationIndex = 0;
241 setOrder( Insertion );
242}
243
244
245OCompletion::~OCompletion()
246{
247 delete d;
248 delete myTreeRoot;
249}
250
251
252void OCompletion::setOrder( CompOrder order )
253{
254 myOrder = order;
255 d->matches.setSorting( order == Weighted );
256}
257
258
259void OCompletion::setIgnoreCase( bool ignoreCase )
260{
261 myIgnoreCase = ignoreCase;
262}
263
264
265void OCompletion::setItems( const QStringList& items )
266{
267 clear();
268 insertItems( items );
269}
270
271
272void OCompletion::insertItems( const QStringList& items )
273{
274 bool weighted = (myOrder == Weighted);
275 QStringList::ConstIterator it;
276 if ( weighted ) { // determine weight
277 for ( it = items.begin(); it != items.end(); ++it ) addWeightedItem( *it );
278 }
279 else {
280 for ( it = items.begin(); it != items.end(); ++it ) addItem( *it, 0 );
281 }
282}
283
284
285QStringList OCompletion::items() const
286{
287 OCompletionMatchesWrapper list; // unsorted
288 bool addWeight = (myOrder == Weighted);
289 extractStringsFromNode( myTreeRoot, QString::null, &list, addWeight );
290
291 return list.list();
292}
293
294
295void OCompletion::addItem( const QString& item )
296{
297 d->matches.clear();
298 myRotationIndex = 0;
299 myLastString = QString::null;
300
301 addItem( item, 0 );
302}
303
304
305void OCompletion::addItem( const QString& item, uint weight )
306{
307 if ( item.isEmpty() ) return;
308
309 OCompTreeNode *node = myTreeRoot;
310 uint len = item.length();
311
312 bool sorted = (myOrder == Sorted);
313 bool weighted = ((myOrder == Weighted) && weight > 1);
314
315 // knowing the weight of an item, we simply add this weight to all of its
316 // nodes.
317
318 for ( uint i = 0; i < len; i++ ) {
319 node = node->insert( item.at(i), sorted );
320 if ( weighted ) node->confirm( weight -1 ); // node->insert() sets weighting to 1
321 }
322
323 // add 0x0-item as delimiter with evtl. weight
324 node = node->insert( 0x0, true );
325 if ( weighted )
326 node->confirm( weight -1 );
327 //qDebug( "OCompletion: added: %s (%i)", item.latin1(), node->weight());
328}
329
330
331void OCompletion::addWeightedItem( const QString& item )
332{
333 if ( myOrder != Weighted ) {
334 addItem( item, 0 );
335 return;
336 }
337
338 uint len = item.length();
339 uint weight = 0;
340
341 // find out the weighting of this item (appended to the string as ":num")
342 int index = item.findRev(':');
343 if ( index > 0 ) {
344 bool ok;
345 weight = item.mid( index + 1 ).toUInt( &ok );
346 if ( !ok )
347 weight = 0;
348
349 len = index; // only insert until the ':'
350 }
351
352 addItem( item.left( len ), weight );
353 return;
354}
355
356
357void OCompletion::removeItem( const QString& item )
358{
359 d->matches.clear();
360 myRotationIndex = 0;
361 myLastString = QString::null;
362
363 myTreeRoot->remove( item );
364}
365
366
367void OCompletion::clear()
368{
369 d->matches.clear();
370 myRotationIndex = 0;
371 myLastString = QString::null;
372
373 delete myTreeRoot;
374 myTreeRoot = new OCompTreeNode;
375}
376
377
378QString OCompletion::makeCompletion( const QString& string )
379{
380 if ( myCompletionMode == OGlobalSettings::CompletionNone )
381 return QString::null;
382
383 //qDebug( "OCompletion: completing: %s", string );
384
385 d->matches.clear();
386 myRotationIndex = 0;
387 myHasMultipleMatches = false;
388 myLastMatch = myCurrentMatch;
389
390 // in Shell-completion-mode, emit all matches when we get the same
391 // complete-string twice
392 if ( myCompletionMode == OGlobalSettings::CompletionShell &&
393 string == myLastString ) {
394 // Don't use d->matches since calling postProcessMatches()
395 // on d->matches here would interfere with call to
396 // postProcessMatch() during rotation
397
398 findAllCompletions( string, &d->matches, myHasMultipleMatches );
399 QStringList l = d->matches.list();
400 postProcessMatches( &l );
401 emit matches( l );
402
403 if ( l.isEmpty() )
404 doBeep( NoMatch );
405
406 return QString::null;
407 }
408
409 QString completion;
410 // in case-insensitive popup mode, we search all completions at once
411 if ( myCompletionMode == OGlobalSettings::CompletionPopup ||
412 myCompletionMode == OGlobalSettings::CompletionPopupAuto ) {
413 findAllCompletions( string, &d->matches, myHasMultipleMatches );
414 if ( !d->matches.isEmpty() )
415 completion = d->matches.first();
416 }
417 else
418 completion = findCompletion( string );
419
420 if ( myHasMultipleMatches )
421 emit multipleMatches();
422
423 myLastString = string;
424 myCurrentMatch = completion;
425
426 postProcessMatch( &completion );
427
428 if ( !string.isEmpty() ) { // only emit match when string != ""
429 //qDebug( "OCompletion: Match: %s", completion );
430 emit match( completion );
431 }
432
433 if ( completion.isNull() )
434 doBeep( NoMatch );
435
436 return completion;
437}
438
439QStringList OCompletion::substringCompletion( const QString& string ) const
440{
441 // get all items in the tree, eventually in sorted order
442 bool sorted = (myOrder == Weighted);
443 OCompletionMatchesWrapper allItems( sorted );
444 extractStringsFromNode( myTreeRoot, QString::null, &allItems, false );
445
446 QStringList list = allItems.list();
447
448 // subStringMatches is invoked manually, via a shortcut, so we should
449 // beep here, if necessary.
450 if ( list.isEmpty() ) {
451 doBeep( NoMatch );
452 return list;
453 }
454
455 if ( string.isEmpty() ) { // shortcut
456 postProcessMatches( &list );
457 return list;
458 }
459
460 QStringList matches;
461 QStringList::ConstIterator it = list.begin();
462
463 for( ; it != list.end(); ++it ) {
464 QString item = *it;
465 if ( item.find( string, 0, false ) != -1 ) { // always case insensitive
466 postProcessMatch( &item );
467 matches.append( item );
468 }
469 }
470
471 if ( matches.isEmpty() )
472 doBeep( NoMatch );
473
474 return matches;
475}
476
477
478void OCompletion::setCompletionMode( OGlobalSettings::Completion mode )
479{
480 myCompletionMode = mode;
481}
482
483
484QStringList OCompletion::allMatches()
485{
486 // Don't use d->matches since calling postProcessMatches()
487 // on d->matches here would interfere with call to
488 // postProcessMatch() during rotation
489 OCompletionMatchesWrapper matches( myOrder == Weighted );
490 bool dummy;
491 findAllCompletions( myLastString, &matches, dummy );
492 QStringList l = matches.list();
493 postProcessMatches( &l );
494 return l;
495}
496
497
498OCompletionMatches OCompletion::allWeightedMatches()
499{
500 // Don't use d->matches since calling postProcessMatches()
501 // on d->matches here would interfere with call to
502 // postProcessMatch() during rotation
503 OCompletionMatchesWrapper matches( myOrder == Weighted );
504 bool dummy;
505 findAllCompletions( myLastString, &matches, dummy );
506 OCompletionMatches ret( matches );
507 postProcessMatches( &ret );
508 return ret;
509}
510
511QStringList OCompletion::allMatches( const QString &string )
512{
513 OCompletionMatchesWrapper matches( myOrder == Weighted );
514 bool dummy;
515 findAllCompletions( string, &matches, dummy );
516 QStringList l = matches.list();
517 postProcessMatches( &l );
518 return l;
519}
520
521OCompletionMatches OCompletion::allWeightedMatches( const QString &string )
522{
523 OCompletionMatchesWrapper matches( myOrder == Weighted );
524 bool dummy;
525 findAllCompletions( string, &matches, dummy );
526 OCompletionMatches ret( matches );
527 postProcessMatches( &ret );
528 return ret;
529}
530
531/////////////////////////////////////////////////////
532///////////////// tree operations ///////////////////
533
534
535QString OCompletion::nextMatch()
536{
537 QString completion;
538 myLastMatch = myCurrentMatch;
539
540 if ( d->matches.isEmpty() ) {
541 findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
542 completion = d->matches.first();
543 myCurrentMatch = completion;
544 myRotationIndex = 0;
545 postProcessMatch( &completion );
546 emit match( completion );
547 return completion;
548 }
549
550 QStringList matches = d->matches.list();
551 myLastMatch = matches[ myRotationIndex++ ];
552
553 if ( myRotationIndex == matches.count() -1 )
554 doBeep( Rotation ); // indicate last matching item -> rotating
555
556 else if ( myRotationIndex == matches.count() )
557 myRotationIndex = 0;
558
559 completion = matches[ myRotationIndex ];
560 myCurrentMatch = completion;
561 postProcessMatch( &completion );
562 emit match( completion );
563 return completion;
564}
565
566
567
568QString OCompletion::previousMatch()
569{
570 QString completion;
571 myLastMatch = myCurrentMatch;
572
573 if ( d->matches.isEmpty() ) {
574 findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
575 completion = d->matches.last();
576 myCurrentMatch = completion;
577 myRotationIndex = 0;
578 postProcessMatch( &completion );
579 emit match( completion );
580 return completion;
581 }
582
583 QStringList matches = d->matches.list();
584 myLastMatch = matches[ myRotationIndex ];
585 if ( myRotationIndex == 1 )
586 doBeep( Rotation ); // indicate first item -> rotating
587
588 else if ( myRotationIndex == 0 )
589 myRotationIndex = matches.count();
590
591 myRotationIndex--;
592
593 completion = matches[ myRotationIndex ];
594 myCurrentMatch = completion;
595 postProcessMatch( &completion );
596 emit match( completion );
597 return completion;
598}
599
600
601
602// tries to complete "string" from the tree-root
603QString OCompletion::findCompletion( const QString& string )
604{
605 QChar ch;
606 QString completion;
607 const OCompTreeNode *node = myTreeRoot;
608
609 // start at the tree-root and try to find the search-string
610 for( uint i = 0; i < string.length(); i++ ) {
611 ch = string.at( i );
612 node = node->find( ch );
613
614 if ( node )
615 completion += ch;
616 else
617 return QString::null; // no completion
618 }
619
620 // Now we have the last node of the to be completed string.
621 // Follow it as long as it has exactly one child (= longest possible
622 // completion)
623
624 while ( node->childrenCount() == 1 ) {
625 node = node->firstChild();
626 if ( !node->isNull() )
627 completion += *node;
628 }
629 // if multiple matches and auto-completion mode
630 // -> find the first complete match
631 if ( node && node->childrenCount() > 1 ) {
632 myHasMultipleMatches = true;
633
634 if ( myCompletionMode == OGlobalSettings::CompletionAuto ) {
635 myRotationIndex = 1;
636 if (myOrder != Weighted) {
637 while ( (node = node->firstChild()) ) {
638 if ( !node->isNull() )
639 completion += *node;
640 else
641 break;
642 }
643 }
644 else {
645 // don't just find the "first" match, but the one with the
646 // highest priority
647
648 const OCompTreeNode* temp_node = 0L;
649 while(1) {
650 int count = node->childrenCount();
651 temp_node = node->firstChild();
652 uint weight = temp_node->weight();
653 const OCompTreeNode* hit = temp_node;
654 for( int i = 1; i < count; i++ ) {
655 temp_node = node->childAt(i);
656 if( temp_node->weight() > weight ) {
657 hit = temp_node;
658 weight = hit->weight();
659 }
660 }
661 // 0x0 has the highest priority -> we have the best match
662 if ( hit->isNull() )
663 break;
664
665 node = hit;
666 completion += *node;
667 }
668 }
669 }
670
671 else
672 doBeep( PartialMatch ); // partial match -> beep
673 }
674
675 return completion;
676}
677
678
679void OCompletion::findAllCompletions(const QString& string,
680 OCompletionMatchesWrapper *matches,
681 bool& hasMultipleMatches) const
682{
683 //qDebug( "OCompletion: finding all completions for %s", (const char*) string );
684
685 if ( string.isEmpty() )
686 return;
687
688 if ( myIgnoreCase ) { // case insensitive completion
689 extractStringsFromNodeCI( myTreeRoot, QString::null, string, matches );
690 hasMultipleMatches = (matches->count() > 1);
691 return;
692 }
693
694 QChar ch;
695 QString completion;
696 const OCompTreeNode *node = myTreeRoot;
697
698 // start at the tree-root and try to find the search-string
699 for( uint i = 0; i < string.length(); i++ ) {
700 ch = string.at( i );
701 node = node->find( ch );
702
703 if ( node )
704 completion += ch;
705 else
706 return; // no completion -> return empty list
707 }
708
709 // Now we have the last node of the to be completed string.
710 // Follow it as long as it has exactly one child (= longest possible
711 // completion)
712
713 while ( node->childrenCount() == 1 ) {
714 node = node->firstChild();
715 if ( !node->isNull() )
716 completion += *node;
717 // kdDebug() << completion << node->latin1();
718 }
719
720
721 // there is just one single match)
722 if ( node->childrenCount() == 0 )
723 matches->append( node->weight(), completion );
724
725 else {
726 // node has more than one child
727 // -> recursively find all remaining completions
728 hasMultipleMatches = true;
729 extractStringsFromNode( node, completion, matches );
730 }
731}
732
733
734void OCompletion::extractStringsFromNode( const OCompTreeNode *node,
735 const QString& beginning,
736 OCompletionMatchesWrapper *matches,
737 bool addWeight ) const
738{
739 if ( !node || !matches ) return;
740
741 // kDebug() << "Beginning: " << beginning << endl;
742 const OCompTreeChildren *list = node->children();
743 QString string;
744 QString w;
745
746 // loop thru all children
747 for ( OCompTreeNode *cur = list->begin(); cur ; cur = cur->next) {
748 string = beginning;
749 node = cur;
750 if ( !node->isNull() )
751 string += *node;
752
753 while ( node && node->childrenCount() == 1 ) {
754 node = node->firstChild();
755 if ( node->isNull() ) break;
756 string += *node;
757 }
758
759 if ( node && node->isNull() ) { // we found a leaf
760 if ( addWeight ) {
761 // add ":num" to the string to store the weighting
762 string += ':';
763 w.setNum( node->weight() );
764 string.append( w );
765 }
766 matches->append( node->weight(), string );
767 }
768
769 // recursively find all other strings.
770 if ( node && node->childrenCount() > 1 )
771 extractStringsFromNode( node, string, matches, addWeight );
772 }
773}
774
775void OCompletion::extractStringsFromNodeCI( const OCompTreeNode *node,
776 const QString& beginning,
777 const QString& restString,
778 OCompletionMatchesWrapper *matches ) const
779{
780 if ( restString.isEmpty() ) {
781 extractStringsFromNode( node, beginning, matches, false /*noweight*/ );
782 return;
783 }
784
785 QChar ch1 = restString.at(0);
786 QString newRest = restString.mid(1);
787 OCompTreeNode *child1, *child2;
788
789 child1 = node->find( ch1 ); // the correct match
790 if ( child1 )
791 extractStringsFromNodeCI( child1, beginning + *child1, newRest,
792 matches );
793
794 // append the case insensitive matches, if available
795 if ( ch1.isLetter() ) {
796 // find out if we have to lower or upper it. Is there a better way?
797 QChar ch2 = ch1.lower();
798 if ( ch1 == ch2 )
799 ch2 = ch1.upper();
800 if ( ch1 != ch2 ) {
801 child2 = node->find( ch2 );
802 if ( child2 )
803 extractStringsFromNodeCI( child2, beginning + *child2, newRest,
804 matches );
805 }
806 }
807}
808
809// FIXME: Revise this for Opie?
810
811void OCompletion::doBeep( BeepMode mode ) const
812{
813 if ( !myBeep ) return;
814
815 QString text, event;
816
817 switch ( mode ) {
818 case Rotation:
819 event = QString::fromLatin1("Textcompletion: rotation");
820 text = tr("You reached the end of the list\nof matching items.\n");
821 break;
822 case PartialMatch:
823 if ( myCompletionMode == OGlobalSettings::CompletionShell ||
824 myCompletionMode == OGlobalSettings::CompletionMan ) {
825 event = QString::fromLatin1("Textcompletion: partial match");
826 text = tr("The completion is ambiguous, more than one\nmatch is available.\n");
827 }
828 break;
829 case NoMatch:
830 if ( myCompletionMode == OGlobalSettings::CompletionShell ) {
831 event = QString::fromLatin1("Textcompletion: no match");
832 text = tr("There is no matching item available.\n");
833 }
834 break;
835 }
836
837 //if ( !text.isEmpty() )
838 //ONotifyClient::event( event, text ); // FIXME: Revise for Opie?
839}
840
841// Implements the tree. Every node is a QChar and has a list of children, which
842// are Nodes as well.
843// QChar( 0x0 ) is used as the delimiter of a string; the last child of each
844// inserted string is 0x0.
845
846OCompTreeNode::~OCompTreeNode()
847{
848 // delete all children
849 OCompTreeNode *cur = myChildren.begin();
850 while (cur) {
851 OCompTreeNode * next = cur->next;
852 delete myChildren.remove(cur);
853 cur = next;
854 }
855}
856
857
858// Adds a child-node "ch" to this node. If such a node is already existant,
859// it will not be created. Returns the new/existing node.
860OCompTreeNode * OCompTreeNode::insert( const QChar& ch, bool sorted )
861{
862 OCompTreeNode *child = find( ch );
863 if ( !child ) {
864 child = new OCompTreeNode( ch );
865
866 // FIXME, first (slow) sorted insertion implementation
867 if ( sorted ) {
868 OCompTreeNode * prev = 0;
869 OCompTreeNode * cur = myChildren.begin();
870 while ( cur ) {
871 if ( ch > *cur ) {
872 prev = cur;
873 cur = cur->next;
874 } else
875 break;
876 }
877 if (prev)
878 myChildren.insert( prev, child );
879 else
880 myChildren.prepend(child);
881 }
882
883 else
884 myChildren.append( child );
885 }
886
887 // implicit weighting: the more often an item is inserted, the higher
888 // priority it gets.
889 child->confirm();
890
891 return child;
892}
893
894
895// Recursively removes a string from the tree (untested :-)
896void OCompTreeNode::remove( const QString& string )
897{
898 OCompTreeNode *child = 0L;
899
900 if ( string.isEmpty() ) {
901 child = find( 0x0 );
902 delete myChildren.remove( child );
903 return;
904 }
905
906 QChar ch = string.at(0);
907 child = find( ch );
908 if ( child ) {
909 child->remove( string.right( string.length() -1 ) );
910 if ( child->myChildren.count() == 0 ) {
911 delete myChildren.remove( child );
912 }
913 }
914}
915
916QStringList OCompletionMatchesWrapper::list() const {
917 if ( sortedList && dirty ) {
918 sortedList->sort();
919 dirty = false;
920
921 stringList.clear();
922
923 // high weight == sorted last -> reverse the sorting here
924 QValueListConstIterator<OSortableItem<QString> > it;
925 for ( it = sortedList->begin(); it != sortedList->end(); ++it )
926 stringList.prepend( (*it).value() );
927 }
928
929 return stringList;
930}
931
932OCompletionMatches::OCompletionMatches( bool sort_P )
933 : _sorting( sort_P )
934{
935}
936
937OCompletionMatches::OCompletionMatches( const OCompletionMatchesWrapper& matches )
938 : _sorting( matches.sorting())
939{
940 if( matches.sortedList != 0L )
941 OCompletionMatchesList::operator=( *matches.sortedList );
942 else {
943 QStringList l = matches.list();
944 for( QStringList::ConstIterator it = l.begin();
945 it != l.end();
946 ++it )
947 prepend( OSortableItem<QString, int>( 1, *it ) );
948 }
949}
950
951OCompletionMatches::~OCompletionMatches()
952{
953}
954
955QStringList OCompletionMatches::list( bool sort_P ) const
956{
957 if( _sorting && sort_P )
958 const_cast< OCompletionMatches* >( this )->sort();
959 QStringList stringList;
960 // high weight == sorted last -> reverse the sorting here
961 for ( ConstIterator it = begin(); it != end(); ++it )
962 stringList.prepend( (*it).value() );
963 return stringList;
964}
965
966void OCompletionMatches::removeDuplicates()
967{
968 Iterator it1, it2;
969 for ( it1 = begin(); it1 != end(); ++it1 ) {
970 for ( (it2 = it1), ++it2; it2 != end();) {
971 if( (*it1).value() == (*it2).value()) {
972 // use the max height
973 //(*it1).first = kMax( (*it1).index(), (*it2).index());
974 (*it1).first = (*it2).index() < (*it1).index() ? (*it1).index() : (*it2).index();
975 it2 = remove( it2 );
976 continue;
977 }
978 ++it2;
979 }
980 }
981}
982
983void OCompTreeNodeList::append(OCompTreeNode *item)
984{
985 m_count++;
986 if (!last) {
987 last = item;
988 last->next = 0;
989 first = item;
990 return;
991 }
992 last->next = item;
993 item->next = 0;
994 last = item;
995}
996
997void OCompTreeNodeList::prepend(OCompTreeNode *item)
998{
999 m_count++;
1000 if (!last) {
1001 last = item;
1002 last->next = 0;
1003 first = item;
1004 return;
1005 }
1006 item->next = first;
1007 first = item;
1008}
1009
1010void OCompTreeNodeList::insert(OCompTreeNode *after, OCompTreeNode *item)
1011{
1012 if (!after) {
1013 append(item);
1014 return;
1015 }
1016
1017 m_count++;
1018
1019 item->next = after->next;
1020 after->next = item;
1021
1022 if (after == last)
1023 last = item;
1024}
1025
1026OCompTreeNode *OCompTreeNodeList::remove(OCompTreeNode *item)
1027{
1028 if (!first || !item)
1029 return 0;
1030 OCompTreeNode *cur = 0;
1031
1032 if (item == first)
1033 first = first->next;
1034 else {
1035 cur = first;
1036 while (cur && cur->next != item) cur = cur->next;
1037 if (!cur)
1038 return 0;
1039 cur->next = item->next;
1040 }
1041 if (item == last)
1042 last = cur;
1043 m_count--;
1044 return item;
1045}
1046
1047OCompTreeNode *OCompTreeNodeList::at(uint index) const
1048{
1049 OCompTreeNode *cur = first;
1050 while (index-- && cur) cur = cur->next;
1051 return cur;
1052}
1053
1054// FIXME: Revise for Opie?
1055//OZoneAllocator OCompTreeNode::alloc(8192);
1056
1057//void OCompletion::virtual_hook( int, void* )
1058//{ /*BASE::virtual_hook( id, data );*/ }
1059
1060//void OCompletionBase::virtual_hook( int, void* )
1061//{ /*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 @@
1/*
2                 This file is part of the Opie Project
3 Originally part of the KDE Project
4 Copyright (C) 1999,2000 Carsten Pfeiffer <pfeiffer@kde.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29*/
30
31#ifndef OCOMPLETION_H
32#define OCOMPLETION_H
33
34/* QT */
35
36#include <qmap.h>
37#include <qlist.h>
38#include <qobject.h>
39#include <qstring.h>
40#include <qstringlist.h>
41#include <qguardedptr.h>
42
43/* OPIE */
44
45#include <opie2/oglobalsettings.h>
46#include <opie2/osortablevaluelist.h>
47
48/* FORWARDS */
49
50class OCompTreeNode;
51class OCompletionPrivate;
52class OCompletionBasePrivate;
53class OCompletionMatchesWrapper;
54class OCompletionMatches;
55class QPopupMenu;
56
57// FIXME: Do we need special ShortCut handling in Opie? If so, revise this.
58class OShortcut
59{
60public:
61 bool isNull() const { return true; };
62 bool operator == ( const OShortcut& bla ) const { return false; };
63};
64
65
66/**
67 * This class offers easy use of "auto-completion", "manual-completion" or
68 * "shell completion" on QString objects. A common use is completing filenames
69 * or URLs (see @ref OURLCompletion()).
70 * But it is not limited to URL-completion -- everything should be completable!
71 * The user should be able to complete email-addresses, telephone-numbers,
72 * commands, SQL queries, ...
73 * Every time your program knows what the user can type into an edit-field, you
74 * should offer completion. With OCompletion, this is very easy, and if you are
75 * using a line edit widget (@ref OLineEdit), it is even more easy.
76 * Basically, you tell a OCompletion object what strings should be completable
77 * and whenever completion should be invoked, you call @ref makeCompletion().
78 * OLineEdit and (an editable) OComboBox even do this automatically for you.
79 *
80 * OCompletion offers the completed string via the signal @ref match() and
81 * all matching strings (when the result is ambiguous) via the method
82 * @ref allMatches().
83 *
84 * Notice: auto-completion, shell completion and manual completion work
85 * slightly differently:
86 *
87 * @li auto-completion always returns a complete item as match.
88 * When more than one matching items are available, it will deliver just
89 * the first (depending on sorting order) item. Iterating over all matches
90 * is possible via @ref nextMatch() and @ref previousMatch().
91 *
92 * @li popup-completion works in the same way, the only difference being that
93 * the completed items are not put into the edit-widget, but into a
94 * separate popup-box.
95 *
96 * @li manual completion works the same way as auto-completion, the
97 * subtle difference is, that it isn't invoked automatically while the user
98 * is typing, but only when the user presses a special key. The difference
99 * of manual and auto-completion is therefore only visible in UI classes,
100 * OCompletion needs to know whether to deliver partial matches
101 * (shell completion) or whole matches (auto/manual completion), therefore
102 * @ref OGlobalSettings::CompletionMan and
103 * @ref OGlobalSettings::CompletionAuto have the exact same effect in
104 * OCompletion.
105 *
106 * @li shell completion works like how shells complete filenames:
107 * when multiple matches are available, the longest possible string of all
108 * matches is returned (i.e. only a partial item).
109 * Iterating over all matching items (complete, not partial) is possible
110 * via @ref nextMatch() and @ref previousMatch().
111 *
112 * You don't have to worry much about that though, OCompletion handles
113 * that for you, according to the setting @ref setCompletionMode().
114 * The default setting is globally configured by the user and read
115 * from @ref OGlobalSettings::completionMode().
116 *
117 * A short example:
118 * <pre>
119 * OCompletion completion;
120 * completion.setOrder( OCompletion::Sorted );
121 * completion.addItem( "pfeiffer@kde.org" );
122 * completion.addItem( "coolo@kde.org" );
123 * completion.addItem( "carpdjih@sp.zrz.tu-berlin.de" );
124 * completion.addItem( "carp@cs.tu-berlin.de" );
125 *
126 * cout << completion.makeCompletion( "ca" ).latin1() << endl;
127 * </pre>
128 * In shell-completion-mode, this will be "carp"; in auto-completion-
129 * mode it will be "carp@cs.tu-berlin.de", as that is alphabetically
130 * smaller.
131 * If setOrder was set to Insertion, "carpdjih@sp.zrz.tu-berlin.de"
132 * would be completed in auto-completion-mode, as that was inserted before
133 * "carp@cs.tu-berlin.de".
134 *
135 * You can dynamically update the completable items by removing and adding them
136 * whenever you want.
137 * For advanced usage, you could even use multiple OCompletion objects. E.g.
138 * imagine an editor like kwrite with multiple open files. You could store
139 * items of each file in a different OCompletion object, so that you know (and
140 * tell the user) where a completion comes from.
141 *
142 * Note: OCompletion does not work with strings that contain 0x0 characters
143 * (unicode nul), as this is used internally as a delimiter.
144 *
145 * You may inherit from OCompletion and override @ref makeCompletion() in
146 * special cases (like reading directories/urls and then supplying the
147 * contents to OCompletion, as OURLCompletion does), but generally, this is
148 * not necessary.
149 *
150 *
151 * @short A generic class for completing QStrings
152 * @author Carsten Pfeiffer <pfeiffer@kde.org>
153 * @version $Id$
154 */
155
156class OCompletion : public QObject
157{
158 Q_ENUMS( CompOrder )
159 Q_PROPERTY( CompOrder order READ order WRITE setOrder )
160 Q_PROPERTY( bool ignoreCase READ ignoreCase WRITE setIgnoreCase )
161 Q_PROPERTY( QStringList items READ items WRITE setItems )
162 Q_OBJECT
163
164 public:
165 /**
166 * Constants that represent the order in which OCompletion performs
167 * completion-lookups.
168 */
169 enum CompOrder { Sorted, Insertion, Weighted };
170
171 /**
172 * Constructor, nothing special here :)
173 */
174 OCompletion();
175
176 // FIXME: copy constructor, assignment constructor...
177
178 /**
179 * Destructor, nothing special here, either.
180 */
181 virtual ~OCompletion();
182
183 /**
184 * Attempts to find an item in the list of available completions,
185 * that begins with @p string. Will either return the first matching item
186 * (if there is more than one match) or QString::null, if no match was
187 * found.
188 *
189 * In the latter case, a sound will be issued, depending on
190 * @ref isSoundsEnabled().
191 * If a match was found, it will also be emitted via the signal
192 * @ref match().
193 *
194 * If this is called twice or more often with the same string while no
195 * items were added or removed in the meantime, all available completions
196 * will be emitted via the signal @ref matches().
197 * This happens only in shell-completion-mode.
198 *
199 * @returns the matching item, or QString::null if there is no matching
200 * item.
201 * @see #slotMakeCompletion
202 * @see #substringCompletion
203 */
204 virtual QString makeCompletion( const QString& string );
205
206 /**
207 * @returns a list of items which all contain @p text as a substring,
208 * i.e. not necessarily at the beginning.
209 *
210 * @see #makeCompletion
211 */
212 QStringList substringCompletion( const QString& string ) const;
213
214 /**
215 * @returns the next item from the matching-items-list.
216 * When reaching the beginning, the list is rotated so it will return the
217 * last match and a sound is issued (depending on @ref isSoundsEnabled()).
218 * When there is no match, QString::null is returned and
219 * a sound is be issued.
220 * @see #slotPreviousMatch
221 */
222 QString previousMatch();
223
224 /**
225 * @returns the previous item from the matching-items-list
226 * When reaching the last item, the list is rotated, so it will return
227 * the first match and a sound is issued (depending on
228 * @ref isSoundsEnabled()). When there is no match, QString::null is
229 * returned and a sound is issued.
230 * @see #slotNextMatch
231 */
232 QString nextMatch();
233
234 /**
235 * @returns the last match. Might be useful if you need to check whether
236 * a completion is different from the last one.
237 * QString::null is returned when there is no last match.
238 */
239 virtual const QString& lastMatch() const { return myLastMatch; }
240
241 /**
242 * Returns a list of all items inserted into OCompletion. This is useful
243 * if you need to save the state of a OCompletion object and restore it
244 * later.
245 *
246 * Important note: when @ref order() == Weighted, then every item in the
247 * stringlist has its weight appended, delimited by a colon. E.g. an item
248 * "www.kde.org" might look like "www.kde.org:4", where 4 is the weight.
249 *
250 * This is necessary so that you can save the items along with its
251 * weighting on disk and load them back with @ref setItems(), restoring its
252 * weight as well. If you really don't want the appended weightings, call
253 * @ref setOrder( OCompletion::Insertion )
254 * before calling items().
255 *
256 * @returns a list of all items
257 * @see #setItems
258 */
259 QStringList items() const;
260
261 /**
262 * Sets the completion mode to Auto/Manual, Shell or None.
263 * If you don't set the mode explicitly, the global default value
264 * OGlobalSettings::completionMode() is used.
265 * @ref OGlobalSettings::CompletionNone disables completion.
266 * @see #completionMode
267 * @see #OGlobalSettings::completionMode
268 */
269 virtual void setCompletionMode( OGlobalSettings::Completion mode );
270
271 /**
272 * @returns the current completion mode.
273 * May be different from @ref OGlobalSettings::completionMode(), if you
274 * explicitly called @ref setCompletionMode().
275 * @see #setCompletionMode
276 */
277 OGlobalSettings::Completion completionMode() const { return myCompletionMode; };
278
279 /**
280 * OCompletion offers three different ways in which it offers its items:
281 * @li in the order of insertion
282 * @li sorted alphabetically
283 * @li weighted
284 *
285 * Choosing weighted makes OCompletion perform an implicit weighting based
286 * on how often an item is inserted. Imagine a web browser with a location
287 * bar, where the user enters URLs. The more often a URL is entered, the
288 * higher priority it gets.
289 *
290 * Note: Setting the order to sorted only affects new inserted items,
291 * already existing items will stay in the current order. So you probably
292 * want to call setOrder( Sorted ) before inserting items, when you want
293 * everything sorted.
294 *
295 * Default is insertion order
296 * @see #order
297 */
298 virtual void setOrder( CompOrder order );
299
300 /**
301 * @returns the current completion order.
302 * @see #setOrder
303 */
304 CompOrder order() const { return myOrder; }
305
306 /**
307 * Setting this to true makes OCompletion behave case insensitively.
308 * E.g. makeCompletion( "CA" ); might return "carp@cs.tu-berlin.de".
309 * Default is false (case sensitive).
310 * @see #ignoreCase
311 */
312 virtual void setIgnoreCase( bool ignoreCase );
313
314 /**
315 * @returns whether OCompletion acts case insensitively or not.
316 * Default is false (case sensitive).
317 * @see #setIgnoreCase
318 */
319 bool ignoreCase() const { return myIgnoreCase; };
320
321 /**
322 * @returns a list of all items matching the last completed string.
323 * Might take some time, when you have LOTS of items.
324 *
325 * @see #substringCompletion
326 */
327 QStringList allMatches();
328
329 /**
330 * @returns a list of all items matching @p string.
331 */
332 QStringList allMatches( const QString& string );
333
334 /**
335 * @returns a list of all items matching the last completed string.
336 * Might take some time, when you have LOTS of items.
337 * The matches are returned as OCompletionMatches, which also
338 * keeps the weight of the matches, allowing
339 * you to modify some matches or merge them with matches
340 * from another call to allWeightedMatches(), and sort the matches
341 * after that in order to have the matches ordered correctly
342 *
343 * @see #substringCompletion
344 */
345 OCompletionMatches allWeightedMatches();
346
347 /**
348 * @returns a list of all items matching @p string.
349 */
350 OCompletionMatches allWeightedMatches( const QString& string );
351
352 /**
353 * Enables/disables playing a sound when
354 * @li @ref makeCompletion() can't find a match
355 * @li there is a partial completion (= multiple matches in
356 * Shell-completion mode)
357 * @li @ref nextMatch() or @ref previousMatch() hit the last possible
358 * match -> rotation
359 *
360 * For playing the sounds, @ref ONotifyClient() is used. // FIXME: Revise this for Opie
361 *
362 * @see #isSoundsEnabled
363 */
364 virtual void setEnableSounds( bool enable ) { myBeep = enable; }
365
366 /**
367 * Tells you whether OCompletion will play sounds on certain occasions.
368 * Default is enabled
369 * @see #enableSounds
370 * @see #disableSounds
371 */
372 bool isSoundsEnabled() const { return myBeep; };
373
374 /**
375 * @returns true when more than one match is found
376 * @see #multipleMatches
377 */
378 bool hasMultipleMatches() const { return myHasMultipleMatches; };
379
380 public slots:
381 /**
382 * Attempts to complete "string" and emits the completion via @ref match().
383 * Same as @ref makeCompletion() (just as a slot).
384 * @see #makeCompletion
385 */
386 void slotMakeCompletion( const QString& string ) { (void) makeCompletion( string ); };
387
388 /**
389 * Searches the previous matching item and emits it via @ref match()
390 * Same as @ref previousMatch() (just as a slot).
391 * @see #previousMatch
392 */
393 void slotPreviousMatch() { (void) previousMatch(); };
394
395 /**
396 * Searches the next matching item and emits it via @ref match()
397 * Same as @ref nextMatch() (just as a slot).
398 * @see #nextMatch
399 */
400 void slotNextMatch() { (void) nextMatch(); };
401
402 /**
403 * Inserts @p items into the list of possible completions.
404 * Does the same as @ref setItems(), but does not call @ref clear() before.
405 */
406 void insertItems( const QStringList& items );
407
408 /**
409 * Sets the list of items available for completion. Removes all previous
410 * items.
411 *
412 * Notice: when order() == Weighted, then the weighting is looked up for
413 * every item in the stringlist. Every item should have ":number" appended,
414 * where number is an unsigned integer, specifying the weighting.
415 *
416 * If you don't like this, call
417 * setOrder( OCompletion::Insertion )
418 * before calling setItems().
419 *
420 * @see #items
421 */
422 virtual void setItems( const QStringList& );
423
424 /**
425 * Adds an item to the list of available completions.
426 * Resets the current item-state (@ref previousMatch() and @ref nextMatch()
427 * won't work anymore).
428 */
429 void addItem( const QString& );
430
431 /**
432 * Adds an item to the list of available completions.
433 * Resets the current item-state (@ref previousMatch() and @ref nextMatch()
434 * won't work anymore).
435 *
436 * Sets the weighting of the item to @p weight or adds it to the current
437 * weighting if the item is already available. The weight has to be greater
438 * than 1 to take effect (default weight is 1).
439 */
440 void addItem( const QString&, uint weight );
441
442 /**
443 * Removes an item from the list of available completions.
444 * Resets the current item-state (@ref previousMatch() and @ref nextMatch()
445 * won't work anymore).
446 */
447 void removeItem( const QString& );
448
449 /**
450 * Removes all inserted items.
451 */
452 virtual void clear();
453
454 signals:
455 /**
456 * The matching item. Will be emitted by @ref makeCompletion(),
457 * @ref previousMatch() or @ref nextMatch(). May be QString::null if there
458 * is no matching item.
459 */
460 void match( const QString& );
461
462 /**
463 * All matching items. Will be emitted by @ref makeCompletion() in shell-
464 * completion-mode, when the same string is passed to makeCompletion twice
465 * or more often.
466 */
467 void matches( const QStringList& );
468
469 /**
470 * This signal is emitted, when calling @ref makeCompletion() and more than
471 * one matching item is found.
472 * @see #hasMultipleMatches
473 */
474 void multipleMatches();
475
476 protected:
477 /**
478 * This method is called after a completion is found and before the
479 * matching string is emitted. You can override this method to modify the
480 * string that will be emitted.
481 * This is necessary e.g. in @ref OURLCompletion(), where files with spaces
482 * in their names are shown escaped ("filename\ with\ spaces"), but stored
483 * unescaped inside OCompletion.
484 * Never delete that pointer!
485 *
486 * Default implementation does nothing.
487 * @see #postProcessMatches
488 */
489 virtual void postProcessMatch( QString * /*match*/ ) const {}
490
491 /**
492 * This method is called before a list of all available completions is
493 * emitted via @ref matches. You can override this method to modify the
494 * found items before @ref match() or @ref matches() are emitted.
495 * Never delete that pointer!
496 *
497 * Default implementation does nothing.
498 * @see #postProcessMatch
499 */
500 virtual void postProcessMatches( QStringList * /*matches*/ ) const {}
501
502 /**
503 * This method is called before a list of all available completions is
504 * emitted via @ref matches. You can override this method to modify the
505 * found items before @ref match() or @ref matches() are emitted.
506 * Never delete that pointer!
507 *
508 * Default implementation does nothing.
509 * @see #postProcessMatch
510 */
511 virtual void postProcessMatches( OCompletionMatches * /*matches*/ ) const {}
512
513private:
514 void addWeightedItem( const QString& );
515 QString findCompletion( const QString& string );
516 void findAllCompletions( const QString&, OCompletionMatchesWrapper *matches, bool& hasMultipleMatches ) const;
517
518 void extractStringsFromNode( const OCompTreeNode *,
519 const QString& beginning,
520 OCompletionMatchesWrapper *matches,
521 bool addWeight = false ) const;
522 void extractStringsFromNodeCI( const OCompTreeNode *,
523 const QString& beginning,
524 const QString& restString,
525 OCompletionMatchesWrapper *matches) const;
526
527 enum BeepMode { NoMatch, PartialMatch, Rotation };
528 void doBeep( BeepMode ) const;
529
530 OGlobalSettings::Completion myCompletionMode;
531
532 CompOrder myOrder;
533 QString myLastString;
534 QString myLastMatch;
535 QString myCurrentMatch;
536 OCompTreeNode * myTreeRoot;
537 QStringList myRotations;
538 bool myBeep;
539 bool myIgnoreCase;
540 bool myHasMultipleMatches;
541 uint myRotationIndex;
542
543 private:
544 OCompletionPrivate *d;
545};
546
547// some more helper stuff
548typedef OSortableValueList<QString> OCompletionMatchesList;
549class OCompletionMatchesPrivate;
550
551/**
552 * This structure is returned by @ref OCompletion::allWeightedMatches .
553 * It also keeps the weight of the matches, allowing
554 * you to modify some matches or merge them with matches
555 * from another call to allWeightedMatches(), and sort the matches
556 * after that in order to have the matches ordered correctly
557 *
558 * Example (a simplified example of what Oonqueror's completion does):
559 * <pre>
560 * OCompletionMatches matches = completion->allWeightedMatches( location );
561 * if( !location.startsWith( "www." ))
562 matches += completion->allWeightedmatches( "www." + location" );
563 * matches.removeDuplicates();
564 * QStringList list = matches.list();
565 * </pre>
566 *
567 * @short List for keeping matches returned from OCompletion
568 */
569
570class OCompletionMatches
571 : public OCompletionMatchesList
572{
573 public:
574 OCompletionMatches( bool sort );
575 /**
576 * @internal
577 */
578 OCompletionMatches( const OCompletionMatchesWrapper& matches );
579 ~OCompletionMatches();
580 /**
581 * Removes duplicate matches. Needed only when you merged several matches
582 * results and there's a possibility of duplicates.
583 */
584 void removeDuplicates();
585 /**
586 * Returns the matches as a QStringList.
587 * @param sort if false, the matches won't be sorted before the conversion,
588 * use only if you're sure the sorting is not needed
589 */
590 QStringList list( bool sort = true ) const;
591 /**
592 * If sorting() returns false, the matches aren't sorted by their weight,
593 * even if true is passed to list().
594 */
595 bool sorting() const {
596 return _sorting;
597 }
598private:
599 bool _sorting;
600 OCompletionMatchesPrivate* d;
601};
602
603#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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 Inspired by the KDE completion classes which are
6 Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31*/
32
33#include <opie2/ocompletion.h>
34#include <opie2/ocompletionbase.h>
35
36OCompletionBase::OCompletionBase()
37{
38 m_delegate = 0L;
39 // Assign the default completion type to use.
40 m_iCompletionMode = OGlobalSettings::completionMode();
41
42 // Initialize all key-bindings to 0 by default so that
43 // the event filter will use the global settings.
44 useGlobalKeyBindings();
45
46 // By default we initialize everything to false.
47 // All the variables would be setup properly when
48 // the appropriate member functions are called.
49 setup( false, false, false );
50}
51
52OCompletionBase::~OCompletionBase()
53{
54 if( m_bAutoDelCompObj && m_pCompObj )
55 {
56 delete m_pCompObj;
57 }
58}
59
60void OCompletionBase::setDelegate( OCompletionBase *delegate )
61{
62 m_delegate = delegate;
63
64 if ( m_delegate ) {
65 m_delegate->m_bAutoDelCompObj = m_bAutoDelCompObj;
66 m_delegate->m_bHandleSignals = m_bHandleSignals;
67 m_delegate->m_bEmitSignals = m_bEmitSignals;
68 m_delegate->m_iCompletionMode = m_iCompletionMode;
69 m_delegate->m_keyMap = m_keyMap;
70 }
71}
72
73OCompletion* OCompletionBase::completionObject( bool hsig )
74{
75 if ( m_delegate )
76 return m_delegate->completionObject( hsig );
77
78 if ( !m_pCompObj )
79 {
80 setCompletionObject( new OCompletion(), hsig );
81 m_bAutoDelCompObj = true;
82 }
83 return m_pCompObj;
84}
85
86void OCompletionBase::setCompletionObject( OCompletion* compObj, bool hsig )
87{
88 if ( m_delegate ) {
89 m_delegate->setCompletionObject( compObj, hsig );
90 return;
91 }
92
93 if ( m_bAutoDelCompObj && compObj != m_pCompObj )
94 delete m_pCompObj;
95
96 m_pCompObj = compObj;
97
98 // We emit rotation and completion signals
99 // if completion object is not NULL.
100 setup( false, hsig, !m_pCompObj.isNull() );
101}
102
103// BC: Inline this function and possibly rename it to setHandleEvents??? (DA)
104void OCompletionBase::setHandleSignals( bool handle )
105{
106 if ( m_delegate )
107 m_delegate->setHandleSignals( handle );
108 else
109 m_bHandleSignals = handle;
110}
111
112void OCompletionBase::setCompletionMode( OGlobalSettings::Completion mode )
113{
114 if ( m_delegate ) {
115 m_delegate->setCompletionMode( mode );
116 return;
117 }
118
119 m_iCompletionMode = mode;
120 // Always sync up OCompletion mode with ours as long as we
121 // are performing completions.
122 if( m_pCompObj && m_iCompletionMode != OGlobalSettings::CompletionNone )
123 m_pCompObj->setCompletionMode( m_iCompletionMode );
124}
125
126bool OCompletionBase::setKeyBinding( KeyBindingType item, const OShortcut& cut )
127{
128 if ( m_delegate )
129 return m_delegate->setKeyBinding( item, cut );
130
131
132 if( !cut.isNull() )
133 {
134 for( KeyBindingMap::Iterator it = m_keyMap.begin(); it != m_keyMap.end(); ++it )
135 if( it.data() == cut ) return false;
136 }
137 m_keyMap.replace( item, cut );
138 return true;
139}
140
141void OCompletionBase::useGlobalKeyBindings()
142{
143
144/*
145
146 if ( m_delegate ) {
147 m_delegate->useGlobalKeyBindings();
148 return;
149 }
150
151 m_keyMap.clear();
152 m_keyMap.insert( TextCompletion, 0 );
153 m_keyMap.insert( PrevCompletionMatch, 0 );
154 m_keyMap.insert( NextCompletionMatch, 0 );
155 m_keyMap.insert( SubstringCompletion, 0 );
156
157*/
158
159}
160
161void OCompletionBase::setup( bool autodel, bool hsig, bool esig )
162{
163 if ( m_delegate ) {
164 m_delegate->setup( autodel, hsig, esig );
165 return;
166 }
167
168 m_bAutoDelCompObj = autodel;
169 m_bHandleSignals = hsig;
170 m_bEmitSignals = esig;
171}
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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 Inspired by the KDE completion classes which are
6 Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31*/
32
33#ifndef OCOMPLETIONBASE_H
34#define OCOMPLETIONBASE_H
35
36/**
37 * An abstract base class for adding a completion feature
38 * into widgets.
39 *
40 * This is a convenience class that provides the basic functions
41 * needed to add text completion support into widgets. All that
42 * is required is an implementation for the pure virtual function
43 * @ref setCompletedText. Refer to @ref OLineEdit or @ref OComboBox
44 * to see how easily such support can be added using this as a base
45 * class.
46 *
47 * @short An abstract class for adding text completion support to widgets.
48 * @author Dawit Alemayehu <adawit@kde.org>
49 */
50
51class OCompletionBase
52{
53
54 public:
55
56 /**
57 * Constants that represent the items whose short-cut
58 * key-binding is programmable. The default key-bindings
59 * for these items are defined in @ref OStdAccel.
60 */
61 enum KeyBindingType {
62 /**
63 * Text completion (by default Ctrl-E).
64 */
65 TextCompletion,
66 /**
67 * Switch to previous completion (by default Ctrl-Up).
68 */
69 PrevCompletionMatch,
70 /**
71 * Switch to next completion (by default Ctrl-Down).
72 */
73 NextCompletionMatch,
74 /**
75 * Substring completion (by default Ctrl-T).
76 */
77 SubstringCompletion
78 };
79
80
81 // Map for the key binding types mentioned above.
82 typedef QMap<KeyBindingType, OShortcut> KeyBindingMap;
83
84 /**
85 * Default constructor.
86 */
87 OCompletionBase();
88
89 /**
90 * Destructor.
91 */
92 virtual ~OCompletionBase();
93
94 /**
95 * Returns a pointer to the current completion object.
96 *
97 * If the object does not exist, it is automatically
98 * created. Note that the completion object created
99 * here is used by default to handle the signals
100 * internally. It is also deleted when this object's
101 * destructor is invoked. If you do not want these
102 * default settings, use @ref setAutoDeleteCompletionObject
103 * and @ref setHandleSignals to change the behavior.
104 * Alternatively, you can set the boolean parameter to
105 * false to disable the automatic handling of the signals
106 * by this object. Note that the boolean argument will be
107 * ignored if there already exists a completion object since
108 * no new object needs to be created. You need to use either
109 * @ref setHandleSignals or @ref setCompletionObject for
110 * such cases depending on your requirement.
111 *
112 * @param hsig if true, handles signals internally.
113 * @return a pointer the completion object.
114 */
115 OCompletion* completionObject( bool hsig = true );
116
117 /**
118 * Sets up the completion object to be used.
119 *
120 * This method assigns the completion object and sets it
121 * up to automatically handle the completion and rotation
122 * signals internally. You should use this function if
123 * you want to share one completion object among you widgets
124 * or need to use a customized completion object.
125 *
126 * The object assigned through this method is not deleted
127 * when this object's destructor is invoked unless you
128 * explicitly call @ref setAutoDeleteCompletionObject after
129 * calling this method. Also if you do not want the signals
130 * to be handled by an internal implementation, be sure to
131 * set the bool argument to false.
132 *
133 * This method is also called when a completion-object is created
134 * automatically, when completionObject() is called the first time.
135 *
136 * @param compObj a @ref OCompletion() or a derived child object.
137 * @param hsig if true, handles signals internally.
138 */
139 virtual void setCompletionObject( OCompletion* /*compObj*/, bool hsig = true );
140
141 /**
142 * Enables this object to handle completion and rotation
143 * events internally.
144 *
145 * This function simply assigns a boolean value that
146 * indicates whether it should handle rotation and
147 * completion events or not. Note that this does not
148 * stop the object from emitting signals when these
149 * events occur.
150 *
151 * @param handle if true, handle completion & rotation internally.
152 */
153 virtual void setHandleSignals( bool /*handle*/ );
154
155 /**
156 * Returns true if the completion object is deleted
157 * upon this widget's destruction.
158 *
159 * See @ref setCompletionObject() and @ref enableCompletion()
160 * for details.
161 *
162 * @return true if the completion object
163 */
164 bool isCompletionObjectAutoDeleted() const {
165 return m_delegate ? m_delegate->isCompletionObjectAutoDeleted() : m_bAutoDelCompObj;
166 }
167
168 /**
169 * Sets the completion object when this widget's destructor
170 * is called.
171 *
172 * If the argument is set to true, the completion object
173 * is deleted when this widget's destructor is called.
174 *
175 * @param autoDelete if true, delete completion object on destruction.
176 */
177 void setAutoDeleteCompletionObject( bool autoDelete ) {
178 if ( m_delegate )
179 m_delegate->setAutoDeleteCompletionObject( autoDelete );
180 else
181 m_bAutoDelCompObj = autoDelete;
182 }
183
184 /**
185 * Sets the widget's ability to emit text completion and
186 * rotation signals.
187 *
188 * Invoking this function with @p enable set to @p false will
189 * cause the completion & rotation signals not to be emitted.
190 * However, unlike setting the completion object to @p NULL
191 * using @ref setCompletionObject, disabling the emition of
192 * the signals through this method does not affect the current
193 * completion object.
194 *
195 * There is no need to invoke this function by default. When a
196 * completion object is created through @ref completionObject or
197 * @ref setCompletionObject, these signals are set to emit
198 * automatically. Also note that disabling this signals will not
199 * necessarily interfere with the objects ability to handle these
200 * events internally. See @ref setHandleSignals.
201 *
202 * @param enable if false, disables the emition of completion & rotation signals.
203 */
204 void setEnableSignals( bool enable ) {
205 if ( m_delegate )
206 m_delegate->setEnableSignals( enable );
207 else
208 m_bEmitSignals = enable;
209 }
210
211 /**
212 * Returns true if the object handles the signals
213 *
214 * @return true if this signals are handled internally.
215 */
216 bool handleSignals() const { return m_delegate ? m_delegate->handleSignals() : m_bHandleSignals; }
217
218 /**
219 * Returns true if the object emits the signals
220 *
221 * @return true if signals are emitted
222 */
223 bool emitSignals() const { return m_delegate ? m_delegate->emitSignals() : m_bEmitSignals; }
224
225 /**
226 * Sets the type of completion to be used.
227 *
228 * The completion modes supported are those defined in
229 * @ref OGlobalSettings(). See below.
230 *
231 * @param mode Completion type:
232 * @li CompletionNone: Disables completion feature.
233 * @li CompletionAuto: Attempts to find a match &
234 * fills-in the remaining text.
235 * @li CompletionMan: Acts the same as the above
236 * except the action has to be
237 * manually triggered through
238 * pre-defined completion key.
239 * @li CompletionShell: Mimics the completion feature
240 * found in typical *nix shell
241 * environments.
242 * @li CompletionPopup: Shows all available completions at once,
243 * in a listbox popping up.
244 */
245 virtual void setCompletionMode( OGlobalSettings::Completion mode );
246
247 /**
248 * Returns the current completion mode.
249 *
250 * The return values are of type @ref OGlobalSettings::Completion.
251 * See @ref setCompletionMode() for details.
252 *
253 * @return the completion mode.
254 */
255 OGlobalSettings::Completion completionMode() const {
256 return m_delegate ? m_delegate->completionMode() : m_iCompletionMode;
257 }
258
259 /**
260 * Sets the key-binding to be used for manual text
261 * completion, text rotation in a history list as
262 * well as a completion list.
263 *
264 *
265 * When the keys set by this function are pressed, a
266 * signal defined by the inheriting widget will be activated.
267 * If the default value or 0 is specified by the second
268 * parameter, then the key-binding as defined in the global
269 * setting should be used. This method returns false value
270 * for @p key is negative or the supplied key-binding conflicts
271 * with the ones set for one of the other features.
272 *
273 * NOTE: To use a modifier key (Shift, Ctrl, Alt) as part of
274 * the key-binding simply simply @p sum up the values of the
275 * modifier and the actual key. For example, to use CTRL+E as
276 * a key binding for one of the items, you would simply supply
277 * @p "Qt::CtrlButton + Qt::Key_E" as the second argument to this
278 * function.
279 *
280 * @param item the feature whose key-binding needs to be set:
281 *
282 * @li TextCompletionthe manual completion key-binding.
283 * @li PrevCompletionMatchthe previous match key for multiple completion.
284 * @li NextCompletionMatchthe next match key for for multiple completion.
285 * @li SubstringCompletion the key for substring completion
286 *
287 * @param key key-binding used to rotate down in a list.
288 *
289 * @return true if key-binding can successfully be set.
290 * @see #getKeyBinding
291 */
292 bool setKeyBinding( KeyBindingType /*item*/ , const OShortcut& cut );
293
294 /**
295 * Returns the key-binding used for the specified item.
296 *
297 * This methods returns the key-binding used to activate
298 * the feature feature given by @p item. If the binding
299 * contains modifier key(s), the SUM of the modifier key
300 * and the actual key code are returned.
301 *
302 * @return the key-binding used for the feature given by @p item.
303 * @see #setKeyBinding
304 */
305 const OShortcut& getKeyBinding( KeyBindingType item ) const {
306 return m_delegate ? m_delegate->getKeyBinding( item ) : m_keyMap[ item ];
307 }
308
309 /**
310 * Sets this object to use global values for key-bindings.
311 *
312 * This method changes the values of the key bindings for
313 * rotation and completion features to the default values
314 * provided in OGlobalSettings.
315 *
316 * NOTE: By default inheriting widgets should uses the
317 * global key-bindings so that there will be no need to
318 * call this method.
319 */
320 void useGlobalKeyBindings();
321
322 /**
323 * A pure virtual function that must be implemented by
324 * all inheriting classes.
325 *
326 * This function is intended to allow external completion
327 * implementations to set completed text appropriately. It
328 * is mostly relevant when the completion mode is set to
329 * CompletionAuto and CompletionManual modes. See
330 * @ref OCompletionBase::setCompletedText.
331 * Does nothing in CompletionPopup mode, as all available
332 * matches will be shown in the popup.
333 *
334 * @param text the completed text to be set in the widget.
335 */
336 virtual void setCompletedText( const QString& text ) = 0;
337
338 /**
339 * A pure virtual function that must be implemented by
340 * all inheriting classes.
341 *
342 */
343 virtual void setCompletedItems( const QStringList& items ) = 0;
344
345 /**
346 * Returns a pointer to the completion object.
347 *
348 * This method is only different from @ref completionObject()
349 * in that it does not create a new OCompletion object even if
350 * the internal pointer is @p NULL. Use this method to get the
351 * pointer to a completion object when inheriting so that you
352 * won't inadvertently create it!!
353 *
354 * @returns the completion object or NULL if one does not exist.
355 */
356 OCompletion* compObj() const { return m_delegate ? m_delegate->compObj() : (OCompletion*) m_pCompObj; }
357
358protected:
359 /**
360 * Returns a key-binding map
361 *
362 * This method is the same as @ref getKeyBinding() except it
363 * returns the whole keymap containing the key-bindings.
364 *
365 * @return the key-binding used for the feature given by @p item.
366 */
367 KeyBindingMap getKeyBindings() const { return m_delegate ? m_delegate->getKeyBindings() : m_keyMap; }
368
369 void setDelegate( OCompletionBase *delegate );
370 OCompletionBase *delegate() const { return m_delegate; }
371
372private:
373 // This method simply sets the autodelete boolean for
374 // the completion object, the emit signals and handle
375 // signals internally flags to the provided values.
376 void setup( bool, bool, bool );
377
378 // Flag that determined whether the completion object
379 // should be deleted when this object is destroyed.
380 bool m_bAutoDelCompObj;
381 // Determines whether this widget handles completion signals
382 // internally or not
383 bool m_bHandleSignals;
384 // Determines whether this widget fires rotation signals
385 bool m_bEmitSignals;
386 // Stores the completion mode locally.
387 OGlobalSettings::Completion m_iCompletionMode;
388 // Pointer to Completion object.
389 QGuardedPtr<OCompletion> m_pCompObj;
390 // Keybindings
391 KeyBindingMap m_keyMap;
392 // we may act as a proxy to another OCompletionBase object
393 OCompletionBase *m_delegate;
394
395 // FIXME: Revise this for Opie?
396 //protected:
397 // virtual void virtual_hook( int id, void* data );
398 private:
399 OCompletionBasePrivate *d;
400};
401
402#endif // OCOMPLETIONBASE_H
403
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 @@
1// QPair minus QT_INLINE_TEMPLATE (instead directly using 'inline' directive)
2//FIXME: remove and use qpair.h as soon as we're on Qt3
3
4/****************************************************************************
5**
6** Definition of QPair class
7**
8**
9** Copyright (C) 1992-2001 Trolltech AS. All rights reserved.
10**
11** This file is part of the tools module of the Qt GUI Toolkit.
12**
13** This file may be distributed under the terms of the Q Public License
14** as defined by Trolltech AS of Norway and appearing in the file
15** LICENSE.QPL included in the packaging of this file.
16**
17** This file may be distributed and/or modified under the terms of the
18** GNU General Public License version 2 as published by the Free Software
19** Foundation and appearing in the file LICENSE.GPL included in the
20** packaging of this file.
21**
22** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
23** licenses may use this file in accordance with the Qt Commercial License
24** Agreement provided with the Software.
25**
26** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
27** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28**
29** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
30** information about Qt Commercial License Agreements.
31** See http://www.trolltech.com/qpl/ for QPL licensing information.
32** See http://www.trolltech.com/gpl/ for GPL licensing information.
33**
34** Contact info@trolltech.com if any conditions of this licensing are
35** not clear to you.
36**
37**********************************************************************/
38
39#ifndef QPAIR_H
40#define QPAIR_H
41
42#ifndef QT_H
43#include "qglobal.h"
44#include "qdatastream.h"
45#endif // QT_H
46
47template <class T1, class T2>
48struct QPair
49{
50 typedef T1 first_type;
51 typedef T2 second_type;
52
53 QPair()
54 : first( T1() ), second( T2() )
55 {}
56 QPair( const T1& t1, const T2& t2 )
57 : first( t1 ), second( t2 )
58 {}
59
60 T1 first;
61 T2 second;
62};
63
64template <class T1, class T2>
65inline bool operator==( const QPair<T1, T2>& x, const QPair<T1, T2>& y )
66{
67 return x.first == y.first && x.second == y.second;
68}
69
70template <class T1, class T2>
71inline bool operator<( const QPair<T1, T2>& x, const QPair<T1, T2>& y )
72{
73 return x.first < y.first ||
74 ( !( y.first < x.first ) && x.second < y.second );
75}
76
77template <class T1, class T2>
78inline QPair<T1, T2> qMakePair( const T1& x, const T2& y )
79{
80 return QPair<T1, T2>( x, y );
81}
82
83#ifndef QT_NO_DATASTREAM
84template <class T1, class T2>
85inline QDataStream& operator>>( QDataStream& s, QPair<T1, T2>& p )
86{
87 s >> p.first >> p.second;
88 return s;
89}
90
91template <class T1, class T2>
92inline QDataStream& operator<<( QDataStream& s, const QPair<T1, T2>& p )
93{
94 s << p.first << p.second;
95 return s;
96}
97#endif
98
99#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 @@
1/*
2                 This file is part of the Opie Project
3 Originally a part of the KDE Project
4 (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29*/
30
31#ifndef OSORTABLEVALUELIST_H
32#define OSORTABLEVALUELIST_H
33
34#if QT_VERSION > 290
35#include <qtl.h>
36#include <qpair.h>
37#else
38#include <opie2/otl.h>
39#include <opie2/opair.h>
40#endif
41#include <qvaluelist.h>
42
43template<class T, class Key = int> class OSortableItem : public QPair<Key,T>
44{
45public:
46 OSortableItem( Key i, const T& t ) : QPair<Key, T>( i, t ) {}
47 OSortableItem( const OSortableItem<T, Key> &rhs )
48 : QPair<Key,T>( rhs.first, rhs.second ) {}
49
50 OSortableItem() {}
51
52 OSortableItem<T, Key> &operator=( const OSortableItem<T, Key>& i ) {
53 first = i.first;
54 second = i.second;
55 return *this;
56 }
57
58 // operators for sorting
59 bool operator> ( const OSortableItem<T, Key>& i2 ) const {
60 return (i2.first < first);
61 }
62 bool operator< ( const OSortableItem<T, Key>& i2 ) const {
63 return (first < i2.first);
64 }
65 bool operator>= ( const OSortableItem<T, Key>& i2 ) const {
66 return (first >= i2.first);
67 }
68 bool operator<= ( const OSortableItem<T, Key>& i2 ) const {
69 return !(i2.first < first);
70 }
71 bool operator== ( const OSortableItem<T, Key>& i2 ) const {
72 return (first == i2.first);
73 }
74 bool operator!= ( const OSortableItem<T, Key>& i2 ) const {
75 return (first != i2.first);
76 }
77
78 T& value() {
79 return second;
80 }
81 const T& value() const {
82 return second;
83 }
84
85 Key index() const {
86 return first;
87 }
88};
89
90
91// convenience
92template <class T, class Key = int>
93class OSortableValueList : public QValueList<OSortableItem<T, Key> >
94{
95public:
96 void insert( Key i, const T& t ) {
97 QValueList<OSortableItem<T, Key> >::append( OSortableItem<T, Key>( i, t ) );
98 }
99 // add more as you please...
100
101 T& operator[]( Key i ) {
102 return QValueList<OSortableItem<T, Key> >::operator[]( i ).value();
103 }
104 const T& operator[]( Key i ) const {
105 return QValueList<OSortableItem<T, Key> >::operator[]( i ).value();
106 }
107
108 void sort() {
109 qHeapSort( *this );
110 }
111};
112
113// template <class T> class OSortableValueListIterator : public QValueListIterator<OSortableItem<T> >
114// {
115// };
116
117#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 @@
1// qtl minus QT_INLINE_TEMPLATE and QT_EXPLICIT (instead directly using 'inline' directive)
2//FIXME: remove and use qtl.h as soon as we're on Qt3
3
4/****************************************************************************
5** $Id$
6**
7** Definition of Qt template library classes
8**
9** Created : 990128
10**
11** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
12**
13** This file is part of the tools module of the Qt GUI Toolkit.
14**
15** This file may be distributed under the terms of the Q Public License
16** as defined by Trolltech AS of Norway and appearing in the file
17** LICENSE.QPL included in the packaging of this file.
18**
19** This file may be distributed and/or modified under the terms of the
20** GNU General Public License version 2 as published by the Free Software
21** Foundation and appearing in the file LICENSE.GPL included in the
22** packaging of this file.
23**
24** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
25** licenses may use this file in accordance with the Qt Commercial License
26** Agreement provided with the Software.
27**
28** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30**
31** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
32** information about Qt Commercial License Agreements.
33** See http://www.trolltech.com/qpl/ for QPL licensing information.
34** See http://www.trolltech.com/gpl/ for GPL licensing information.
35**
36** Contact info@trolltech.com if any conditions of this licensing are
37** not clear to you.
38**
39**********************************************************************/
40
41#ifndef QTL_H
42#define QTL_H
43
44#ifndef QT_H
45#include "qglobal.h"
46#include "qtextstream.h"
47#include "qstring.h"
48#endif // QT_H
49
50#ifndef QT_NO_TEXTSTREAM
51template <class T>
52class QTextOStreamIterator
53{
54protected:
55 QTextOStream& stream;
56 QString separator;
57
58public:
59 QTextOStreamIterator( QTextOStream& s) : stream( s ) {}
60 QTextOStreamIterator( QTextOStream& s, const QString& sep )
61 : stream( s ), separator( sep ) {}
62 QTextOStreamIterator<T>& operator= ( const T& x ) {
63 stream << x;
64 if ( !separator.isEmpty() )
65 stream << separator;
66 return *this;
67 }
68 QTextOStreamIterator<T>& operator*() { return *this; }
69 QTextOStreamIterator<T>& operator++() { return *this; }
70 QTextOStreamIterator<T>& operator++(int) { return *this; }
71};
72#endif //QT_NO_TEXTSTREAM
73
74template <class InputIterator, class OutputIterator>
75inline OutputIterator qCopy( InputIterator _begin, InputIterator _end,
76 OutputIterator _dest )
77{
78 while( _begin != _end )
79 *_dest++ = *_begin++;
80 return _dest;
81}
82
83template <class BiIterator, class BiOutputIterator>
84inline BiOutputIterator qCopyBackward( BiIterator _begin, BiIterator _end,
85 BiOutputIterator _dest )
86{
87 while ( _begin != _end )
88 *--_dest = *--_end;
89 return _dest;
90}
91
92template <class InputIterator1, class InputIterator2>
93inline bool qEqual( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2 )
94{
95 // ### compare using !(*first1 == *first2) in Qt 4.0
96 for ( ; first1 != last1; ++first1, ++first2 )
97 if ( *first1 != *first2 )
98 return FALSE;
99 return TRUE;
100}
101
102template <class ForwardIterator, class T>
103inline void qFill( ForwardIterator first, ForwardIterator last, const T& val )
104{
105 for ( ; first != last; ++first )
106 *first = val;
107}
108
109#if 0
110template <class BiIterator, class OutputIterator>
111inline OutputIterator qReverseCopy( BiIterator _begin, BiIterator _end,
112 OutputIterator _dest )
113{
114 while ( _begin != _end ) {
115 --_end;
116 *_dest = *_end;
117 ++_dest;
118 }
119 return _dest;
120}
121#endif
122
123
124template <class InputIterator, class T>
125inline InputIterator qFind( InputIterator first, InputIterator last,
126 const T& val )
127{
128 while ( first != last && *first != val )
129 ++first;
130 return first;
131}
132
133template <class InputIterator, class T, class Size>
134inline void qCount( InputIterator first, InputIterator last, const T& value,
135 Size& n )
136{
137 for ( ; first != last; ++first )
138 if ( *first == value )
139 ++n;
140}
141
142template <class T>
143inline void qSwap( T& _value1, T& _value2 )
144{
145 T tmp = _value1;
146 _value1 = _value2;
147 _value2 = tmp;
148}
149
150
151template <class InputIterator>
152inline void qBubbleSort( InputIterator b, InputIterator e )
153{
154 // Goto last element;
155 InputIterator last = e;
156 --last;
157 // only one element or no elements ?
158 if ( last == b )
159 return;
160
161 // So we have at least two elements in here
162 while( b != last ) {
163 bool swapped = FALSE;
164 InputIterator swap_pos = b;
165 InputIterator x = e;
166 InputIterator y = x;
167 y--;
168 do {
169 --x;
170 --y;
171 if ( *x < *y ) {
172 swapped = TRUE;
173 qSwap( *x, *y );
174 swap_pos = y;
175 }
176 } while( y != b );
177 if ( !swapped )
178 return;
179 b = swap_pos;
180 b++;
181 }
182}
183
184
185template <class Container>
186inline void qBubbleSort( Container &c )
187{
188 qBubbleSort( c.begin(), c.end() );
189}
190
191
192template <class Value>
193inline void qHeapSortPushDown( Value* heap, int first, int last )
194{
195 int r = first;
196 while ( r <= last / 2 ) {
197 if ( last == 2 * r ) {
198 // node r has only one child
199 if ( heap[2 * r] < heap[r] )
200 qSwap( heap[r], heap[2 * r] );
201 r = last;
202 } else {
203 // node r has two children
204 if ( heap[2 * r] < heap[r] && !(heap[2 * r + 1] < heap[2 * r]) ) {
205 // swap with left child
206 qSwap( heap[r], heap[2 * r] );
207 r *= 2;
208 } else if ( heap[2 * r + 1] < heap[r]
209 && heap[2 * r + 1] < heap[2 * r] ) {
210 // swap with right child
211 qSwap( heap[r], heap[2 * r + 1] );
212 r = 2 * r + 1;
213 } else {
214 r = last;
215 }
216 }
217 }
218}
219
220
221template <class InputIterator, class Value>
222inline void qHeapSortHelper( InputIterator b, InputIterator e, Value, uint n )
223{
224 // Create the heap
225 InputIterator insert = b;
226 Value* realheap = new Value[n];
227 // Wow, what a fake. But I want the heap to be indexed as 1...n
228 Value* heap = realheap - 1;
229 int size = 0;
230 for( ; insert != e; ++insert ) {
231 heap[++size] = *insert;
232 int i = size;
233 while( i > 1 && heap[i] < heap[i / 2] ) {
234 qSwap( heap[i], heap[i / 2] );
235 i /= 2;
236 }
237 }
238
239 // Now do the sorting
240 for( uint i = n; i > 0; i-- ) {
241 *b++ = heap[1];
242 if ( i > 1 ) {
243 heap[1] = heap[i];
244 qHeapSortPushDown( heap, 1, (int)i - 1 );
245 }
246 }
247
248 delete[] realheap;
249}
250
251
252template <class InputIterator>
253inline void qHeapSort( InputIterator b, InputIterator e )
254{
255 // Empty ?
256 if ( b == e )
257 return;
258
259 // How many entries have to be sorted ?
260 InputIterator it = b;
261 uint n = 0;
262 while ( it != e ) {
263 ++n;
264 ++it;
265 }
266
267 // The second last parameter is a hack to retrieve the value type
268 // Do the real sorting here
269 qHeapSortHelper( b, e, *b, n );
270}
271
272
273template <class Container>
274inline void qHeapSort( Container &c )
275{
276 if ( c.begin() == c.end() )
277 return;
278
279 // The second last parameter is a hack to retrieve the value type
280 // Do the real sorting here
281 qHeapSortHelper( c.begin(), c.end(), *(c.begin()), (uint)c.count() );
282}
283
284template <class Container>
285class QBackInsertIterator
286{
287public:
288 QBackInsertIterator( Container &c )
289 : container( &c )
290 {
291 }
292
293 QBackInsertIterator<Container>&
294 operator=( const typename Container::value_type &value )
295 {
296 container->push_back( value );
297 return *this;
298 }
299
300 QBackInsertIterator<Container>& operator*()
301 {
302 return *this;
303 }
304
305 QBackInsertIterator<Container>& operator++()
306 {
307 return *this;
308 }
309
310 QBackInsertIterator<Container>& operator++(int)
311 {
312 return *this;
313 }
314
315protected:
316 Container *container;
317};
318
319template <class Container>
320inline QBackInsertIterator<Container> qBackInserter( Container &c )
321{
322 return QBackInsertIterator<Container>( c );
323}
324
325#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 @@
1/*
2 This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
3 is part of the Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
4 Opie Project Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
5
6 =. Originally part of the KDE Project
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33/* QT */
34
35#include <qclipboard.h>
36#include <qlistbox.h>
37#include <qpopupmenu.h>
38
39/* OPIE */
40
41#include <opie2/ocompletionbox.h>
42#include <opie2/olineedit.h>
43#include <opie2/opixmapprovider.h>
44#include <opie2/ocombobox.h>
45
46/*======================================================================================
47 * OComboBoxPrivate
48 *======================================================================================*/
49
50class OComboBox::OComboBoxPrivate
51{
52public:
53 OComboBoxPrivate()
54 {
55 olineEdit = 0L;
56 }
57 ~OComboBoxPrivate()
58 {
59 }
60
61 OLineEdit *olineEdit;
62};
63
64/*======================================================================================
65 * OComboBox
66 *======================================================================================*/
67
68OComboBox::OComboBox( QWidget *parent, const char *name )
69 : QComboBox( parent, name )
70{
71 init();
72}
73
74OComboBox::OComboBox( bool rw, QWidget *parent, const char *name )
75 : QComboBox( rw, parent, name )
76{
77 init();
78
79 if ( rw )
80 {
81 OLineEdit *edit = new OLineEdit( this, "combo lineedit" );
82 setLineEdit( edit );
83 }
84}
85
86OComboBox::~OComboBox()
87{
88 delete d;
89}
90
91void OComboBox::init()
92{
93 d = new OComboBoxPrivate;
94
95 // Permanently set some parameters in the parent object.
96 QComboBox::setAutoCompletion( false );
97
98 // Initialize enable popup menu to false.
99 // Below it will be enabled if the widget
100 // is editable.
101 m_bEnableMenu = false;
102
103 m_trapReturnKey = false;
104
105 // Enable context menu by default if widget
106 // is editable.
107 setContextMenuEnabled( true );
108
109 // for wheelscrolling
110 installEventFilter( this );
111 if ( lineEdit() )
112 lineEdit()->installEventFilter( this );
113}
114
115
116bool OComboBox::contains( const QString& _text ) const
117{
118 if ( _text.isEmpty() )
119 return false;
120
121 for (int i = 0; i < count(); i++ ) {
122 if ( text(i) == _text )
123 return true;
124 }
125 return false;
126}
127
128void OComboBox::setAutoCompletion( bool autocomplete )
129{
130 if ( d->olineEdit )
131 {
132 if ( autocomplete )
133 {
134 d->olineEdit->setCompletionMode( OGlobalSettings::CompletionAuto );
135 setCompletionMode( OGlobalSettings::CompletionAuto );
136 }
137 else
138 {
139 d->olineEdit->setCompletionMode( OGlobalSettings::completionMode() );
140 setCompletionMode( OGlobalSettings::completionMode() );
141 }
142 }
143}
144
145void OComboBox::setContextMenuEnabled( bool showMenu )
146{
147 if( d->olineEdit )
148 {
149 d->olineEdit->setContextMenuEnabled( showMenu );
150 m_bEnableMenu = showMenu;
151 }
152}
153
154/*
155void OComboBox::setURLDropsEnabled( bool enable )
156{
157 if ( d->olineEdit )
158 d->olineEdit->setURLDropsEnabled( enable );
159}
160
161bool OComboBox::isURLDropsEnabled() const
162{
163 return d->olineEdit && d->olineEdit->isURLDropsEnabled();
164}
165*/
166
167void OComboBox::setCompletedText( const QString& text, bool marked )
168{
169 if ( d->olineEdit )
170 d->olineEdit->setCompletedText( text, marked );
171}
172
173void OComboBox::setCompletedText( const QString& text )
174{
175 if ( d->olineEdit )
176 d->olineEdit->setCompletedText( text );
177}
178
179void OComboBox::makeCompletion( const QString& text )
180{
181 if( d->olineEdit )
182 d->olineEdit->makeCompletion( text );
183
184 else // read-only combo completion
185 {
186 if( text.isNull() || !listBox() )
187 return;
188
189 int index = listBox()->index( listBox()->findItem( text ) );
190 if( index >= 0 ) {
191 setCurrentItem( index );
192 }
193 }
194}
195
196void OComboBox::rotateText( OCompletionBase::KeyBindingType type )
197{
198 if ( d->olineEdit )
199 d->olineEdit->rotateText( type );
200}
201
202bool OComboBox::eventFilter( QObject* o, QEvent* ev )
203{
204 QLineEdit *edit = lineEdit();
205
206 int type = ev->type();
207
208 if ( o == edit )
209 {
210 //OCursor::autoHideEventFilter( edit, ev );
211
212 if ( type == QEvent::KeyPress )
213 {
214 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
215
216 if ( e->key() == Key_Return || e->key() == Key_Enter)
217 {
218 // On Return pressed event, emit both
219 // returnPressed(const QString&) and returnPressed() signals
220 emit returnPressed();
221 emit returnPressed( currentText() );
222 if ( d->olineEdit && d->olineEdit->completionBox(false) &&
223 d->olineEdit->completionBox()->isVisible() )
224 d->olineEdit->completionBox()->hide();
225
226 return m_trapReturnKey;
227 }
228 }
229 }
230
231
232 // wheel-scrolling changes the current item
233 if ( type == QEvent::Wheel ) {
234 if ( !listBox() || listBox()->isHidden() ) {
235 QWheelEvent *e = static_cast<QWheelEvent*>( ev );
236 static const int WHEEL_DELTA = 120;
237 int skipItems = e->delta() / WHEEL_DELTA;
238 if ( e->state() & ControlButton ) // fast skipping
239 skipItems *= 10;
240
241 int newItem = currentItem() - skipItems;
242
243 if ( newItem < 0 )
244 newItem = 0;
245 else if ( newItem >= count() )
246 newItem = count() -1;
247
248 setCurrentItem( newItem );
249 if ( !text( newItem ).isNull() )
250 emit activated( text( newItem ) );
251 emit activated( newItem );
252 e->accept();
253 return true;
254 }
255 }
256
257 return QComboBox::eventFilter( o, ev );
258}
259
260void OComboBox::setTrapReturnKey( bool grab )
261{
262 m_trapReturnKey = grab;
263}
264
265bool OComboBox::trapReturnKey() const
266{
267 return m_trapReturnKey;
268}
269
270/*
271void OComboBox::setEditURL( const OURL& url )
272{
273 QComboBox::setEditText( url.prettyURL() );
274}
275
276void OComboBox::insertURL( const OURL& url, int index )
277{
278 QComboBox::insertItem( url.prettyURL(), index );
279}
280
281void OComboBox::insertURL( const QPixmap& pixmap, const OURL& url, int index )
282{
283 QComboBox::insertItem( pixmap, url.prettyURL(), index );
284}
285
286void OComboBox::changeURL( const OURL& url, int index )
287{
288 QComboBox::changeItem( url.prettyURL(), index );
289}
290
291void OComboBox::changeURL( const QPixmap& pixmap, const OURL& url, int index )
292{
293 QComboBox::changeItem( pixmap, url.prettyURL(), index );
294}
295*/
296
297
298void OComboBox::setCompletedItems( const QStringList& items )
299{
300 if ( d->olineEdit )
301 d->olineEdit->setCompletedItems( items );
302}
303
304
305OCompletionBox * OComboBox::completionBox( bool create )
306{
307 if ( d->olineEdit )
308 return d->olineEdit->completionBox( create );
309 return 0;
310}
311
312// QWidget::create() turns off mouse-Tracking which would break auto-hiding
313void OComboBox::create( WId id, bool initializeWindow, bool destroyOldWindow )
314{
315 QComboBox::create( id, initializeWindow, destroyOldWindow );
316 //OCursor::setAutoHideCursor( lineEdit(), true, true );
317}
318
319void OComboBox::setLineEdit( OLineEdit *edit )
320{
321 #if QT_VERSION > 290
322 QComboBox::setLineEdit( edit );
323 d->olineEdit = dynamic_cast<OLineEdit*>( edit );
324 setDelegate( d->olineEdit );
325
326 // forward some signals. We only emit returnPressed() ourselves.
327 if ( d->olineEdit ) {
328 connect( d->olineEdit, SIGNAL( completion( const QString& )),
329 SIGNAL( completion( const QString& )) );
330 connect( d->olineEdit, SIGNAL( substringCompletion( const QString& )),
331 SIGNAL( substringCompletion( const QString& )) );
332 connect( d->olineEdit,
333 SIGNAL( textRotation( OCompletionBase::KeyBindingType )),
334 SIGNAL( textRotation( OCompletionBase::KeyBindingType )) );
335 connect( d->olineEdit,
336 SIGNAL( completionModeChanged( OGlobalSettings::Completion )),
337 SIGNAL( completionModeChanged( OGlobalSettings::Completion)));
338
339 connect( d->olineEdit,
340 SIGNAL( aboutToShowContextMenu( QPopupMenu * )),
341 SIGNAL( aboutToShowContextMenu( QPopupMenu * )) );
342 }
343 #else
344 #warning OComboBox is not fully functional with Qt2
345 #endif
346}
347
348// Temporary functions until QT3 appears. - Seth Chaiklin 20 may 2001
349void OComboBox::deleteWordForward()
350{
351 lineEdit()->cursorWordForward(TRUE);
352 #if QT_VERSION > 290
353 if ( lineEdit()->hasSelectedText() )
354 #else
355 if ( lineEdit()->hasMarkedText() )
356 #endif
357 {
358 lineEdit()->del();
359 }
360}
361
362void OComboBox::deleteWordBack()
363{
364 lineEdit()->cursorWordBackward(TRUE);
365 #if QT_VERSION > 290
366 if ( lineEdit()->hasSelectedText() )
367 #else
368 if ( lineEdit()->hasMarkedText() )
369 #endif
370 {
371 lineEdit()->del();
372 }
373}
374
375void OComboBox::setCurrentItem( const QString& item, bool insert, int index )
376{
377 int sel = -1;
378 for (int i = 0; i < count(); ++i)
379 if (text(i) == item)
380 {
381 sel = i;
382 break;
383 }
384 if (sel == -1 && insert)
385 {
386 insertItem(item, index);
387 if (index >= 0)
388 sel = index;
389 else
390 sel = count() - 1;
391 }
392 setCurrentItem(sel);
393}
394
395void OComboBox::setCurrentItem(int index)
396{
397 QComboBox::setCurrentItem(index);
398}
399
400
401/*======================================================================================
402 * OHistoryCombo
403 *======================================================================================*/
404
405// we are always read-write
406OHistoryCombo::OHistoryCombo( QWidget *parent, const char *name )
407 : OComboBox( true, parent, name )
408{
409 init( true ); // using completion
410}
411
412// we are always read-write
413OHistoryCombo::OHistoryCombo( bool useCompletion,
414 QWidget *parent, const char *name )
415 : OComboBox( true, parent, name )
416{
417 init( useCompletion );
418}
419
420void OHistoryCombo::init( bool useCompletion )
421{
422 if ( useCompletion )
423 completionObject()->setOrder( OCompletion::Weighted );
424
425 setInsertionPolicy( NoInsertion );
426 myIterateIndex = -1;
427 myRotated = false;
428 myPixProvider = 0L;
429
430 connect( this, SIGNAL(aboutToShowContextMenu(QPopupMenu*)),
431 SLOT(addContextMenuItems(QPopupMenu*)) );
432 connect( this, SIGNAL( activated(int) ), SLOT( slotReset() ));
433 connect( this, SIGNAL( returnPressed(const QString&) ), SLOT(slotReset()));
434}
435
436OHistoryCombo::~OHistoryCombo()
437{
438 delete myPixProvider;
439}
440
441void OHistoryCombo::setHistoryItems( QStringList items,
442 bool setCompletionList )
443{
444 OComboBox::clear();
445
446 // limit to maxCount()
447 while ( (int) items.count() > maxCount() && !items.isEmpty() )
448 items.remove( items.begin() );
449
450 insertItems( items );
451
452 if ( setCompletionList && useCompletion() ) {
453 // we don't have any weighting information here ;(
454 OCompletion *comp = completionObject();
455 comp->setOrder( OCompletion::Insertion );
456 comp->setItems( items );
457 comp->setOrder( OCompletion::Weighted );
458 }
459
460 clearEdit();
461}
462
463QStringList OHistoryCombo::historyItems() const
464{
465 QStringList list;
466 for ( int i = 0; i < count(); i++ )
467 list.append( text( i ) );
468
469 return list;
470}
471
472void OHistoryCombo::clearHistory()
473{
474 OComboBox::clear();
475 if ( useCompletion() )
476 completionObject()->clear();
477}
478
479void OHistoryCombo::addContextMenuItems( QPopupMenu* menu )
480{
481 if ( menu &&!lineEdit()->text().isEmpty())
482 {
483 menu->insertSeparator();
484 menu->insertItem( tr("Empty Contents"), this, SLOT( slotClear()));
485 }
486}
487
488void OHistoryCombo::addToHistory( const QString& item )
489{
490 if ( item.isEmpty() || (count() > 0 && item == text(0) ))
491 return;
492
493 // remove all existing items before adding
494 if ( !duplicatesEnabled() ) {
495 for ( int i = 0; i < count(); i++ ) {
496 if ( text( i ) == item )
497 removeItem( i );
498 }
499 }
500
501 // now add the item
502 if ( myPixProvider )
503 //insertItem( myPixProvider->pixmapFor(item, KIcon::SizeSmall), item, 0);
504 insertItem( myPixProvider->pixmapFor(item, 16), item, 0);
505 else
506 insertItem( item, 0 );
507
508 int last;
509 QString rmItem;
510
511 bool useComp = useCompletion();
512 while ( count() > maxCount() && count() > 0 ) {
513 // remove the last item, as long as we are longer than maxCount()
514 // remove the removed item from the completionObject if it isn't
515 // anymore available at all in the combobox.
516 last = count() - 1;
517 rmItem = text( last );
518 removeItem( last );
519 if ( useComp && !contains( rmItem ) )
520 completionObject()->removeItem( rmItem );
521 }
522
523 if ( useComp )
524 completionObject()->addItem( item );
525}
526
527bool OHistoryCombo::removeFromHistory( const QString& item )
528{
529 if ( item.isEmpty() )
530 return false;
531
532 bool removed = false;
533 QString temp = currentText();
534 for ( int i = 0; i < count(); i++ ) {
535 while ( item == text( i ) ) {
536 removed = true;
537 removeItem( i );
538 }
539 }
540
541 if ( removed && useCompletion() )
542 completionObject()->removeItem( item );
543
544 setEditText( temp );
545 return removed;
546}
547
548void OHistoryCombo::keyPressEvent( QKeyEvent *e )
549{
550 // save the current text in the lineedit
551 if ( myIterateIndex == -1 )
552 myText = currentText();
553
554 // going up in the history, rotating when reaching QListBox::count()
555 //if ( OStdAccel::isEqual( e, OStdAccel::rotateUp() ) ) {
556 if ( e->key() == Qt::Key_Up ) {
557 myIterateIndex++;
558
559 // skip duplicates/empty items
560 while ( myIterateIndex < count()-1 &&
561 (currentText() == text( myIterateIndex ) ||
562 text( myIterateIndex ).isEmpty()) )
563 myIterateIndex++;
564
565 if ( myIterateIndex >= count() ) {
566 myRotated = true;
567 myIterateIndex = -1;
568
569 // if the typed text is the same as the first item, skip the first
570 if ( myText == text(0) )
571 myIterateIndex = 0;
572
573 setEditText( myText );
574 }
575 else
576 setEditText( text( myIterateIndex ));
577 }
578
579
580 // going down in the history, no rotation possible. Last item will be
581 // the text that was in the lineedit before Up was called.
582 //else if ( OStdAccel::isEqual( e, OStdAccel::rotateDown() ) ) {
583 else if ( e->key() == Qt::Key_Down ) {
584 myIterateIndex--;
585
586 // skip duplicates/empty items
587 while ( myIterateIndex >= 0 &&
588 (currentText() == text( myIterateIndex ) ||
589 text( myIterateIndex ).isEmpty()) )
590 myIterateIndex--;
591
592
593 if ( myIterateIndex < 0 ) {
594 if ( myRotated && myIterateIndex == -2 ) {
595 myRotated = false;
596 myIterateIndex = count() - 1;
597 setEditText( text(myIterateIndex) );
598 }
599 else { // bottom of history
600 if ( myIterateIndex == -2 ) {
601 qDebug( "ONotifyClient is not implemented yet." );
602 //ONotifyClient::event( ONotifyClient::notification,
603 // i18n("No further item in the history."));
604 }
605
606 myIterateIndex = -1;
607 if ( currentText() != myText )
608 setEditText( myText );
609 }
610 }
611 else
612 setEditText( text( myIterateIndex ));
613 }
614
615 else
616 OComboBox::keyPressEvent( e );
617}
618
619void OHistoryCombo::slotReset()
620{
621 myIterateIndex = -1;
622 myRotated = false;
623}
624
625
626void OHistoryCombo::setPixmapProvider( OPixmapProvider *prov )
627{
628 if ( myPixProvider == prov )
629 return;
630
631 delete myPixProvider;
632 myPixProvider = prov;
633
634 // re-insert all the items with/without pixmap
635 // I would prefer to use changeItem(), but that doesn't honour the pixmap
636 // when using an editable combobox (what we do)
637 if ( count() > 0 ) {
638 QStringList items( historyItems() );
639 clear();
640 insertItems( items );
641 }
642}
643
644void OHistoryCombo::insertItems( const QStringList& items )
645{
646 QStringList::ConstIterator it = items.begin();
647 QString item;
648 while ( it != items.end() ) {
649 item = *it;
650 if ( !item.isEmpty() ) { // only insert non-empty items
651 if ( myPixProvider )
652 // insertItem( myPixProvider->pixmapFor(item, OIcon::SizeSmall), item );
653 insertItem( myPixProvider->pixmapFor(item, 16), item );
654 else
655 insertItem( item );
656 }
657 ++it;
658 }
659}
660
661void OHistoryCombo::slotClear()
662{
663 clearHistory();
664 emit cleared();
665}
666
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 @@
1/*
2 This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
3 is part of the Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
4 Opie Project Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
5
6 =. Originally part of the KDE projects
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33#ifndef OCOMBOBOX_H
34#define OCOMBOBOX_H
35
36/* QT */
37
38#include <qcombobox.h>
39
40/* OPIE */
41
42#include <opie2/olineedit.h>
43#include <opie2/ocompletion.h>
44#include <opie2/ocompletionbase.h>
45
46/* FORWARDS */
47
48class QListBoxItem;
49class QPopupMenu;
50class OCompletionBox;
51typedef QString OURL;
52
53/**
54 * A combined button, line-edit and a popup list widget.
55 *
56 * @sect Detail
57 *
58 * This widget inherits from @ref QComboBox and implements
59 * the following additional functionalities: a completion
60 * object that provides both automatic and manual text
61 * completion as well as text rotation features, configurable
62 * key-bindings to activate these features, and a popup-menu
63 * item that can be used to allow the user to set text completion
64 * modes on the fly based on their preference.
65 *
66 * To support these new features OComboBox also emits a few
67 * more additional signals as well. The main ones are the
68 * @ref completion( const QString& ) and @ref textRotation( KeyBindingType )
69 * signals. The completion signal is intended to be connected to a slot
70 * that will assist the user in filling out the remaining text while
71 * the rotation signals is intended to be used to traverse through all
72 * possible matches whenever text completion results in multiple matches.
73 * The @ref returnPressed() and @ref returnPressed( const QString& )
74 * signal is emitted when the user presses the Enter/Return key.
75 *
76 * This widget by default creates a completion object when you invoke
77 * the @ref completionObject( bool ) member function for the first time
78 * or use @ref setCompletionObject( OCompletion*, bool ) to assign your
79 * own completion object. Additionally, to make this widget more functional,
80 * OComboBox will by default handle the text rotation and completion
81 * events internally whenever a completion object is created through either
82 * one of the methods mentioned above. If you do not need this functionality,
83 * simply use @ref OCompletionBase::setHandleSignals( bool ) or alternatively
84 * set the boolean parameter in the above methods to FALSE.
85 *
86 * The default key-bindings for completion and rotation is determined
87 * from the global settings in @ref OStdAccel. These values, however,
88 * can be overriden locally by invoking @ref OCompletionBase::setKeyBinding().
89 * The values can easily be reverted back to the default setting, by simply
90 * calling @ref useGlobalSettings(). An alternate method would be to default
91 * individual key-bindings by usning @ref setKeyBinding() with the default
92 * second argument.
93 *
94 * Note that if this widget is not editable ( i.e. select-only ), then only
95 * one completion mode, @p CompletionAuto, will work. All the other modes are
96 * simply ignored. The @p CompletionAuto mode in this case allows you to
97 * automatically select an item from the list by trying to match the pressed
98 * keycode with the first letter of the enteries in the combo box.
99 *
100 * @sect Useage
101 *
102 * To enable the basic completion feature:
103 *
104 * <pre>
105 * OComboBox *combo = new OComboBox( true, this, "mywidget" );
106 * OCompletion *comp = combo->completionObject();
107 * // Connect to the return pressed signal - optional
108 * connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
109 * </pre>
110 *
111 * To use your own completion object:
112 *
113 * <pre>
114 * OComboBox *combo = new OComboBox( this,"mywidget" );
115 * OURLCompletion *comp = new OURLCompletion();
116 * combo->setCompletionObject( comp );
117 * // Connect to the return pressed signal - optional
118 * connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
119 * </pre>
120 *
121 * Note that you have to either delete the allocated completion object
122 * when you don't need it anymore, or call
123 * setAutoDeleteCompletionObject( true );
124 *
125 * Miscellaneous function calls:
126 *
127 * <pre>
128 * // Tell the widget not to handle completion and rotation
129 * combo->setHandleSignals( false );
130 * // Set your own completion key for manual completions.
131 * combo->setKeyBinding( OCompletionBase::TextCompletion, Qt::End );
132 * // Hide the context (popup) menu
133 * combo->setContextMenuEnabled( false );
134 * // Temporarly disable signal emition
135 * combo->disableSignals();
136 * // Default the all key-bindings to their system-wide settings.
137 * combo->useGlobalKeyBindings();
138 * </pre>
139 *
140 * @short An enhanced combo box.
141 * @author Dawit Alemayehu <adawit@kde.org>
142 */
143class OComboBox : public QComboBox, public OCompletionBase
144{
145 Q_OBJECT
146
147 //Q_PROPERTY( bool autoCompletion READ autoCompletion WRITE setAutoCompletion )
148 //Q_PROPERTY( bool contextMenuEnabled READ isContextMenuEnabled WRITE setContextMenuEnabled )
149 //Q_PROPERTY( bool urlDropsEnabled READ isURLDropsEnabled WRITE setURLDropsEnabled )
150
151public:
152
153 /**
154 * Constructs a read-only or rather select-only combo box with a
155 * parent object and a name.
156 *
157 * @param parent The parent object of this widget
158 * @param name The name of this widget
159 */
160 OComboBox( QWidget *parent=0, const char *name=0 );
161
162 /**
163 * Constructs a "read-write" or "read-only" combo box depending on
164 * the value of the first argument( @p rw ) with a parent, a
165 * name.
166 *
167 * @param rw When @p true, widget will be editable.
168 * @param parent The parent object of this widget.
169 * @param name The name of this widget.
170 */
171 OComboBox( bool rw, QWidget *parent=0, const char *name=0 );
172
173 /**
174 * Destructor.
175 */
176 virtual ~OComboBox();
177
178 /**
179 * Sets @p url into the edit field of the combobox. It uses
180 * @ref OURL::prettyURL() so that the url is properly decoded for
181 * displaying.
182 */
183 //void setEditURL( const OURL& url );
184
185 /**
186 * Inserts @p url at position @p index into the combobox. The item will
187 * be appended if @p index is negative. @ref OURL::prettyURL() is used
188 * so that the url is properly decoded for displaying.
189 */
190 //void insertURL( const OURL& url, int index = -1 );
191
192 /**
193 * Inserts @p url with the pixmap &p pixmap at position @p index into
194 * the combobox. The item will be appended if @p index is negative.
195 * @ref OURL::prettyURL() is used so that the url is properly decoded
196 * for displaying.
197 */
198 //void insertURL( const QPixmap& pixmap, const OURL& url, int index = -1 );
199
200 /**
201 * Replaces the item at position @p index with @p url.
202 * @ref OURL::prettyURL() is used so that the url is properly decoded
203 * for displaying.
204 */
205 //void changeURL( const OURL& url, int index );
206
207 /**
208 * Replaces the item at position @p index with @p url and pixmap @p pixmap.
209 * @ref OURL::prettyURL() is used so that the url is properly decoded
210 * for displaying.
211 */
212 //void changeURL( const QPixmap& pixmap, const OURL& url, int index );
213
214 /**
215 * Returns the current cursor position.
216 *
217 * This method always returns a -1 if the combo-box is @em not
218 * editable (read-write).
219 *
220 * @return Current cursor position.
221 */
222 int cursorPosition() const { return ( lineEdit() ) ? lineEdit()->cursorPosition() : -1; }
223
224 /**
225 * Re-implemented from @ref QComboBox.
226 *
227 * If @p true, the completion mode will be set to automatic.
228 * Otherwise, it is defaulted to the global setting. This
229 * method has been replaced by the more comprehensive
230 * @ref setCompletionMode().
231 *
232 * @param autocomplete Flag to enable/disable automatic completion mode.
233 */
234 virtual void setAutoCompletion( bool autocomplete );
235
236 /**
237 * Re-implemented from QComboBox.
238 *
239 * Returns @p true if the current completion mode is set
240 * to automatic. See its more comprehensive replacement
241 * @ref completionMode().
242 *
243 * @return @p true when completion mode is automatic.
244 */
245 bool autoCompletion() const {
246 return completionMode() == OGlobalSettings::CompletionAuto;
247 }
248
249 /**
250 * Enables or disable the popup (context) menu.
251 *
252 * This method only works if this widget is editable, i.e.
253 * read-write and allows you to enable/disable the context
254 * menu. It does nothing if invoked for a none-editable
255 * combo-box. Note that by default the mode changer item
256 * is made visiable whenever the context menu is enabled.
257 * Use @ref hideModechanger() if you want to hide this
258 * item. Also by default, the context menu is created if
259 * this widget is editable. Call this function with the
260 * argument set to false to disable the popup menu.
261 *
262 * @param showMenu If @p true, show the context menu.
263 * @param showMode If @p true, show the mode changer.
264 */
265 virtual void setContextMenuEnabled( bool showMenu );
266
267 /**
268 * Returns @p true when the context menu is enabled.
269 */
270 bool isContextMenuEnabled() const { return m_bEnableMenu; }
271
272 /**
273 * Enables/Disables handling of URL drops. If enabled and the user
274 * drops an URL, the decoded URL will be inserted. Otherwise the default
275 * behaviour of QComboBox is used, which inserts the encoded URL.
276 *
277 * @param enable If @p true, insert decoded URLs
278 */
279 //void setURLDropsEnabled( bool enable );
280
281 /**
282 * Returns @p true when decoded URL drops are enabled
283 */
284 //bool isURLDropsEnabled() const;
285
286 /**
287 * Convenience method which iterates over all items and checks if
288 * any of them is equal to @p text.
289 *
290 * If @p text is an empty string, @p false
291 * is returned.
292 *
293 * @return @p true if an item with the string @p text is in the combobox.
294 */
295 bool contains( const QString& text ) const;
296
297 /**
298 * By default, OComboBox recognizes Key_Return and Key_Enter
299 * and emits
300 * the @ref returnPressed() signals, but it also lets the event pass,
301 * for example causing a dialog's default-button to be called.
302 *
303 * Call this method with @p trap equal to true to make OComboBox
304 * stop these
305 * events. The signals will still be emitted of course.
306 *
307 * Only affects read-writable comboboxes.
308 *
309 * @see setTrapReturnKey()
310 */
311 void setTrapReturnKey( bool trap );
312
313 /**
314 * @return @p true if keyevents of Key_Return or Key_Enter will
315 * be stopped or if they will be propagated.
316 *
317 * @see setTrapReturnKey ()
318 */
319 bool trapReturnKey() const;
320
321 /**
322 * Re-implemented for internal reasons. API not affected.
323 *
324 * @reimplemented
325 */
326 virtual bool eventFilter( QObject *, QEvent * );
327
328 /**
329 * @returns the completion-box, that is used in completion mode
330 * @ref OGlobalSettings::CompletionPopup and @ref OGlobalSettings::CompletionPopupAuto.
331 * This method will create a completion-box by calling
332 * @ref OLineEdit::completionBox, if none is there, yet.
333 *
334 * @param create Set this to false if you don't want the box to be created
335 * i.e. to test if it is available.
336 */
337 OCompletionBox * completionBox( bool create = true );
338
339 virtual void setLineEdit( OLineEdit * );
340
341signals:
342 /**
343 * Emitted when the user presses the Enter key.
344 *
345 * Note that this signal is only
346 * emitted if this widget is editable.
347 */
348 void returnPressed();
349
350 /**
351 * Emitted when the user presses
352 * the Enter key.
353 *
354 * The argument is the current
355 * text being edited. This signal is just like
356 * @ref returnPressed() except it contains the
357 * current text as its argument.
358 *
359 * Note that this signal is only emitted if this
360 * widget is editable.
361 */
362 void returnPressed( const QString& );
363
364 /**
365 * This signal is emitted when the completion key
366 * is pressed.
367 *
368 * The argument is the current text
369 * being edited.
370 *
371 * Note that this signal is @em not available if this
372 * widget is non-editable or the completion mode is
373 * set to @p OGlobalSettings::CompletionNone.
374 */
375 void completion( const QString& );
376
377 /**
378 * Emitted when the shortcut for substring completion is pressed.
379 */
380 void substringCompletion( const QString& );
381
382 /**
383 * Emitted when the text rotation key-bindings are pressed.
384 *
385 * The argument indicates which key-binding was pressed.
386 * In this case this can be either one of four values:
387 * @p PrevCompletionMatch, @p NextCompletionMatch, @p RotateUp or
388 * @p RotateDown. See @ref OCompletionBase::setKeyBinding() for
389 * details.
390 *
391 * Note that this signal is @em NOT emitted if the completion
392 * mode is set to CompletionNone.
393 */
394 void textRotation( OCompletionBase::KeyBindingType );
395
396 /**
397 * Emitted when the user changed the completion mode by using the
398 * popupmenu.
399 */
400 void completionModeChanged( OGlobalSettings::Completion );
401
402 /**
403 * Emitted before the context menu is displayed.
404 *
405 * The signal allows you to add your own entries into the
406 * the context menu that is created on demand.
407 *
408 * NOTE: Do not store the pointer to the QPopupMenu
409 * provided through since it is created and deleted
410 * on demand.
411 *
412 * @param the context menu about to be displayed
413 */
414 void aboutToShowContextMenu( QPopupMenu * );
415
416public slots:
417
418 /**
419 * Iterates through all possible matches of the completed text
420 * or the history list.
421 *
422 * Depending on the value of the argument, this function either
423 * iterates through the history list of this widget or the all
424 * possible matches in whenever multiple matches result from a
425 * text completion request. Note that the all-possible-match
426 * iteration will not work if there are no previous matches, i.e.
427 * no text has been completed and the *nix shell history list
428 * rotation is only available if the insertion policy for this
429 * widget is set either @p QComobBox::AtTop or @p QComboBox::AtBottom.
430 * For other insertion modes whatever has been typed by the user
431 * when the rotation event was initiated will be lost.
432 *
433 * @param type The key-binding invoked.
434 */
435 void rotateText( OCompletionBase::KeyBindingType /* type */ );
436
437 /**
438 * Sets the completed text in the line-edit appropriately.
439 *
440 * This function is an implementation for
441 * @ref OCompletionBase::setCompletedText.
442 */
443 virtual void setCompletedText( const QString& );
444
445 /**
446 * Sets @p items into the completion-box if @ref completionMode() is
447 * CompletionPopup. The popup will be shown immediately.
448 */
449 void setCompletedItems( const QStringList& items );
450
451 public:
452 /**
453 * Selects the first item that matches @p item. If there is no such item,
454 * it is inserted at position @p index if @p insert is true. Otherwise,
455 * no item is selected.
456 */
457 void setCurrentItem( const QString& item, bool insert = false, int index = -1 );
458 void setCurrentItem(int index);
459
460protected slots:
461
462 /**
463 * @deprecated.
464 */
465 virtual void itemSelected( QListBoxItem* ) {};
466
467 /**
468 * Completes text according to the completion mode.
469 *
470 * Note: this method is @p not invoked if the completion mode is
471 * set to CompletionNone. Also if the mode is set to @p CompletionShell
472 * and multiple matches are found, this method will complete the
473 * text to the first match with a beep to inidicate that there are
474 * more matches. Then any successive completion key event iterates
475 * through the remaining matches. This way the rotation functionality
476 * is left to iterate through the list as usual.
477 */
478 virtual void makeCompletion( const QString& );
479
480protected:
481 /*
482 * This function simply sets the lineedit text and
483 * highlights the text appropriately if the boolean
484 * value is set to true.
485 *
486 * @param
487 * @param
488 */
489 virtual void setCompletedText( const QString& /* */, bool /*marked*/ );
490
491 /**
492 * Reimplemented for internal reasons, the API is not affected.
493 */
494 virtual void create( WId = 0, bool initializeWindow = true,
495 bool destroyOldWindow = true );
496
497private:
498 // Constants that represent the ID's of the popup menu.
499 // TODO: See if we can replace this mess with OActionMenu
500 // in the future though this is working lovely.
501 enum MenuID {
502 Default=0,
503 Cut,
504 Copy,
505 Paste,
506 Clear,
507 Unselect,
508 SelectAll,
509 NoCompletion,
510 AutoCompletion,
511 ShellCompletion,
512 PopupCompletion,
513 SemiAutoCompletion
514 };
515
516 /**
517 * Initializes the variables upon construction.
518 */
519 void init();
520 /**
521 * Temporary functions to delete words back and foward until
522 * alternatives are available in QT3 (Seth Chaiklin, 21 may 2001)
523 */
524 void deleteWordBack();
525 void deleteWordForward();
526
527 bool m_bEnableMenu;
528
529 // indicating if we should stop return-key events from propagating
530 bool m_trapReturnKey;
531
532//protected:
533// virtual void virtual_hook( int id, void* data );
534private:
535 class OComboBoxPrivate;
536 OComboBoxPrivate *d;
537};
538
539
540class OPixmapProvider;
541
542/**
543 * A combobox which implements a history like a unix shell. You can navigate
544 * through all the items by using the Up or Down arrows (configurable of
545 * course). Additionally, weighted completion is available. So you should
546 * load and save the completion list to preserve the weighting between
547 * sessions.
548 *
549 * @author Carsten Pfeiffer <pfeiffer@kde.org>
550 * @short A combobox for offering a history and completion
551 */
552class OHistoryCombo : public OComboBox
553{
554 Q_OBJECT
555 Q_PROPERTY( QStringList historyItems READ historyItems WRITE setHistoryItems )
556
557public:
558 /**
559 * Constructs a "read-write" combobox. A read-only history combobox
560 * doesn't make much sense, so it is only available as read-write.
561 * Completion will be used automatically for the items in the combo.
562 *
563 * The insertion-policy is set to NoInsertion, you have to add the items
564 * yourself via the slot @ref addToHistory. If you want every item added,
565 * use
566 *
567 * <pre>
568 * connect( combo, SIGNAL( activated( const QString& )),
569 * combo, SLOT( addToHistory( const QString& )));
570 * </pre>
571 *
572 * Use @ref QComboBox::setMaxCount() to limit the history.
573 *
574 * @p parent the parent object of this widget.
575 * @p name the name of this widget.
576 */
577 OHistoryCombo( QWidget *parent = 0L, const char *name = 0L );
578
579 // ### merge these two constructors
580 /**
581 * Same as the previous constructor, but additionally has the option
582 * to specify whether you want to let OHistoryCombo handle completion
583 * or not. If set to @p true, OHistoryCombo will sync the completion to the
584 * contents of the combobox.
585 */
586 OHistoryCombo( bool useCompletion,
587 QWidget *parent = 0L, const char *name = 0L );
588
589 /**
590 * Destructs the combo, the completion-object and the pixmap-provider
591 */
592 ~OHistoryCombo();
593
594 /**
595 * Inserts @p items into the combobox. @p items might get
596 * truncated if it is longer than @ref maxCount()
597 *
598 * @see #historyItems
599 */
600 inline void setHistoryItems( QStringList items ) {
601 setHistoryItems(items, false);
602 }
603
604 /**
605 * Inserts @p items into the combobox. @p items might get
606 * truncated if it is longer than @ref maxCount()
607 *
608 * Set @p setCompletionList to true, if you don't have a list of
609 * completions. This tells OHistoryCombo to use all the items for the
610 * completion object as well.
611 * You won't have the benefit of weighted completion though, so normally
612 * you should do something like
613 * <pre>
614 * OConfig *config = kapp->config();
615 * QStringList list;
616 *
617 * // load the history and completion list after creating the history combo
618 * list = config->readListEntry( "Completion list" );
619 * combo->completionObject()->setItems( list );
620 * list = config->readListEntry( "History list" );
621 * combo->setHistoryItems( list );
622 *
623 * [...]
624 *
625 * // save the history and completion list when the history combo is
626 * // destroyed
627 * list = combo->completionObject()->items()
628 * config->writeEntry( "Completion list", list );
629 * list = combo->historyItems();
630 * config->writeEntry( "History list", list );
631 * </pre>
632 *
633 * Be sure to use different names for saving with OConfig if you have more
634 * than one OHistoryCombo.
635 *
636 * Note: When @p setCompletionList is true, the items are inserted into the
637 * OCompletion object with mode OCompletion::Insertion and the mode is set
638 * to OCompletion::Weighted afterwards.
639 *
640 * @see #historyItems
641 * @see OComboBox::completionObject
642 * @see OCompletion::setItems
643 * @see OCompletion::items
644 */
645 void setHistoryItems( QStringList items, bool setCompletionList );
646
647 /**
648 * Returns the list of history items. Empty, when this is not a read-write
649 * combobox.
650 *
651 * @see #setHistoryItems
652 */
653 QStringList historyItems() const;
654
655 /**
656 * Removes all items named @p item.
657 *
658 * @return @p true if at least one item was removed.
659 *
660 * @see #addToHistory
661 */
662 bool removeFromHistory( const QString& item );
663
664 /**
665 * Sets a pixmap provider, so that items in the combobox can have a pixmap.
666 * @ref OPixmapProvider is just an abstract class with the one pure virtual
667 * method @ref OPixmapProvider::pixmapFor(). This method is called whenever
668 * an item is added to the OHistoryComboBox. Implement it to return your
669 * own custom pixmaps, or use the @ref OURLPixmapProvider from libkio,
670 * which uses @ref OMimeType::pixmapForURL to resolve icons.
671 *
672 * Set @p prov to 0L if you want to disable pixmaps. Default no pixmaps.
673 *
674 * @see #pixmapProvider
675 */
676 void setPixmapProvider( OPixmapProvider *prov );
677
678 /**
679 * @returns the current pixmap provider.
680 * @see #setPixmapProvider
681 * @see OPixmapProvider
682 */
683 OPixmapProvider * pixmapProvider() const { return myPixProvider; }
684
685 /**
686 * Resets the current position of the up/down history. Call this
687 * when you manually call @ref setCurrentItem() or @ref clearEdit().
688 */
689 void reset() { slotReset(); }
690
691public slots:
692 /**
693 * Adds an item to the end of the history list and to the completion list.
694 * If @ref maxCount() is reached, the first item of the list will be
695 * removed.
696 *
697 * If the last inserted item is the same as @p item, it will not be
698 * inserted again.
699 *
700 * If @ref duplicatesEnabled() is false, any equal existing item will be
701 * removed before @p item is added.
702 *
703 * Note: By using this method and not the Q and OComboBox insertItem()
704 * methods, you make sure that the combobox stays in sync with the
705 * completion. It would be annoying if completion would give an item
706 * not in the combobox, and vice versa.
707 *
708 * @see #removeFromHistory
709 * @see QComboBox::setDuplicatesEnabled
710 */
711 void addToHistory( const QString& item );
712
713 /**
714 * Clears the history and the completion list.
715 */
716 void clearHistory();
717
718signals:
719 /**
720 * Emitted when the history was cleared by the entry in the popup menu.
721 */
722 void cleared();
723
724protected:
725 /**
726 * Handling key-events, the shortcuts to rotate the items.
727 */
728 virtual void keyPressEvent( QKeyEvent * );
729
730
731 /**
732 * Inserts @p items into the combo, honouring @ref pixmapProvider()
733 * Does not update the completionObject.
734 *
735 * Note: @ref duplicatesEnabled() is not honored here.
736 *
737 * Called from @ref setHistoryItems() and @ref setPixmapProvider()
738 */
739 void insertItems( const QStringList& items );
740
741 /**
742 * @returns if we can modify the completion object or not.
743 */
744 bool useCompletion() const { return compObj() != 0L; }
745
746private slots:
747 /**
748 * Resets the iterate index to -1
749 */
750 void slotReset();
751
752 /**
753 * Called from the popupmenu,
754 * calls clearHistory() and emits cleared()
755 */
756 void slotClear();
757
758 /**
759 * Appends our own context menu entry.
760 */
761 void addContextMenuItems( QPopupMenu* );
762
763private:
764 void init( bool useCompletion );
765
766 /**
767 * The current position (index) in the combobox, used for Up and Down
768 */
769 int myIterateIndex;
770
771 /**
772 * The text typed before Up or Down was pressed.
773 */
774 QString myText;
775
776 /**
777 * Indicates that the user at least once rotated Up through the entire list
778 * Needed to allow going back after rotation.
779 */
780 bool myRotated;
781 OPixmapProvider *myPixProvider;
782
783private:
784 class OHistoryComboPrivate;
785 OHistoryComboPrivate *d;
786};
787
788
789#endif
790
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 @@
1/*
2 This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
3 is part of the Copyright (C) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
4 Opie Project Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de>
5 Copyright (C) 2000,2001 Dawit Alemayehu <adawit@kde.org>
6 =.
7 .=l. Originally part of the KDE Project
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33#include <qapplication.h>
34#include <qevent.h>
35#include <qstyle.h>
36
37#include <opie2/ocompletionbox.h>
38
39#define OListBox QListBox
40
41class OCompletionBox::OCompletionBoxPrivate
42{
43public:
44 QWidget *m_parent; // necessary to set the focus back
45 QString cancelText;
46 bool tabHandling;
47 bool down_workaround;
48};
49
50OCompletionBox::OCompletionBox( QWidget *parent, const char *name )
51 :OListBox( parent, name, WType_Popup )
52{
53 d = new OCompletionBoxPrivate;
54 d->m_parent = parent;
55 d->tabHandling = true;
56 d->down_workaround = false;
57
58 setColumnMode( 1 );
59 setLineWidth( 1 );
60 setFrameStyle( QFrame::Box | QFrame::Plain );
61
62 if ( parent )
63 setFocusProxy( parent );
64 else
65 setFocusPolicy( NoFocus );
66
67 setVScrollBarMode( Auto );
68 setHScrollBarMode( AlwaysOff );
69
70 connect( this, SIGNAL( doubleClicked( QListBoxItem * )),
71 SLOT( slotActivated( QListBoxItem * )) );
72
73 // grmbl, just QListBox workarounds :[ Thanks Volker.
74 connect( this, SIGNAL( currentChanged( QListBoxItem * )),
75 SLOT( slotCurrentChanged() ));
76 connect( this, SIGNAL( clicked( QListBoxItem * )),
77 SLOT( slotItemClicked( QListBoxItem * )) );
78}
79
80OCompletionBox::~OCompletionBox()
81{
82 d->m_parent = 0L;
83 delete d;
84}
85
86QStringList OCompletionBox::items() const
87{
88 QStringList list;
89 for ( uint i = 0; i < count(); i++ ) {
90 list.append( text( i ) );
91 }
92 return list;
93}
94
95void OCompletionBox::slotActivated( QListBoxItem *item )
96{
97 if ( !item )
98 return;
99
100 hide();
101 emit activated( item->text() );
102}
103
104bool OCompletionBox::eventFilter( QObject *o, QEvent *e )
105{
106 int type = e->type();
107
108 if ( o == d->m_parent ) {
109 if ( isVisible() ) {
110 if ( type == QEvent::KeyPress ) {
111 QKeyEvent *ev = static_cast<QKeyEvent *>( e );
112 switch ( ev->key() ) {
113 case Key_BackTab:
114 if ( d->tabHandling ) {
115 up();
116 ev->accept();
117 return true;
118 }
119 break;
120 case Key_Tab:
121 if ( d->tabHandling ) {
122 down(); // Only on TAB!!
123 ev->accept();
124 return true;
125 }
126 break;
127 case Key_Down:
128 down();
129 ev->accept();
130 return true;
131 case Key_Up:
132 up();
133 ev->accept();
134 return true;
135 case Key_Prior:
136 pageUp();
137 ev->accept();
138 return true;
139 case Key_Next:
140 pageDown();
141 ev->accept();
142 return true;
143 case Key_Escape:
144 cancelled();
145 ev->accept();
146 return true;
147 case Key_Enter:
148 case Key_Return:
149 if ( ev->state() & ShiftButton ) {
150 hide();
151 ev->accept(); // Consume the Enter event
152 return true;
153 }
154 break;
155 default:
156 break;
157 }
158 }
159 else if ( type == QEvent::AccelOverride ) {
160 // Override any acceleartors that match
161 // the key sequences we use here...
162 QKeyEvent *ev = static_cast<QKeyEvent *>( e );
163 switch ( ev->key() ) {
164 case Key_Tab:
165 case Key_BackTab:
166 case Key_Down:
167 case Key_Up:
168 case Key_Prior:
169 case Key_Next:
170 case Key_Escape:
171 case Key_Enter:
172 case Key_Return:
173 ev->accept();
174 return true;
175 break;
176 default:
177 break;
178 }
179 }
180
181 // parent loses focus or gets a click -> we hide
182 else if ( type == QEvent::FocusOut || type == QEvent::Resize ||
183 type == QEvent::Close || type == QEvent::Hide ||
184 type == QEvent::Move ) {
185 hide();
186 }
187 else if ( type == QEvent::Move )
188 move( d->m_parent->mapToGlobal(QPoint(0, d->m_parent->height())));
189 else if ( type == QEvent::Resize )
190 resize( sizeHint() );
191 }
192 }
193
194 // any mouse-click on something else than "this" makes us hide
195 else if ( type == QEvent::MouseButtonPress ) {
196 QMouseEvent *ev = static_cast<QMouseEvent *>( e );
197 if ( !rect().contains( ev->pos() )) // this widget
198 hide();
199 }
200
201 return OListBox::eventFilter( o, e );
202}
203
204
205void OCompletionBox::popup()
206{
207 if ( count() == 0 )
208 hide();
209 else {
210 ensureCurrentVisible();
211 bool block = signalsBlocked();
212 blockSignals( true );
213 setCurrentItem( 0 );
214 blockSignals( block );
215 clearSelection();
216 if ( !isVisible() )
217 show();
218 else if ( size().height() < sizeHint().height() )
219 resize( sizeHint() );
220 }
221}
222
223void OCompletionBox::show()
224{
225 resize( sizeHint() );
226
227 if ( d->m_parent )
228 {
229 //QDesktopWidget *screen = QApplication::desktop();
230 QWidget *screen = QApplication::desktop();
231
232 QPoint orig = d->m_parent->mapToGlobal( QPoint(0, d->m_parent->height()) );
233 int x = orig.x();
234 int y = orig.y();
235
236 if ( x + width() > screen->width() )
237 x = screen->width() - width();
238 if (y + height() > screen->height() )
239 y = y - height() - d->m_parent->height();
240
241 move( x, y);
242 qApp->installEventFilter( this );
243 }
244
245 // ### we shouldn't need to call this, but without this, the scrollbars
246 // are pretty b0rked.
247 //triggerUpdate( true );
248
249 OListBox::show();
250}
251
252void OCompletionBox::hide()
253{
254 if ( d->m_parent )
255 qApp->removeEventFilter( this );
256 d->cancelText = QString::null;
257 OListBox::hide();
258}
259
260QSize OCompletionBox::sizeHint() const
261{
262 int ih = itemHeight();
263 int h = QMIN( 15 * ih, (int) count() * ih ) +1;
264 h = QMAX( h, OListBox::minimumSizeHint().height() );
265
266 int w = (d->m_parent) ? d->m_parent->width() : OListBox::minimumSizeHint().width();
267 w = QMAX( OListBox::minimumSizeHint().width(), w );
268 return QSize( w, h );
269}
270
271void OCompletionBox::down()
272{
273 int i = currentItem();
274
275 if ( i == 0 && d->down_workaround ) {
276 d->down_workaround = false;
277 setCurrentItem( 0 );
278 setSelected( 0, true );
279 emit highlighted( currentText() );
280 }
281
282 else if ( i < (int) count() - 1 )
283 setCurrentItem( i + 1 );
284}
285
286void OCompletionBox::up()
287{
288 if ( currentItem() > 0 )
289 setCurrentItem( currentItem() - 1 );
290}
291
292void OCompletionBox::pageDown()
293{
294 int i = currentItem() + numItemsVisible();
295 i = i > (int)count() - 1 ? (int)count() - 1 : i;
296 setCurrentItem( i );
297}
298
299void OCompletionBox::pageUp()
300{
301 int i = currentItem() - numItemsVisible();
302 i = i < 0 ? 0 : i;
303 setCurrentItem( i );
304}
305
306void OCompletionBox::home()
307{
308 setCurrentItem( 0 );
309}
310
311void OCompletionBox::end()
312{
313 setCurrentItem( count() -1 );
314}
315
316void OCompletionBox::setTabHandling( bool enable )
317{
318 d->tabHandling = enable;
319}
320
321bool OCompletionBox::isTabHandling() const
322{
323 return d->tabHandling;
324}
325
326void OCompletionBox::setCancelledText( const QString& text )
327{
328 d->cancelText = text;
329}
330
331QString OCompletionBox::cancelledText() const
332{
333 return d->cancelText;
334}
335
336void OCompletionBox::cancelled()
337{
338 if ( !d->cancelText.isNull() )
339 emit userCancelled( d->cancelText );
340 if ( isVisible() )
341 hide();
342}
343
344class OCompletionBoxItem : public QListBoxItem
345{
346public:
347 void reuse( const QString &text ) { setText( text ); }
348};
349
350
351void OCompletionBox::insertItems( const QStringList& items, int index )
352{
353 bool block = signalsBlocked();
354 blockSignals( true );
355 insertStringList( items, index );
356 blockSignals( block );
357 d->down_workaround = true;
358}
359
360void OCompletionBox::setItems( const QStringList& items )
361{
362 bool block = signalsBlocked();
363 blockSignals( true );
364
365 QListBoxItem* item = firstItem();
366 if ( !item ) {
367 insertStringList( items );
368 }
369 else {
370 for ( QStringList::ConstIterator it = items.begin(); it != items.end(); it++) {
371 if ( item ) {
372 ((OCompletionBoxItem*)item)->reuse( *it );
373 item = item->next();
374 }
375 else {
376 insertItem( new QListBoxText( *it ) );
377 }
378 }
379 QListBoxItem* tmp = item;
380 while ( (item = tmp ) ) {
381 tmp = item->next();
382 delete item;
383 }
384 triggerUpdate( false );
385 }
386
387 blockSignals( block );
388 d->down_workaround = true;
389}
390
391void OCompletionBox::slotCurrentChanged()
392{
393 d->down_workaround = false;
394}
395
396void OCompletionBox::slotItemClicked( QListBoxItem *item )
397{
398 if ( item )
399 {
400 if ( d->down_workaround ) {
401 d->down_workaround = false;
402 emit highlighted( item->text() );
403 }
404
405 hide();
406 emit activated( item->text() );
407 }
408}
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 @@
1/*
2 This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
3 is part of the Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
4 Opie Project Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de>
5
6 =. Originally part of the KDE Project
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33#ifndef OCOMPLETIONBOX_H
34#define OCOMPLETIONBOX_H
35
36class QEvent;
37#include <qstringlist.h>
38#include <qlistbox.h>
39
40// ML: Until we don't have an own OListBox, we use the QListBox
41#define OListBox QListBox
42
43/**
44 * A little utility class for "completion-widgets", like @ref OLineEdit or
45 * @ref OComboBox. OCompletionBox is a listbox, displayed as a rectangle without
46 * any window decoration, usually directly under the lineedit or combobox.
47 * It is filled with all possible matches for a completion, so the user
48 * can select the one he wants.
49 *
50 * It is used when OGlobalSettings::Completion == CompletionPopup or CompletionPopupAuto.
51 *
52 * @short A helper widget for "completion-widgets" (OLineEdit, OComboBox))
53 * @short Adapted for the Opie project by Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
54 * @author Carsten Pfeiffer <pfeiffer@kde.org>
55 *
56 */
57class OCompletionBox : public OListBox
58{
59 Q_OBJECT
60 Q_PROPERTY( bool isTabHandling READ isTabHandling WRITE setTabHandling )
61 Q_PROPERTY(QString cancelledText READ cancelledText WRITE setCancelledText)
62
63public:
64 /**
65 * Constructs a OCompletionBox.
66 *
67 * Notice: the parent needs to be always 0L,
68 * so you can't specify it in the constructor. Because of that, Qt's
69 * auto-deletion does not take place, so you have to explicitly delete
70 * this widget when you don't need it anymore.
71 *
72 * The parent widget is used to give the focus back when pressing the
73 * up-button on the very first item.
74 */
75 OCompletionBox( QWidget *parent, const char *name = 0 );
76
77 /**
78 * Destroys the box
79 */
80 ~OCompletionBox();
81
82 virtual QSize sizeHint() const;
83
84public slots:
85 /**
86 * Returns a list of all items currently in the box.
87 */
88 QStringList items() const;
89
90 /**
91 * Inserts @p items into the box. Does not clear the items before.
92 * @p index determines at which position @p items will be inserted.
93 * (defaults to appending them at the end)
94 */
95 void insertItems( const QStringList& items, int index = -1 );
96
97 /**
98 * Clears the box and inserts @p items.
99 */
100 void setItems( const QStringList& items );
101
102 /**
103 * Adjusts the size of the box to fit the width of the parent given in the
104 * constructor and pops it up at the most appropriate place, relative to
105 * the parent.
106 *
107 * Depending on the screensize and the position of the parent, this may
108 * be a different place, however the default is to pop it up and the
109 * lower left corner of the parent.
110 *
111 * Make sure to hide() the box when appropriate.
112 */
113 virtual void popup();
114
115 /**
116 * Makes this widget (when visible) capture Tab-key events to traverse the
117 * items in the dropdown list.
118 *
119 * Default off, as it conflicts with the usual behavior of Tab to traverse
120 * widgets. It is useful for cases like Konqueror's Location Bar, though.
121 *
122 * @see #isTabHandling
123 */
124 void setTabHandling( bool enable );
125
126 /**
127 * @returns true if this widget is handling Tab-key events to traverse the
128 * items in the dropdown list, otherwise false.
129 *
130 * Default is false.
131 *
132 * @see #setTabHandling
133 */
134 bool isTabHandling() const;
135
136 /**
137 * Sets the text to be emitted if the user chooses not to
138 * pick from the available matches.
139 *
140 * If the cancelled text is not set through this function, the
141 * @ref userCancelled signal will not be emitted.
142 *
143 * @see userCancelled( const QString& )
144 * @param txt the text to be emitted if the user cancels this box
145 */
146 void setCancelledText( const QString& );
147
148 /**
149 * @returns the text set via @ref setCancelledText() or QString::null.
150 */
151 QString cancelledText() const;
152
153 /**
154 * Moves the selection one line down or select the first item if nothing is selected yet.
155 */
156 void down();
157
158 /**
159 * Moves the selection one line up or select the first item if nothing is selected yet.
160 */
161 void up();
162
163 /**
164 * Moves the selection one page down.
165 */
166 void pageDown();
167
168 /**
169 * Moves the selection one page up.
170 */
171 void pageUp();
172
173 /**
174 * Moves the selection up to the first item.
175 */
176 void home();
177
178 /**
179 * Moves the selection down to the last item.
180 */
181 void end();
182
183 /**
184 * Re-implemented for internal reasons. API is unaffected.
185 */
186 virtual void show();
187
188 /**
189 * Re-implemented for internal reasons. API is unaffected.
190 */
191 virtual void hide();
192
193signals:
194 /**
195 * Emitted when an item was selected, contains the text of
196 * the selected item.
197 */
198 void activated( const QString& );
199
200 /**
201 * Emitted whenever the user chooses to ignore the available
202 * selections and close the this box.
203 */
204 void userCancelled( const QString& );
205
206protected:
207 /**
208 * Reimplemented from OListBox to get events from the viewport (to hide
209 * this widget on mouse-click, Escape-presses, etc.
210 */
211 virtual bool eventFilter( QObject *, QEvent * );
212
213protected slots:
214 /**
215 * Called when an item was activated. Emits
216 * @ref activated() with the item.
217 */
218 virtual void slotActivated( QListBoxItem * );
219
220private slots:
221 void slotSetCurrentItem( QListBoxItem *i ) { setCurrentItem( i ); } // grrr
222 void slotCurrentChanged();
223 void cancelled();
224 void slotItemClicked( QListBoxItem * );
225
226private:
227 class OCompletionBoxPrivate;
228 OCompletionBoxPrivate* d;
229};
230
231
232#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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org>
3 2000, 2002 Carsten Pfeiffer <pfeiffer@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/* QT */
22
23#include <qstringlist.h>
24#include <qpushbutton.h>
25#include <qlayout.h>
26#include <qgroupbox.h>
27#include <qlistbox.h>
28#include <qwhatsthis.h>
29#include <qlabel.h>
30
31/* OPIE */
32
33#include <opie2/ocombobox.h>
34#include <opie2/odialog.h>
35#include <opie2/olineedit.h>
36#include <opie2/oeditlistbox.h>
37
38/* UNIX */
39
40#include <assert.h>
41
42/*======================================================================================
43 * OEditListBoxPrivate
44 *======================================================================================*/
45
46class OEditListBoxPrivate
47{
48public:
49 bool m_checkAtEntering;
50 int buttons;
51};
52
53/*======================================================================================
54 * OEditListBox
55 *======================================================================================*/
56
57OEditListBox::OEditListBox(QWidget *parent, const char *name,
58 bool checkAtEntering, int buttons )
59 :QGroupBox(parent, name )
60{
61 init( checkAtEntering, buttons );
62}
63
64OEditListBox::OEditListBox(const QString& title, QWidget *parent,
65 const char *name, bool checkAtEntering, int buttons)
66 :QGroupBox(title, parent, name )
67{
68 init( checkAtEntering, buttons );
69}
70
71OEditListBox::OEditListBox(const QString& title, const CustomEditor& custom,
72 QWidget *parent, const char *name,
73 bool checkAtEntering, int buttons)
74 :QGroupBox(title, parent, name )
75{
76 m_lineEdit = custom.lineEdit();
77 init( checkAtEntering, buttons, custom.representationWidget() );
78}
79
80OEditListBox::~OEditListBox()
81{
82 delete d;
83 d=0;
84}
85
86void OEditListBox::init( bool checkAtEntering, int buttons,
87 QWidget *representationWidget )
88{
89 d=new OEditListBoxPrivate;
90 d->m_checkAtEntering=checkAtEntering;
91 d->buttons = buttons;
92
93 int lostButtons = 0;
94 if ( (buttons & Add) == 0 )
95 lostButtons++;
96 if ( (buttons & Remove) == 0 )
97 lostButtons++;
98 if ( (buttons & UpDown) == 0 )
99 lostButtons += 2;
100
101
102 servNewButton = servRemoveButton = servUpButton = servDownButton = 0L;
103 setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,
104 QSizePolicy::MinimumExpanding));
105
106 QWidget * gb = this;
107 QGridLayout * grid = new QGridLayout(gb, 7 - lostButtons, 2,
108 ODialog::marginHint(),
109 ODialog::spacingHint());
110 grid->addRowSpacing(0, fontMetrics().lineSpacing());
111 for ( int i = 1; i < 7 - lostButtons; i++ )
112 grid->setRowStretch(i, 1);
113
114 grid->setMargin(15);
115
116 if ( representationWidget )
117 representationWidget->reparent( gb, QPoint(0,0) );
118 else
119 m_lineEdit=new OLineEdit(gb);
120
121 m_listBox = new QListBox(gb);
122
123 QWidget *editingWidget = representationWidget ?
124 representationWidget : m_lineEdit;
125 grid->addMultiCellWidget(editingWidget,1,1,0,1);
126 grid->addMultiCellWidget(m_listBox, 2, 6 - lostButtons, 0, 0);
127 int row = 2;
128 if ( buttons & Add ) {
129 servNewButton = new QPushButton(tr("&Add"), gb);
130 servNewButton->setEnabled(false);
131 connect(servNewButton, SIGNAL(clicked()), SLOT(addItem()));
132
133 grid->addWidget(servNewButton, row++, 1);
134 }
135
136 if ( buttons & Remove ) {
137 servRemoveButton = new QPushButton(tr("&Remove"), gb);
138 servRemoveButton->setEnabled(false);
139 connect(servRemoveButton, SIGNAL(clicked()), SLOT(removeItem()));
140
141 grid->addWidget(servRemoveButton, row++, 1);
142 }
143
144 if ( buttons & UpDown ) {
145 servUpButton = new QPushButton(tr("Move &Up"), gb);
146 servUpButton->setEnabled(false);
147 connect(servUpButton, SIGNAL(clicked()), SLOT(moveItemUp()));
148
149 servDownButton = new QPushButton(tr("Move &Down"), gb);
150 servDownButton->setEnabled(false);
151 connect(servDownButton, SIGNAL(clicked()), SLOT(moveItemDown()));
152
153 grid->addWidget(servUpButton, row++, 1);
154 grid->addWidget(servDownButton, row++, 1);
155 }
156
157 connect(m_lineEdit,SIGNAL(textChanged(const QString&)),this,SLOT(typedSomething(const QString&)));
158 m_lineEdit->setTrapReturnKey(true);
159 connect(m_lineEdit,SIGNAL(returnPressed()),this,SLOT(addItem()));
160 connect(m_listBox, SIGNAL(highlighted(int)), SLOT(enableMoveButtons(int)));
161
162 // maybe supplied lineedit has some text already
163 typedSomething( m_lineEdit->text() );
164}
165
166void OEditListBox::typedSomething(const QString& text)
167{
168 if(currentItem() >= 0) {
169 if(currentText() != m_lineEdit->text())
170 {
171 // IMHO changeItem() shouldn't do anything with the value
172 // of currentItem() ... like changing it or emitting signals ...
173 // but TT disagree with me on this one (it's been that way since ages ... grrr)
174 bool block = m_listBox->signalsBlocked();
175 m_listBox->blockSignals( true );
176 m_listBox->changeItem(text, currentItem());
177 m_listBox->blockSignals( block );
178 emit changed();
179 }
180 }
181
182 if ( !servNewButton )
183 return;
184
185 if (!d->m_checkAtEntering)
186 servNewButton->setEnabled(!text.isEmpty());
187 else
188 {
189 if (text.isEmpty())
190 {
191 servNewButton->setEnabled(false);
192 }
193 else
194 {
195 #if QT_VERSION > 290
196 StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive );
197 bool enable = (m_listBox->findItem( text, mode ) == 0L);
198 #else
199 bool enable = (m_listBox->findItem( text ) == 0L);
200 #endif
201 servNewButton->setEnabled( enable );
202 }
203 }
204}
205
206void OEditListBox::moveItemUp()
207{
208 if (!m_listBox->isEnabled())
209 {
210 //ONotifyClient::beep();
211 return;
212 }
213
214 unsigned int selIndex = m_listBox->currentItem();
215 if (selIndex == 0)
216 {
217 //ONotifyClient::beep();
218 return;
219 }
220
221 QListBoxItem *selItem = m_listBox->item(selIndex);
222 m_listBox->takeItem(selItem);
223 m_listBox->insertItem(selItem, selIndex-1);
224 m_listBox->setCurrentItem(selIndex - 1);
225
226 emit changed();
227}
228
229void OEditListBox::moveItemDown()
230{
231 if (!m_listBox->isEnabled())
232 {
233 //ONotifyClient::beep();
234 return;
235 }
236
237 unsigned int selIndex = m_listBox->currentItem();
238 if (selIndex == m_listBox->count() - 1)
239 {
240 //ONotifyClient::beep();
241 return;
242 }
243
244 QListBoxItem *selItem = m_listBox->item(selIndex);
245 m_listBox->takeItem(selItem);
246 m_listBox->insertItem(selItem, selIndex+1);
247 m_listBox->setCurrentItem(selIndex + 1);
248
249 emit changed();
250}
251
252void OEditListBox::addItem()
253{
254 // when m_checkAtEntering is true, the add-button is disabled, but this
255 // slot can still be called through Key_Return/Key_Enter. So we guard
256 // against this.
257 if ( !servNewButton || !servNewButton->isEnabled() )
258 return;
259
260 const QString& currentTextLE=m_lineEdit->text();
261 bool alreadyInList(false);
262 //if we didn't check for dupes at the inserting we have to do it now
263 if (!d->m_checkAtEntering)
264 {
265 // first check current item instead of dumb iterating the entire list
266 if ( m_listBox->currentText() == currentTextLE )
267 alreadyInList = true;
268 else
269 {
270 #if QT_VERSION > 290
271 StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive );
272 alreadyInList =(m_listBox->findItem(currentTextLE, mode) != 0);
273 #else
274 alreadyInList =(m_listBox->findItem(currentTextLE) != 0);
275 #endif
276 }
277 }
278
279 if ( servNewButton )
280 servNewButton->setEnabled(false);
281
282 bool block = m_lineEdit->signalsBlocked();
283 m_lineEdit->blockSignals(true);
284 m_lineEdit->clear();
285 m_lineEdit->blockSignals(block);
286
287 m_listBox->setSelected(currentItem(), false);
288
289 if (!alreadyInList)
290 {
291 block = m_listBox->signalsBlocked();
292 m_listBox->blockSignals( true );
293 m_listBox->insertItem(currentTextLE);
294 m_listBox->blockSignals( block );
295 emit changed();
296 emit added( currentTextLE );
297 }
298}
299
300int OEditListBox::currentItem() const
301{
302 int nr = m_listBox->currentItem();
303 #if QT_VERSION > 290
304 if(nr >= 0 && !m_listBox->item(nr)->isSelected()) return -1;
305 #else
306 if(nr >= 0 && !m_listBox->isSelected(m_listBox->item(nr))) return -1;
307 #endif
308 return nr;
309}
310
311void OEditListBox::removeItem()
312{
313 int selected = m_listBox->currentItem();
314
315 if ( selected >= 0 )
316 {
317 QString removedText = m_listBox->currentText();
318
319 m_listBox->removeItem( selected );
320 if ( count() > 0 )
321 m_listBox->setSelected( QMIN( selected, count() - 1 ), true );
322
323 emit changed();
324 emit removed( removedText );
325 }
326
327 if ( servRemoveButton && m_listBox->currentItem() == -1 )
328 servRemoveButton->setEnabled(false);
329}
330
331void OEditListBox::enableMoveButtons(int index)
332{
333 // Update the lineEdit when we select a different line.
334 if(currentText() != m_lineEdit->text())
335 m_lineEdit->setText(currentText());
336
337 bool moveEnabled = servUpButton && servDownButton;
338
339 if (moveEnabled )
340 {
341 if (m_listBox->count() <= 1)
342 {
343 servUpButton->setEnabled(false);
344 servDownButton->setEnabled(false);
345 }
346 else if ((uint) index == (m_listBox->count() - 1))
347 {
348 servUpButton->setEnabled(true);
349 servDownButton->setEnabled(false);
350 }
351 else if (index == 0)
352 {
353 servUpButton->setEnabled(false);
354 servDownButton->setEnabled(true);
355 }
356 else
357 {
358 servUpButton->setEnabled(true);
359 servDownButton->setEnabled(true);
360 }
361 }
362
363 if ( servRemoveButton )
364 servRemoveButton->setEnabled(true);
365}
366
367void OEditListBox::clear()
368{
369 m_lineEdit->clear();
370 m_listBox->clear();
371 emit changed();
372}
373
374void OEditListBox::insertStringList(const QStringList& list, int index)
375{
376 m_listBox->insertStringList(list,index);
377}
378
379void OEditListBox::insertStrList(const QStrList* list, int index)
380{
381 m_listBox->insertStrList(list,index);
382}
383
384void OEditListBox::insertStrList(const QStrList& list, int index)
385{
386 m_listBox->insertStrList(list,index);
387}
388
389void OEditListBox::insertStrList(const char ** list, int numStrings, int index)
390{
391 m_listBox->insertStrList(list,numStrings,index);
392}
393
394QStringList OEditListBox::items() const
395{
396 QStringList list;
397 for ( uint i = 0; i < m_listBox->count(); i++ )
398 list.append( m_listBox->text( i ));
399
400 return list;
401}
402
403void OEditListBox::virtual_hook( int, void* )
404{ /*BASE::virtual_hook( id, data );*/ }
405
406
407/*======================================================================================
408 * CustomEditor
409 *======================================================================================*/
410
411OEditListBox::CustomEditor::CustomEditor( OComboBox *combo )
412{
413 m_representationWidget = combo;
414 m_lineEdit = dynamic_cast<OLineEdit*>( combo->lineEdit() );
415 assert( m_lineEdit );
416}
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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20#ifndef OEDITLISTBOX_H
21#define OEDITLISTBOX_H
22
23#include <qgroupbox.h>
24#include <qlistbox.h>
25
26class OLineEdit;
27class OComboBox;
28class QPushButton;
29
30#if QT_VERSION < 300
31 enum StringComparisonMode {
32 CaseSensitive = 0x00001, // 0 0001
33 BeginsWith = 0x00002, // 0 0010
34 EndsWith = 0x00004, // 0 0100
35 Contains = 0x00008, // 0 1000
36 ExactMatch = 0x00010 // 1 0000
37 };
38#endif
39
40class OEditListBoxPrivate;
41/**
42 * An editable listbox
43 *
44 * This class provides a editable listbox ;-), this means
45 * a listbox which is accompanied by a line edit to enter new
46 * items into the listbox and pushbuttons to add and remove
47 * items from the listbox and two buttons to move items up and down.
48 */
49class OEditListBox : public QGroupBox
50{
51 Q_OBJECT
52
53public:
54 /// @since 3.1
55 class CustomEditor
56 {
57 public:
58 CustomEditor()
59 : m_representationWidget( 0L ),
60 m_lineEdit( 0L ) {}
61 CustomEditor( QWidget *repWidget, OLineEdit *edit )
62 : m_representationWidget( repWidget ),
63 m_lineEdit( edit ) {}
64 CustomEditor( OComboBox *combo );
65
66 void setRepresentationWidget( QWidget *repWidget ) {
67 m_representationWidget = repWidget;
68 }
69 void setLineEdit( OLineEdit *edit ) {
70 m_lineEdit = edit;
71 }
72
73 virtual QWidget *representationWidget() const {
74 return m_representationWidget;
75 }
76 virtual OLineEdit *lineEdit() const {
77 return m_lineEdit;
78 }
79
80 protected:
81 QWidget *m_representationWidget;
82 OLineEdit *m_lineEdit;
83 };
84
85 public:
86
87 /**
88 * Enumeration of the buttons, the listbox offers. Specify them in the
89 * constructor in the buttons parameter.
90 */
91 enum Button { Add = 1, Remove = 2, UpDown = 4, All = Add|Remove|UpDown };
92
93 /**
94 * Create an editable listbox.
95 *
96 * If @p checkAtEntering is true, after every character you type
97 * in the line edit OEditListBox will enable or disable
98 * the Add-button, depending whether the current content of the
99 * line edit is already in the listbox. Maybe this can become a
100 * performance hit with large lists on slow machines.
101 * If @p checkAtEntering is false,
102 * it will be checked if you press the Add-button. It is not
103 * possible to enter items twice into the listbox.
104 */
105 OEditListBox(QWidget *parent = 0, const char *name = 0,
106 bool checkAtEntering=false, int buttons = All );
107 /**
108 * Create an editable listbox.
109 *
110 * The same as the other constructor, additionally it takes
111 * @title, which will be the title of the frame around the listbox.
112 */
113 OEditListBox(const QString& title, QWidget *parent = 0,
114 const char *name = 0, bool checkAtEntering=false,
115 int buttons = All );
116
117 /**
118 * Another constructor, which allows to use a custom editing widget
119 * instead of the standard OLineEdit widget. E.g. you can use a
120 * @ref OURLRequester or a @ref OComboBox as input widget. The custom
121 * editor must consist of a lineedit and optionally another widget that
122 * is used as representation. A OComboBox or a OURLRequester have a
123 * OLineEdit as child-widget for example, so the OComboBox is used as
124 * the representation widget.
125 *
126 * @see OURLRequester::customEditor()
127 * @since 3.1
128 */
129 OEditListBox( const QString& title,
130 const CustomEditor &customEditor,
131 QWidget *parent = 0, const char *name = 0,
132 bool checkAtEntering = false, int buttons = All );
133
134 virtual ~OEditListBox();
135
136 /**
137 * Return a pointer to the embedded QListBox.
138 */
139 QListBox* listBox() const { return m_listBox; }
140 /**
141 * Return a pointer to the embedded QLineEdit.
142 */
143 OLineEdit* lineEdit() const { return m_lineEdit; }
144 /**
145 * Return a pointer to the Add button
146 */
147 QPushButton* addButton() const { return servNewButton; }
148 /**
149 * Return a pointer to the Remove button
150 */
151 QPushButton* removeButton() const { return servRemoveButton; }
152 /**
153 * Return a pointer to the Up button
154 */
155 QPushButton* upButton() const { return servUpButton; }
156 /**
157 * Return a pointer to the Down button
158 */
159 QPushButton* downButton() const { return servDownButton; }
160
161 /**
162 * See @ref QListBox::count()
163 */
164 int count() const { return int(m_listBox->count()); }
165 /**
166 * See @ref QListBox::insertStringList()
167 */
168 void insertStringList(const QStringList& list, int index=-1);
169 /**
170 * See @ref QListBox::insertStringList()
171 */
172 void insertStrList(const QStrList* list, int index=-1);
173 /**
174 * See @ref QListBox::insertStrList()
175 */
176 void insertStrList(const QStrList& list, int index=-1);
177 /**
178 * See @ref QListBox::insertStrList()
179 */
180 void insertStrList(const char ** list, int numStrings=-1, int index=-1);
181 /**
182 * See @ref QListBox::insertItem()
183 */
184 void insertItem(const QString& text, int index=-1) {m_listBox->insertItem(text,index);}
185 /**
186 * Clears both the listbox and the line edit.
187 */
188 void clear();
189 /**
190 * See @ref QListBox::text()
191 */
192 QString text(int index) const { return m_listBox->text(index); }
193 /**
194 * See @ref QListBox::currentItem()
195 */
196 int currentItem() const;
197 /**
198 * See @ref QListBox::currentText()
199 */
200 QString currentText() const { return m_listBox->currentText(); }
201
202 /**
203 * @returns a stringlist of all items in the listbox
204 */
205 QStringList items() const;
206
207 signals:
208 void changed();
209
210 /**
211 * This signal is emitted when the user adds a new string to the list,
212 * the parameter is the added string.
213 * @since 3.2
214 */
215 void added( const QString & text );
216
217 /**
218 * This signal is emitted when the user removes a string from the list,
219 * the parameter is the removed string.
220 * @since 3.2
221 */
222 void removed( const QString & text );
223
224 protected slots:
225 //the names should be self-explaining
226 void moveItemUp();
227 void moveItemDown();
228 void addItem();
229 void removeItem();
230 void enableMoveButtons(int index);
231 void typedSomething(const QString& text);
232
233 private:
234 QListBox *m_listBox;
235 QPushButton *servUpButton, *servDownButton;
236 QPushButton *servNewButton, *servRemoveButton;
237 OLineEdit *m_lineEdit;
238
239 //this is called in both ctors, to avoid code duplication
240 void init( bool checkAtEntering, int buttons,
241 QWidget *representationWidget = 0L );
242
243 protected:
244 virtual void virtual_hook( int id, void* data );
245 private:
246 //our lovely private d-pointer
247 OEditListBoxPrivate *d;
248};
249
250#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 @@
1/*
2                 This file is part of the Opie Project
3
4 Originally part of the KDE project
5 (C) 1999-2000 Espen Sand (espensa@online.no)
6 =.
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33/* QT */
34
35#include <qbitmap.h>
36#include <qgrid.h>
37#include <qhbox.h>
38#include <qheader.h>
39#include <qlabel.h>
40#include <qlayout.h>
41#include <qobjectlist.h>
42#include <qpixmap.h>
43#include <qlistview.h>
44#include <qsplitter.h>
45#include <qtabwidget.h>
46#include <qvbox.h>
47#include <qwidgetstack.h>
48#include <qpainter.h>
49#include <qtimer.h>
50#include <qstyle.h>
51
52/* OPIE */
53
54#include <opie2/odialog.h>
55#include <opie2/oseparator.h>
56#include <opie2/ojanuswidget.h>
57
58/*======================================================================================
59 * IconListItem
60 *======================================================================================*/
61
62class OJanusWidget::IconListItem : public QListBoxItem
63{
64 public:
65 IconListItem( QListBox *listbox, const QPixmap &pixmap,
66 const QString &text );
67 virtual int height( const QListBox *lb ) const;
68 virtual int width( const QListBox *lb ) const;
69 int expandMinimumWidth( int width );
70
71 protected:
72 const QPixmap &defaultPixmap();
73 void paint( QPainter *painter );
74
75 private:
76 QPixmap mPixmap;
77 int mMinimumWidth;
78};
79
80template class QPtrList<QListViewItem>;
81
82/*======================================================================================
83 * OJanusWidget
84 *======================================================================================*/
85
86OJanusWidget::OJanusWidget( QWidget *parent, const char *name, int face )
87 : QWidget( parent, name, 0 ),
88 mValid(false), mPageList(0),
89 mTitleList(0), mFace(face), mTitleLabel(0), mActivePageWidget(0),
90 mShowIconsInTreeList(false), d(0)
91{
92 QVBoxLayout *topLayout = new QVBoxLayout( this );
93
94 if( mFace == TreeList || mFace == IconList )
95 {
96 mPageList = new QPtrList<QWidget>;
97 mTitleList = new QStringList();
98
99 QFrame *page;
100 if( mFace == TreeList )
101 {
102 QSplitter *splitter = new QSplitter( this );
103 topLayout->addWidget( splitter, 10 );
104 mTreeListResizeMode = QSplitter::KeepSize;
105
106 mTreeList = new QListView( splitter );
107 mTreeList->addColumn( QString::fromLatin1("") );
108 mTreeList->header()->hide();
109 mTreeList->setRootIsDecorated(true);
110 mTreeList->setSorting( -1 );
111 connect( mTreeList, SIGNAL(selectionChanged()), SLOT(slotShowPage()) );
112 connect( mTreeList, SIGNAL(clicked(QListViewItem *)), SLOT(slotItemClicked(QListViewItem *)));
113
114 //
115 // Page area. Title at top with a separator below and a pagestack using
116 // all available space at bottom.
117 //
118 QFrame *p = new QFrame( splitter );
119
120 QHBoxLayout *hbox = new QHBoxLayout( p, 0, 0 );
121 hbox->addSpacing( ODialog::spacingHint() );
122
123 page = new QFrame( p );
124 hbox->addWidget( page, 10 );
125 }
126 else
127 {
128 QHBoxLayout *hbox = new QHBoxLayout( topLayout );
129 mIconList = new IconListBox( this );
130
131 QFont listFont( mIconList->font() );
132 listFont.setBold( true );
133 mIconList->setFont( listFont );
134
135 mIconList->verticalScrollBar()->installEventFilter( this );
136 hbox->addWidget( mIconList );
137 connect( mIconList, SIGNAL(selectionChanged()), SLOT(slotShowPage()));
138 hbox->addSpacing( ODialog::spacingHint() );
139 page = new QFrame( this );
140 hbox->addWidget( page, 10 );
141 }
142
143 //
144 // Rest of page area. Title at top with a separator below and a
145 // pagestack using all available space at bottom.
146 //
147
148 QVBoxLayout *vbox = new QVBoxLayout( page, 0, ODialog::spacingHint() );
149
150 mTitleLabel = new QLabel( QString::fromLatin1("Empty page"), page, "OJanusWidgetTitleLabel" );
151 vbox->addWidget( mTitleLabel );
152
153 QFont titleFont( mTitleLabel->font() );
154 titleFont.setBold( true );
155 mTitleLabel->setFont( titleFont );
156
157 mTitleSep = new OSeparator( page );
158 mTitleSep->setFrameStyle( QFrame::HLine|QFrame::Plain );
159 vbox->addWidget( mTitleSep );
160
161 mPageStack = new QWidgetStack( page );
162 connect(mPageStack, SIGNAL(aboutToShow(QWidget *)),
163 this, SIGNAL(aboutToShowPage(QWidget *)));
164 vbox->addWidget( mPageStack, 10 );
165 }
166 else if( mFace == Tabbed )
167 {
168 mPageList = new QPtrList<QWidget>;
169
170 mTabControl = new QTabWidget( this );
171 mTabControl->setMargin (ODialog::marginHint());
172 topLayout->addWidget( mTabControl, 10 );
173 }
174 else if( mFace == Swallow )
175 {
176 mSwallowPage = new QWidget( this );
177 topLayout->addWidget( mSwallowPage, 10 );
178 }
179 else
180 {
181 mFace = Plain;
182 mPlainPage = new QFrame( this );
183 topLayout->addWidget( mPlainPage, 10 );
184 }
185
186 /* FIXME: Revise for Opie
187 if ( kapp )
188 connect(kapp,SIGNAL(kdisplayFontChanged()),SLOT(slotFontChanged()));
189 */
190
191 mValid = true;
192
193 setSwallowedWidget(0); // Set default size if 'mFace' is Swallow.
194}
195
196
197OJanusWidget::~OJanusWidget()
198{
199 delete mPageList;
200 mPageList = 0;
201 delete mTitleList;
202 mTitleList = 0;
203}
204
205
206bool OJanusWidget::isValid() const
207{
208 return( mValid );
209}
210
211
212QFrame *OJanusWidget::plainPage()
213{
214 return( mPlainPage );
215}
216
217
218int OJanusWidget::face() const
219{
220 return( mFace );
221}
222
223QWidget *OJanusWidget::FindParent()
224{
225 if( mFace == Tabbed ) {
226 return mTabControl;
227 }
228 else {
229 return this;
230 }
231}
232
233QFrame *OJanusWidget::addPage( const QStringList &items, const QString &header,
234 const QPixmap &pixmap )
235{
236 if( mValid == false )
237 {
238 qDebug( "addPage: Invalid object" );
239 return( 0 );
240 }
241
242 QFrame *page = new QFrame( FindParent(), "page" );
243 addPageWidget( page, items, header, pixmap );
244
245 return page;
246}
247
248void OJanusWidget::pageGone( QObject *obj )
249{
250 removePage( static_cast<QWidget*>( obj ) );
251}
252
253void OJanusWidget::slotReopen( QListViewItem * item )
254{
255 if( item )
256 item->setOpen( true );
257}
258
259QFrame *OJanusWidget::addPage( const QString &itemName, const QString &header,
260 const QPixmap &pixmap )
261{
262 QStringList items;
263 items << itemName;
264 return addPage(items, header, pixmap);
265}
266
267
268
269QVBox *OJanusWidget::addVBoxPage( const QStringList &items,
270 const QString &header,
271 const QPixmap &pixmap )
272{
273 if( mValid == false )
274 {
275 qDebug( "addPage: Invalid object" );
276 return( 0 );
277 }
278
279 QVBox *page = new QVBox(FindParent() , "page" );
280 page->setSpacing( ODialog::spacingHint() );
281 addPageWidget( page, items, header, pixmap );
282
283 return page;
284}
285
286QVBox *OJanusWidget::addVBoxPage( const QString &itemName,
287 const QString &header,
288 const QPixmap &pixmap )
289{
290 QStringList items;
291 items << itemName;
292 return addVBoxPage(items, header, pixmap);
293}
294
295QHBox *OJanusWidget::addHBoxPage( const QStringList &items,
296 const QString &header,
297 const QPixmap &pixmap )
298{
299 if( mValid == false ) {
300 qDebug( "addPage: Invalid object" );
301 return( 0 );
302 }
303
304 QHBox *page = new QHBox(FindParent(), "page");
305 page->setSpacing( ODialog::spacingHint() );
306 addPageWidget( page, items, header, pixmap );
307
308 return page;
309}
310
311QHBox *OJanusWidget::addHBoxPage( const QString &itemName,
312 const QString &header,
313 const QPixmap &pixmap )
314{
315 QStringList items;
316 items << itemName;
317 return addHBoxPage(items, header, pixmap);
318}
319
320QGrid *OJanusWidget::addGridPage( int n, Orientation dir,
321 const QStringList &items,
322 const QString &header,
323 const QPixmap &pixmap )
324{
325 if( mValid == false )
326 {
327 qDebug( "addPage: Invalid object" );
328 return( 0 );
329 }
330
331 QGrid *page = new QGrid( n, dir, FindParent(), "page" );
332 page->setSpacing( ODialog::spacingHint() );
333 addPageWidget( page, items, header, pixmap );
334
335 return page;
336}
337
338
339QGrid *OJanusWidget::addGridPage( int n, Orientation dir,
340 const QString &itemName,
341 const QString &header,
342 const QPixmap &pixmap )
343{
344 QStringList items;
345 items << itemName;
346 return addGridPage(n, dir, items, header, pixmap);
347}
348
349void OJanusWidget::InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page)
350{
351 bool isTop = true;
352 QListViewItem *curTop = 0, *child, *last, *newChild;
353 unsigned int index = 1;
354 QStringList curPath;
355
356 for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it, index++ ) {
357 QString name = (*it);
358 bool isPath = ( index != items.count() );
359
360 // Find the first child.
361 if (isTop) {
362 child = mTreeList->firstChild();
363 }
364 else {
365 child = curTop->firstChild();
366 }
367
368 // Now search for a child with the current Name, and if it we doesn't
369 // find it, then remember the location of the last child.
370 for (last = 0; child && child->text(0) != name ; last = child, child = child->nextSibling());
371
372 if (last == 0 && child == 0) {
373 // This node didn't have any children at all, lets just insert the
374 // new child.
375 if (isTop)
376 newChild = new QListViewItem(mTreeList, name);
377 else
378 newChild = new QListViewItem(curTop, name);
379
380 }
381 else if (child != 0) {
382 // we found the given name in this child.
383 if (!isPath) {
384 qDebug( "The element inserted was already in the TreeList box!" );
385 return;
386 }
387 else {
388 // Ok we found the folder
389 newChild = child;
390 }
391 }
392 else {
393 // the node had some children, but we didn't find the given name
394 if (isTop)
395 newChild = new QListViewItem(mTreeList, last, name);
396 else
397 newChild = new QListViewItem(curTop, last, name);
398 }
399
400 // Now make the element expandable if it is a path component, and make
401 // ready for next loop
402 if (isPath) {
403 newChild->setExpandable(true);
404 curTop = newChild;
405 isTop = false;
406 curPath << name;
407
408 QString key = curPath.join("_/_");
409 if (mFolderIconMap.contains(key)) {
410 QPixmap p = mFolderIconMap[key];
411 newChild->setPixmap(0,p);
412 }
413 }
414 else {
415 if (mShowIconsInTreeList) {
416 newChild->setPixmap(0, pixmap);
417 }
418 mTreeListToPageStack.insert(newChild, page);
419 }
420 }
421}
422
423void OJanusWidget::addPageWidget( QFrame *page, const QStringList &items,
424 const QString &header,const QPixmap &pixmap )
425{
426 connect(page, SIGNAL(destroyed(QObject*)), SLOT(pageGone(QObject*)));
427
428 if( mFace == Tabbed )
429 {
430 mTabControl->addTab (page, items.last());
431 mPageList->append (page);
432 }
433 else if( mFace == TreeList || mFace == IconList )
434 {
435 mPageList->append( page );
436 mPageStack->addWidget( page, 0 );
437
438 if (items.count() == 0) {
439 qDebug( "Invalid QStringList, with zero items" );
440 return;
441 }
442
443 if( mFace == TreeList )
444 {
445 InsertTreeListItem(items, pixmap, page);
446 }
447 else // mFace == IconList
448 {
449 QString itemName = items.last();
450 IconListItem *item = new IconListItem( mIconList, pixmap, itemName );
451 //
452 // 2000-06-01 Espen Sand: If I do this with Qt 2.1.1 all sorts of
453 // strange things happen. With Qt <= 2.1 it worked but now I must
454 // either specify the listbox in the constructor on the item
455 // or as below, not both.
456 // mIconList->insertItem( item );
457 //
458 mIconListToPageStack.insert(item, page);
459 mIconList->invalidateHeight();
460 mIconList->invalidateWidth();
461
462 if (mIconList->isVisible())
463 mIconList->updateWidth();
464 }
465
466 //
467 // Make sure the title label is sufficiently wide
468 //
469 QString lastName = items.last();
470 const QString &title = (header != QString::null ? header : lastName);
471 QRect r = mTitleLabel->fontMetrics().boundingRect( title );
472 if( mTitleLabel->minimumWidth() < r.width() )
473 {
474 mTitleLabel->setMinimumWidth( r.width() );
475 }
476 mTitleList->append( title );
477
478 if( mTitleList->count() == 1 )
479 {
480 showPage(0);
481 }
482 }
483 else
484 {
485 qDebug( "OJanusWidget::addPageWidget: can only add a page in Tabbed, TreeList or IconList modes" );
486 }
487
488}
489
490void OJanusWidget::setFolderIcon(const QStringList &path, const QPixmap &pixmap)
491{
492 QString key = path.join("_/_");
493 mFolderIconMap.insert(key,pixmap);
494}
495
496
497
498bool OJanusWidget::setSwallowedWidget( QWidget *widget )
499{
500 if( mFace != Swallow || mValid == false )
501 {
502 return( false );
503 }
504
505 //
506 // Remove current layout and make a new.
507 //
508 if( mSwallowPage->layout() != 0 )
509 {
510 delete mSwallowPage->layout();
511 }
512 QGridLayout *gbox = new QGridLayout( mSwallowPage, 1, 1, 0 );
513
514 //
515 // Hide old children
516 //
517 QObjectList *l = (QObjectList*)mSwallowPage->children(); // silence please
518 for( uint i=0; i < l->count(); i++ )
519 {
520 QObject *o = l->at(i);
521 if( o->isWidgetType() )
522 {
523 ((QWidget*)o)->hide();
524 }
525 }
526
527 //
528 // Add new child or make default size
529 //
530 if( widget == 0 )
531 {
532 gbox->addRowSpacing(0,100);
533 gbox->addColSpacing(0,100);
534 mSwallowPage->setMinimumSize(100,100);
535 }
536 else
537 {
538 if( widget->parent() != mSwallowPage )
539 {
540 widget->reparent( mSwallowPage, 0, QPoint(0,0) );
541 }
542 gbox->addWidget(widget, 0, 0 );
543 gbox->activate();
544 mSwallowPage->setMinimumSize( widget->minimumSize() );
545 }
546
547 return( true );
548}
549
550bool OJanusWidget::slotShowPage()
551{
552 if( mValid == false )
553 {
554 return( false );
555 }
556
557 if( mFace == TreeList )
558 {
559 QListViewItem *node = mTreeList->selectedItem();
560 if( node == 0 ) { return( false ); }
561
562 QWidget *stackItem = mTreeListToPageStack[node];
563 return showPage(stackItem);
564 }
565 else if( mFace == IconList )
566 {
567 QListBoxItem *node = mIconList->item( mIconList->currentItem() );
568 if( node == 0 ) { return( false ); }
569 QWidget *stackItem = mIconListToPageStack[node];
570 return showPage(stackItem);
571 }
572
573 return( false );
574}
575
576
577bool OJanusWidget::showPage( int index )
578{
579 if( mPageList == 0 || mValid == false )
580 {
581 return( false );
582 }
583 else
584 {
585 return showPage(mPageList->at(index));
586 }
587}
588
589
590bool OJanusWidget::showPage( QWidget *w )
591{
592 if( w == 0 || mValid == false )
593 {
594 return( false );
595 }
596
597 if( mFace == TreeList || mFace == IconList )
598 {
599 mPageStack->raiseWidget( w );
600 mActivePageWidget = w;
601
602 int index = mPageList->findRef( w );
603 mTitleLabel->setText( *mTitleList->at(index) );
604 if( mFace == TreeList )
605 {
606 QMap<QListViewItem *, QWidget *>::Iterator it;
607 for (it = mTreeListToPageStack.begin(); it != mTreeListToPageStack.end(); ++it){
608 QListViewItem *key = it.key();
609 QWidget *val = it.data();
610 if (val == w) {
611 mTreeList->setSelected(key, true );
612 break;
613 }
614 }
615 }
616 else
617 {
618 QMap<QListBoxItem *, QWidget *>::Iterator it;
619 for (it = mIconListToPageStack.begin(); it != mIconListToPageStack.end(); ++it){
620 QListBoxItem *key = it.key();
621 QWidget *val = it.data();
622 if (val == w) {
623 mIconList->setSelected( key, true );
624 break;
625 }
626 }
627
628 //
629 // 2000-02-13 Espen Sand
630 // Don't ask me why (because I don't know). If I select a page
631 // with the mouse the page is not updated until it receives an
632 // event. It seems this event get lost if the mouse is not moved
633 // when released. The timer ensures the update
634 //
635 QTimer::singleShot( 0, mActivePageWidget, SLOT(update()) );
636 }
637 }
638 else if( mFace == Tabbed )
639 {
640 mTabControl->showPage(w);
641 mActivePageWidget = w;
642 }
643 else
644 {
645 return( false );
646 }
647
648 return( true );
649}
650
651
652int OJanusWidget::activePageIndex() const
653{
654 if( mFace == TreeList) {
655 QListViewItem *node = mTreeList->selectedItem();
656 if( node == 0 ) { return -1; }
657 QWidget *stackItem = mTreeListToPageStack[node];
658 return mPageList->findRef(stackItem);
659 }
660 else if (mFace == IconList) {
661 QListBoxItem *node = mIconList->item( mIconList->currentItem() );
662 if( node == 0 ) { return( false ); }
663 QWidget *stackItem = mIconListToPageStack[node];
664 return mPageList->findRef(stackItem);
665 }
666 else if( mFace == Tabbed ) {
667 QWidget *widget = mTabControl->currentPage();
668 return( widget == 0 ? -1 : mPageList->findRef( widget ) );
669 }
670 else {
671 return( -1 );
672 }
673}
674
675
676int OJanusWidget::pageIndex( QWidget *widget ) const
677{
678 if( widget == 0 )
679 {
680 return( -1 );
681 }
682 else if( mFace == TreeList || mFace == IconList )
683 {
684 return( mPageList->findRef( widget ) );
685 }
686 else if( mFace == Tabbed )
687 {
688 //
689 // The user gets the real page widget with addVBoxPage(), addHBoxPage()
690 // and addGridPage() but not with addPage() which returns a child of
691 // the toplevel page. addPage() returns a QFrame so I check for that.
692 //
693 if( widget->isA("QFrame") )
694 {
695 return( mPageList->findRef( widget->parentWidget() ) );
696 }
697 else
698 {
699 return( mPageList->findRef( widget ) );
700 }
701 }
702 else
703 {
704 return( -1 );
705 }
706}
707
708void OJanusWidget::slotFontChanged()
709{
710#ifdef FIXME
711
712 if ( mTitleLabel != 0 )
713 {
714 mTitleLabel->setFont( KGlobalSettings::generalFont() );
715 QFont titleFont( mTitleLabel->font() );
716 titleFont.setBold( true );
717 mTitleLabel->setFont( titleFont );
718 }
719#endif
720
721 if( mFace == IconList )
722 {
723 QFont listFont( mIconList->font() );
724 listFont.setBold( true );
725 mIconList->setFont( listFont );
726 mIconList->invalidateHeight();
727 mIconList->invalidateWidth();
728 }
729}
730
731// makes the treelist behave like the list of kcontrol
732void OJanusWidget::slotItemClicked(QListViewItem *it)
733{
734 if(it && (it->childCount()>0))
735 it->setOpen(!it->isOpen());
736}
737
738void OJanusWidget::setFocus()
739{
740 if( mValid == false ) { return; }
741 if( mFace == TreeList )
742 {
743 mTreeList->setFocus();
744 }
745 if( mFace == IconList )
746 {
747 mIconList->setFocus();
748 }
749 else if( mFace == Tabbed )
750 {
751 mTabControl->setFocus();
752 }
753 else if( mFace == Swallow )
754 {
755 mSwallowPage->setFocus();
756 }
757 else if( mFace == Plain )
758 {
759 mPlainPage->setFocus();
760 }
761}
762
763
764QSize OJanusWidget::minimumSizeHint() const
765{
766 if( mFace == TreeList || mFace == IconList )
767 {
768 QSize s1( ODialog::spacingHint(), ODialog::spacingHint()*2 );
769 QSize s2(0,0);
770 QSize s3(0,0);
771 QSize s4( mPageStack->sizeHint() );
772
773 if( mFace == TreeList )
774 {
775#if QT_VERSION < 300
776 s1.rwidth() += style().splitterWidth();
777#else
778 s1.rwidth() += style().pixelMetric( QStyle::PM_SplitterWidth );
779#endif
780 s2 = mTreeList->minimumSize();
781 }
782 else
783 {
784 mIconList->updateMinimumHeight();
785 mIconList->updateWidth();
786 s2 = mIconList->minimumSize();
787 }
788
789 if( mTitleLabel->isVisible() == true )
790 {
791 s3 += mTitleLabel->sizeHint();
792 s3.rheight() += mTitleSep->minimumSize().height();
793 }
794
795 //
796 // Select the tallest item. It has only effect in IconList mode
797 //
798 int h1 = s1.rheight() + s3.rheight() + s4.height();
799 int h2 = QMAX( h1, s2.rheight() );
800
801 return( QSize( s1.width()+s2.width()+QMAX(s3.width(),s4.width()), h2 ) );
802 }
803 else if( mFace == Tabbed )
804 {
805 return( mTabControl->sizeHint() );
806 }
807 else if( mFace == Swallow )
808 {
809 return( mSwallowPage->minimumSize() );
810 }
811 else if( mFace == Plain )
812 {
813 return( mPlainPage->sizeHint() );
814 }
815 else
816 {
817 return( QSize( 100, 100 ) ); // Should never happen though.
818 }
819
820}
821
822
823QSize OJanusWidget::sizeHint() const
824{
825 return( minimumSizeHint() );
826}
827
828
829void OJanusWidget::setTreeListAutoResize( bool state )
830{
831 if( mFace == TreeList )
832 {
833 mTreeListResizeMode = state == false ?
834 QSplitter::KeepSize : QSplitter::Stretch;
835 QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget());
836 splitter->setResizeMode( mTreeList, mTreeListResizeMode );
837 }
838}
839
840
841void OJanusWidget::setIconListAllVisible( bool state )
842{
843 if( mFace == IconList )
844 {
845 mIconList->setShowAll( state );
846 }
847}
848
849void OJanusWidget::setShowIconsInTreeList( bool state )
850{
851 mShowIconsInTreeList = state;
852}
853
854void OJanusWidget::setRootIsDecorated( bool state )
855{
856 if( mFace == TreeList ) {
857 mTreeList->setRootIsDecorated(state);
858 }
859}
860
861void OJanusWidget::unfoldTreeList( bool persist )
862{
863 if( mFace == TreeList )
864 {
865 if( persist )
866 connect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
867 else
868 disconnect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
869
870 for( QListViewItem * item = mTreeList->firstChild(); item; item = item->itemBelow() )
871 item->setOpen( true );
872 }
873}
874
875void OJanusWidget::showEvent( QShowEvent * )
876{
877 if( mFace == TreeList )
878 {
879 QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget());
880 splitter->setResizeMode( mTreeList, mTreeListResizeMode );
881 }
882}
883
884
885//
886// 2000-13-02 Espen Sand
887// It should be obvious that this eventfilter must only be
888// be installed on the vertical scrollbar of the mIconList.
889//
890bool OJanusWidget::eventFilter( QObject *o, QEvent *e )
891{
892 if( e->type() == QEvent::Show )
893 {
894 IconListItem *item = (IconListItem*)mIconList->item(0);
895 if( item != 0 )
896 {
897 int lw = item->width( mIconList );
898 int sw = mIconList->verticalScrollBar()->sizeHint().width();
899 mIconList->setFixedWidth( lw+sw+mIconList->frameWidth()*2 );
900 }
901 }
902 else if( e->type() == QEvent::Hide )
903 {
904 IconListItem *item = (IconListItem*)mIconList->item(0);
905 if( item != 0 )
906 {
907 int lw = item->width( mIconList );
908 mIconList->setFixedWidth( lw+mIconList->frameWidth()*2 );
909 }
910 }
911 return QWidget::eventFilter( o, e );
912}
913
914
915
916//
917// Code for the icon list box
918//
919
920
921OJanusWidget::IconListBox::IconListBox( QWidget *parent, const char *name,
922 WFlags f )
923 :QListBox( parent, name, f ), mShowAll(false), mHeightValid(false),
924 mWidthValid(false)
925{
926}
927
928
929void OJanusWidget::IconListBox::updateMinimumHeight()
930{
931 if( mShowAll == true && mHeightValid == false )
932 {
933 int h = frameWidth()*2;
934 for( QListBoxItem *i = item(0); i != 0; i = i->next() )
935 {
936 h += i->height( this );
937 }
938 setMinimumHeight( h );
939 mHeightValid = true;
940 }
941}
942
943
944void OJanusWidget::IconListBox::updateWidth()
945{
946 if( mWidthValid == false )
947 {
948 int maxWidth = 10;
949 for( QListBoxItem *i = item(0); i != 0; i = i->next() )
950 {
951 int w = ((IconListItem *)i)->width(this);
952 maxWidth = QMAX( w, maxWidth );
953 }
954
955 for( QListBoxItem *i = item(0); i != 0; i = i->next() )
956 {
957 ((IconListItem *)i)->expandMinimumWidth( maxWidth );
958 }
959
960 if( verticalScrollBar()->isVisible() )
961 {
962 maxWidth += verticalScrollBar()->sizeHint().width();
963 }
964
965 setFixedWidth( maxWidth + frameWidth()*2 );
966 mWidthValid = true;
967 }
968}
969
970
971void OJanusWidget::IconListBox::invalidateHeight()
972{
973 mHeightValid = false;
974}
975
976
977void OJanusWidget::IconListBox::invalidateWidth()
978{
979 mWidthValid = false;
980}
981
982
983void OJanusWidget::IconListBox::setShowAll( bool showAll )
984{
985 mShowAll = showAll;
986 mHeightValid = false;
987}
988
989
990
991OJanusWidget::IconListItem::IconListItem( QListBox *listbox, const QPixmap &pixmap,
992 const QString &text )
993 : QListBoxItem( listbox )
994{
995 mPixmap = pixmap;
996 if( mPixmap.isNull() == true )
997 {
998 mPixmap = defaultPixmap();
999 }
1000 setText( text );
1001 mMinimumWidth = 0;
1002}
1003
1004
1005int OJanusWidget::IconListItem::expandMinimumWidth( int width )
1006{
1007 mMinimumWidth = QMAX( mMinimumWidth, width );
1008 return( mMinimumWidth );
1009}
1010
1011
1012const QPixmap &OJanusWidget::IconListItem::defaultPixmap()
1013{
1014 static QPixmap *pix=0;
1015 if( pix == 0 )
1016 {
1017 pix = new QPixmap( 32, 32 );
1018 QPainter p( pix );
1019 p.eraseRect( 0, 0, pix->width(), pix->height() );
1020 p.setPen( Qt::red );
1021 p.drawRect ( 0, 0, pix->width(), pix->height() );
1022 p.end();
1023
1024 QBitmap mask( pix->width(), pix->height(), true );
1025 mask.fill( Qt::black );
1026 p.begin( &mask );
1027 p.setPen( Qt::white );
1028 p.drawRect ( 0, 0, pix->width(), pix->height() );
1029 p.end();
1030
1031 pix->setMask( mask );
1032 }
1033 return( *pix );
1034}
1035
1036
1037void OJanusWidget::IconListItem::paint( QPainter *painter )
1038{
1039 QFontMetrics fm = painter->fontMetrics();
1040 //int wt = fm.boundingRect(text()).width();
1041 int wp = mPixmap.width();
1042 int ht = fm.lineSpacing();
1043 int hp = mPixmap.height();
1044
1045 painter->drawPixmap( (mMinimumWidth-wp)/2, 5, mPixmap );
1046 if( text().isEmpty() == false )
1047 {
1048 painter->drawText( 0, hp+7, mMinimumWidth, ht, Qt::AlignCenter, text() );
1049 }
1050}
1051
1052int OJanusWidget::IconListItem::height( const QListBox *lb ) const
1053{
1054 if( text().isEmpty() == true )
1055 {
1056 return( mPixmap.height() );
1057 }
1058 else
1059 {
1060 return( mPixmap.height() + lb->fontMetrics().lineSpacing()+10 );
1061 }
1062}
1063
1064
1065int OJanusWidget::IconListItem::width( const QListBox *lb ) const
1066{
1067 int wt = lb->fontMetrics().boundingRect(text()).width()+10;
1068 int wp = mPixmap.width() + 10;
1069 int w = QMAX( wt, wp );
1070 return( QMAX( w, mMinimumWidth ) );
1071}
1072
1073// Just remove the page from our stack of widgets. Do not modify the given widget in
1074// any way. No memory leak occurs as parent is not changed.
1075// Make this virtual in KDE 4.0.
1076// Ravikiran Rajagopal <ravi@ee.eng.ohio-state.edu>
1077void OJanusWidget::removePage( QWidget *page )
1078{
1079 if (!mPageList || !mPageList->containsRef(page))
1080 return;
1081
1082 int index = mPageList->findRef( page );
1083 if ( mTitleList )
1084 mTitleList->remove(mTitleList->at(index));
1085
1086 mPageList->removeRef(page);
1087
1088 if ( mFace == TreeList )
1089 {
1090 QMap<QListViewItem*, QWidget *>::Iterator i;
1091 for( i = mTreeListToPageStack.begin(); i != mTreeListToPageStack.end(); ++i )
1092 if (i.data()==page)
1093 {
1094 delete i.key();
1095 mPageStack->removeWidget(page);
1096 mTreeListToPageStack.remove(i);
1097 break;
1098 }
1099 }
1100 else if ( mFace == IconList )
1101 {
1102 QMap<QListBoxItem*, QWidget *>::Iterator i;
1103 for( i = mIconListToPageStack.begin(); i != mIconListToPageStack.end(); ++i )
1104 if (i.data()==page)
1105 {
1106 delete i.key();
1107 mPageStack->removeWidget(page);
1108 mIconListToPageStack.remove(i);
1109 break;
1110 }
1111 }
1112 else // Tabbed
1113 {
1114 mTabControl->removePage(page);
1115 }
1116}
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 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 Copyright (C) 1999-2000 Espen Sand (espen@kde.org)
6 =.
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33#ifndef OJANUSWIDGET_H
34#define OJANUSWIDGET_H
35
36#include <qptrlist.h>
37#include <qpixmap.h>
38#include <qlistbox.h>
39#include <qmap.h>
40#include <qsplitter.h>
41#include <qstringlist.h>
42
43class QGrid;
44class QHBox;
45class QLabel;
46class QTabWidget;
47class QVBox;
48class QWidgetStack;
49class OSeparator;
50class QListView;
51class QListViewItem;
52
53/**
54 * Provides a number of ready to use layouts (faces). It is used
55 * as an internal widget in @ref KDialogBase, but can also used as a
56 * widget of its own.
57 *
58 * It provides TreeList, IconList, Tabbed, Plain and Swallow layouts.
59 *
60 * The TreeList face provides a list in the left area and pages in the
61 * right. The area are separated by a movable splitter. The style is somewhat
62 * similar to the layout in the Control Center. A page is raised by
63 * selecting the corresponding tree list item.
64 *
65 * The IconList face provides an icon list in the left area and pages in the
66 * right. For each entry the Icon is on top with the text below. The style
67 * is somewhat similar to the layout of the Eudora configuation dialog box.
68 * A page is raised by selecting the corresponding icon list item. The
69 * preferred icon size is 32x32 pixels.
70 *
71 * The Tabbed face is a common tabbed widget. The procedure for creating a
72 * page is similar for creating a TreeList. This has the advantage that if
73 * your widget contain too many pages it is trivial to convert it into a
74 * TreeList. Just change the face in the KJanusWidget constructor to
75 * KJanusWidget::TreeList and you have a tree list layout instead.
76 *
77 * The Plain face provides an empty widget (QFrame) where you can place your
78 * widgets. The KJanusWidget makes no assumptions regarding the contents so
79 * you are free to add whatever you want.
80 *
81 * The Swallow face is provided in order to simplify the usage of existing
82 * widgets and to allow changing the visible widget. You specify the widget
83 * to be displayed by @ref #setSwallowedWidget(). Your widget will be
84 * reparented inside the widget. You can specify a Null (0) widget. A empty
85 * space is then displayed.
86 *
87 * For all modes it is important that you specify the @ref QWidget::minimumSize()
88 * on the page, plain widget or the swallowed widget. If you use a QLayout
89 * on the page, plain widget or the swallowed widget this will be taken care
90 * of automatically. The size is used when the KJanusWidget determines its
91 * own minimum size. You get the minimum size by using the
92 * @ref #minimumSizeHint() or @ref #sizeHint() methods.
93 *
94 * Pages that have been added in TreeList, IconList or Tabbed mode can be
95 * removed by simply deleting the page.
96 *
97 * @short Easy to use widget with many layouts
98 * @author Espen Sand (espen@kde.org)
99 */
100class OJanusWidget : public QWidget
101{
102 Q_OBJECT
103
104 private:
105
106 class IconListBox : public QListBox
107 {
108 public:
109 IconListBox( QWidget *parent=0, const char *name=0, WFlags f=0 );
110 void updateMinimumHeight();
111 void updateWidth();
112 void invalidateHeight();
113 void invalidateWidth();
114 void setShowAll( bool showAll );
115
116 private:
117 bool mShowAll;
118 bool mHeightValid;
119 bool mWidthValid;
120 };
121
122 public:
123
124 enum Face
125 {
126 TreeList = 0,
127 Tabbed,
128 Plain,
129 Swallow,
130 IconList
131 };
132
133 public:
134
135 /**
136 * Constructor where you specify the face.
137 *
138 * @param parent Parent of the widget.
139 * @param name Widget name.
140 * @param int face The kind of dialog, Use TreeList, Tabbed, Plain or
141 * Swallow.
142 */
143 OJanusWidget( QWidget *parent=0, const char *name=0, int face=Plain );
144
145 /**
146 * Destructor.
147 */
148 ~OJanusWidget();
149
150 /**
151 * Raises the page which was added by @ref addPage().
152 *
153 * @param index The index of the page you want to raise.
154 */
155 virtual bool showPage( int index );
156
157 /**
158 * Returns the index of the page that are currently displayed.
159 *
160 * @return The index or -1 if the face is not Tabbed, TreeList or
161 * IconList.
162 */
163 virtual int activePageIndex() const;
164
165 /**
166 * Use this to verify
167 * that no memory allocation failed.
168 *
169 * @return true if the widget was properly created.
170 */
171 virtual bool isValid() const;
172
173 /**
174 * Returns the face type.
175 *
176 * @return The face type.
177 */
178 virtual int face() const;
179
180 /**
181 * Returns the minimum size that must be made available for the widget
182 * so that UIs can be displayed properly
183 *
184 * @return The minimum size.
185 */
186 virtual QSize minimumSizeHint() const;
187
188 /**
189 * Returns the recommended size for the widget in order to be displayed
190 * properly.
191 *
192 * @return The recommended size.
193 */
194 virtual QSize sizeHint() const;
195
196 /**
197 * Returns the empty widget that is available in Plain mode.
198 *
199 * @return The widget or 0 if the face in not Plain.
200 */
201 virtual QFrame *plainPage();
202
203 /**
204 * Add a new page when the class is used in TreeList, IconList or Tabbed
205 * mode. The returned widget is empty and you must add your widgets
206 * as children to this widget. In most cases you must create a layout
207 * manager and associate it with this widget as well.
208 *
209 * Deleting the returned frame will cause the listitem or tab to be
210 * removed (you can re-add a page with the same name later.
211 *
212 * @param item String used in the list or Tab item.
213 * @param header A longer string used in TreeList and IconList mode to
214 * describe the contents of a page. If empty, the item string
215 * will be used instead.
216 * @param pixmap Used in IconList mode or in TreeList mode. You should
217 * prefer a pixmap with size 32x32 pixels.
218 *
219 * @return The empty page or 0 if the face is not TreeList, IconList or
220 * Tabbed.
221 */
222 virtual QFrame *addPage(const QString &item,const QString &header=QString::null,
223 const QPixmap &pixmap=QPixmap() );
224
225 /**
226 * This is like addPage just above, with the difference that the first
227 * element is a list of strings. These strings are used to form a path
228 * of folders down to the given page. The initial elements are names
229 * for the folders, while the last element is the name of the page.
230 * Note: This does yet only work for the TreeList face. Later this may
231 * be added for the IconList face too. In other faces than the
232 * TreeList, all the strings except the last one is ignored.
233 * Deleting the returned frame will cause the listitem or tab to be
234 * removed (you can re-add a page with the same name later.
235 *
236 * Deleting the returned frame will cause the listitem or tab to be
237 * removed (you can re-add a page with the same name later.
238 **/
239 virtual QFrame *addPage(const QStringList &items, const QString &header=QString::null,
240 const QPixmap &pixmap=QPixmap() );
241
242 /**
243 * Add a new page when the class is used in TreeList, IconList or Tabbed
244 * mode. The returned widget is empty and you must add your widgets
245 * as children to this widget. The returned widget is a @ref QVBox
246 * so it contains a QVBoxLayout layout that lines up the child widgets
247 * are vertically.
248 *
249 * Deleting the returned frame will cause the listitem or tab to be
250 * removed (you can re-add a page with the same name later.
251 *
252 * @param item String used in the list or Tab item.
253 * @param header A longer string used in TreeList and IconList mode to
254 * describe the contents of a page. If empty, the item string
255 * will be used instead.
256 * @param pixmap Used in IconList mode or in TreeList mode. You should
257 * prefer a pixmap with size 32x32 pixels.
258 *
259 * @return The empty page or 0 if the face is not TreeList, IconList or
260 * Tabbed. */
261 virtual QVBox *addVBoxPage( const QString &item,
262 const QString &header=QString::null,
263 const QPixmap &pixmap=QPixmap() );
264
265 /**
266 * This is like addVBoxPage just above, with the difference that the first
267 * element is a list of strings. These strings are used to form a path
268 * of folders down to the given page. The initial elements are names
269 * for the folders, while the last element is the name of the page.
270 * Note: This does yet only work for the TreeList face. Later this may
271 * be added for the IconList face too. In other faces than the
272 * TreeList, all the strings except the last one is ignored.
273 *
274 * Deleting the returned frame will cause the listitem or tab to be
275 * removed (you can re-add a page with the same name later.
276 **/
277 virtual QVBox *addVBoxPage( const QStringList &items,
278 const QString &header=QString::null,
279 const QPixmap &pixmap=QPixmap() );
280
281 /**
282 * Add a new page when the class is used in TreeList, IconList or Tabbed
283 * mode. The returned widget is empty and you must add your widgets
284 * as children to this widget. The returned widget is a @ref QHBox
285 * so it contains a QHBoxLayout layout that lines up the child widgets
286 * are horizontally.
287 *
288 * Deleting the returned frame will cause the listitem or tab to be
289 * removed (you can re-add a page with the same name later.
290 *
291 * @param item String used in the list or Tab item.
292 * @param header A longer string used in TreeList and IconList mode to
293 * describe the contents of a page. If empty, the item string
294 * will be used instead.
295 * @param pixmap Used in IconList mode or in TreeList mode. You should
296 * prefer a pixmap with size 32x32 pixels.
297 *
298 * @return The empty page or 0 if the face is not TreeList, IconList or
299 * Tabbed.
300 */
301 virtual QHBox *addHBoxPage( const QString &itemName,
302 const QString &header=QString::null,
303 const QPixmap &pixmap=QPixmap() );
304
305 /**
306 * This is like addHBoxPage just above, with the difference that the first
307 * element is a list of strings. These strings are used to form a path
308 * of folders down to the given page. The initial elements are names
309 * for the folders, while the last element is the name of the page.
310 * Note: This does yet only work for the TreeList face. Later this may
311 * be added for the IconList face too. In other faces than the
312 * TreeList, all the strings except the last one is ignored.
313 *
314 * Deleting the returned frame will cause the listitem or tab to be
315 * removed (you can re-add a page with the same name later.
316 **/
317 virtual QHBox *addHBoxPage( const QStringList &items,
318 const QString &header=QString::null,
319 const QPixmap &pixmap=QPixmap() );
320
321 /**
322 * Add a new page when the class is used in either TreeList or Tabbed
323 * mode. The returned widget is empty and you must add your widgets
324 * as children to this widget. The returned widget is a @ref QGrid
325 * so it contains a QGridLayout layout that places up the child widgets
326 * in a grid.
327 *
328 * Deleting the returned frame will cause the listitem or tab to be
329 * removed (you can re-add a page with the same name later.
330 *
331 * @param n Specifies the number of columns if 'dir' is QGrid::Horizontal
332 * or the number of rows if 'dir' is QGrid::Vertical.
333 * @param dir Can be QGrid::Horizontal or QGrid::Vertical.
334 * @param item String used in the list or Tab item.
335 * @param header A longer string used in TreeList and IconList mode to
336 * describe the contents of a page. If empty, the item string
337 * will be used instead.
338 * @param pixmap Used in IconList mode or in TreeList mode. You should
339 * prefer a pixmap with size 32x32 pixels.
340 *
341 * @return The empty page or 0 if the face is not TreeList, IconList or
342 * Tabbed.
343 */
344 virtual QGrid *addGridPage( int n, Orientation dir,
345 const QString &itemName,
346 const QString &header=QString::null,
347 const QPixmap &pixmap=QPixmap() );
348
349 /**
350 * This is like addGridPage just above, with the difference that the first
351 * element is a list of strings. These strings are used to form a path
352 * of folders down to the given page. The initial elements are names
353 * for the folders, while the last element is the name of the page.
354 * Note: This does yet only work for the TreeList face. Later this may
355 * be added for the IconList face too. In other faces than the
356 * TreeList, all the strings except the last one is ignored.
357 *
358 * Deleting the returned frame will cause the listitem or tab to be
359 * removed (you can re-add a page with the same name later.
360 **/
361 virtual QGrid *addGridPage( int n, Orientation dir,
362 const QStringList &items,
363 const QString &header=QString::null,
364 const QPixmap &pixmap=QPixmap() );
365
366 /**
367 * @short Removes a page created with @ref addPage, @ref addVBoxPage,
368 * @ref addHBoxPage or @ref addGridPage. If the page has already
369 * been deleted or has already been removed, nothing happens. The widget
370 * itself is not deleted.
371 *
372 * @param page The widget returned by @ref addPage , @ref addVBoxPage ,
373 * @ref addHBoxPage or @ref addGridPage .
374 */
375 void removePage( QWidget *page );
376
377
378 /**
379 * Returns the index of a page created with @ref addPage ,
380 * @ref addVBoxPage , @ref addHBoxPage or @ref addGridPage .
381 * You can can compare this index with the value returned from
382 * @ref activePageIndex if you need to do some page specific actions
383 * in your code.
384 *
385 * The returned index will never change so you can safely use this
386 * function once and save the value.
387 *
388 * @param widget The widget returned by @ref addPage , @ref addVBoxPage ,
389 * @ref addHBoxPage or @ref addGridPage .
390 *
391 * @return The index or -1 if the face is not Tabbed, TreeList or
392 * IconList
393 */
394 virtual int pageIndex( QWidget *widget ) const;
395
396 /**
397 * Defines the widget to be swallowed.
398 *
399 * This method can be used several
400 * times. Only the latest defined widget will be shown.
401 *
402 * @param widget The widget to be swallowed. If 0, then an empty rectangle
403 * is displayed.
404 */
405 virtual bool setSwallowedWidget( QWidget *widget );
406
407 /**
408 * This function has only effect in TreeList mode.
409 *
410 * Defines how the tree list is resized when the widget is resized
411 * horizontally. By default the tree list keeps its width when the
412 * widget becomes wider.
413 *
414 * @param state The resize mode. If false (default) the TreeList keeps
415 * its current width when the widget becomes wider.
416 */
417 virtual void setTreeListAutoResize( bool state );
418
419 /**
420 * This function has only effect in TreeList mode.
421 *
422 * This tells the widgets whether the icons given in the @ref addPage,
423 * @ref addVBoxPage, @ref addHBoxPage, or @ref addGridPage methods should
424 * be shown in the TreeList.
425 *
426 * Note: This method must be called before calling any of the methods
427 * which add icons to the page.
428 *
429 * @param state If true the icons are shown.
430 **/
431 virtual void setShowIconsInTreeList(bool state);
432
433 /**
434 * This function has only effect in TreeList mode.
435 *
436 * This tells the widgets whether the root should be decorated.
437 * For details see @ref QListView::setRootIsDecorated
438 *
439 * @param state Root will be decorated if true.
440 **/
441 virtual void setRootIsDecorated( bool state );
442
443 /**
444 * This function has only effect in TreeList mode.
445 *
446 * This tells the TreeList to unfold the whole tree so that all entries
447 * are visible.
448 *
449 * If the list is empty when you call this method newly created entries
450 * will not automatically be opened. If the @p persist flag is set opened
451 * entries cannot be closed again, though.
452 *
453 * @param persist If true the tree always stays unfolded.
454 * @since 3.2
455 */
456 /*virtual*/ void unfoldTreeList( bool persist = false ); //### KDE4 BIC add virtual
457
458 /**
459 * This function has only effect in IconList mode.
460 *
461 * Defines how the icon list widget is displayed. By default it is
462 * the widgets in the pages that decide the minimum height
463 * of the toplevel widget. A vertical scrollbar can be used in
464 * the icon list area.
465 *
466 * @param state The visibility mode. If true, the minimum height is
467 * adjusted so that every icon in the list is visible at the
468 * same time. The vertical scrollbar will never be visible.
469 */
470 virtual void setIconListAllVisible( bool state );
471
472 /**
473 * Sets the icon used in TreeList Mode for the given path.
474 * @param path The path for which this icon should be shown.
475 * @param pixmap The icon used.
476 **/
477 virtual void setFolderIcon(const QStringList &path, const QPixmap &pixmap);
478
479 signals:
480 void aboutToShowPage(QWidget *page);
481
482 public slots:
483 /**
484 * Give the keyboard input focus to the widget.
485 */
486 virtual void setFocus();
487
488 protected:
489 /**
490 * Reimplemented to handle the splitter width when the the face
491 * is TreeList
492 */
493 virtual void showEvent( QShowEvent * );
494
495 /**
496 * This function is used internally when in IconList mode. If you
497 * reimplement this class a make your own event filter, make sure to
498 * call this function from your filter.
499 *
500 * @param o Object that has received an event.
501 * @param e The event.
502 */
503 virtual bool eventFilter( QObject *o, QEvent *e );
504
505 private slots:
506 bool slotShowPage();
507 void slotFontChanged();
508 void slotItemClicked(QListViewItem *it);
509 void pageGone(QObject *obj); // signal from the added page's "destroyed" signal
510 void slotReopen(QListViewItem *item);
511
512 protected:
513 bool showPage( QWidget *w );
514 void addPageWidget( QFrame *page, const QStringList &items,
515 const QString &header, const QPixmap &pixmap );
516 void InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page);
517 QWidget *FindParent();
518
519 private:
520 bool mValid;
521
522 QPtrList<QWidget> *mPageList;
523 QStringList *mTitleList;
524
525 int mFace;
526 QListView *mTreeList;
527 IconListBox *mIconList;
528 QWidgetStack *mPageStack;
529 QLabel *mTitleLabel;
530 QTabWidget *mTabControl;
531 QFrame *mPlainPage;
532 QWidget *mSwallowPage;
533 QWidget *mActivePageWidget;
534 OSeparator *mTitleSep;
535 QSplitter::ResizeMode mTreeListResizeMode;
536 bool mShowIconsInTreeList;
537 QMap<QListViewItem *, QWidget *> mTreeListToPageStack;
538 QMap<QListBoxItem *, QWidget *> mIconListToPageStack;
539 QMap<QString, QPixmap> mFolderIconMap;
540 QMap<QString, QStringList> mChildrenNames;
541 QMap<QString, QWidget *> mChildPages;
542
543 public:
544 class IconListItem;
545
546 private:
547 class OJanusWidgetPrivate;
548 OJanusWidgetPrivate *d;
549};
550
551#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 @@
1/*
2 This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
3 is part of the Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>, Dawit Alemayehu <adawit@kde.org>
4 Opie Project Copyright (C) 1999 Preston Brown <pbrown@kde.org>, Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
5 Copyright (C) 1997 Sven Radej (sven.radej@iname.com)
6 =.
7 .=l. Originally part of the KDE Project
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33/* QT */
34
35#include <qapplication.h>
36#include <qclipboard.h>
37#include <qtimer.h>
38#include <qpopupmenu.h>
39
40/* OPIE */
41
42#include <opie2/ocompletionbox.h>
43#include <opie2/olineedit.h>
44#include <opie2/oglobalsettings.h>
45
46typedef QString KURL; //FIXME: Revise for Opie
47
48/*======================================================================================
49 * OLineEditPrivate
50 *======================================================================================*/
51
52class OLineEdit::OLineEditPrivate
53{
54public:
55 OLineEditPrivate()
56 {
57 grabReturnKeyEvents = false;
58 handleURLDrops = true;
59 completionBox = 0L;
60 }
61 ~OLineEditPrivate()
62 {
63 delete completionBox;
64 }
65
66 bool grabReturnKeyEvents;
67 bool handleURLDrops;
68 OCompletionBox *completionBox;
69};
70
71
72/*======================================================================================
73 * OLineEdit
74 *======================================================================================*/
75
76OLineEdit::OLineEdit( const QString &string, QWidget *parent, const char *name )
77 : QLineEdit( string, parent, name )
78{
79 init();
80}
81
82OLineEdit::OLineEdit( QWidget *parent, const char *name )
83 : QLineEdit( parent, name )
84{
85 init();
86}
87
88OLineEdit::~OLineEdit ()
89{
90 delete d;
91}
92
93void OLineEdit::init()
94{
95 d = new OLineEditPrivate;
96 possibleTripleClick = false;
97 // Enable the context menu by default.
98 setContextMenuEnabled( true );
99 //OCursor::setAutoHideCursor( this, true, true );
100 installEventFilter( this );
101}
102
103void OLineEdit::setCompletionMode( OGlobalSettings::Completion mode )
104{
105 OGlobalSettings::Completion oldMode = completionMode();
106 if ( oldMode != mode && oldMode == OGlobalSettings::CompletionPopup &&
107 d->completionBox && d->completionBox->isVisible() )
108 d->completionBox->hide();
109
110 // If the widgets echo mode is not Normal, no completion
111 // feature will be enabled even if one is requested.
112 if ( echoMode() != QLineEdit::Normal )
113 mode = OGlobalSettings::CompletionNone; // Override the request.
114
115 OCompletionBase::setCompletionMode( mode );
116}
117
118void OLineEdit::setCompletedText( const QString& t, bool marked )
119{
120 QString txt = text();
121 if ( t != txt )
122 {
123 int curpos = marked ? txt.length() : t.length();
124 validateAndSet( t, curpos, curpos, t.length() );
125 }
126}
127
128void OLineEdit::setCompletedText( const QString& text )
129{
130 OGlobalSettings::Completion mode = completionMode();
131 bool marked = ( mode == OGlobalSettings::CompletionAuto ||
132 mode == OGlobalSettings::CompletionMan ||
133 mode == OGlobalSettings::CompletionPopup );
134 setCompletedText( text, marked );
135}
136
137void OLineEdit::rotateText( OCompletionBase::KeyBindingType type )
138{
139 OCompletion* comp = compObj();
140 if ( comp &&
141 (type == OCompletionBase::PrevCompletionMatch ||
142 type == OCompletionBase::NextCompletionMatch ) )
143 {
144 QString input = (type == OCompletionBase::PrevCompletionMatch) ? comp->previousMatch() : comp->nextMatch();
145 // Skip rotation if previous/next match is null or the same text
146 if ( input.isNull() || input == displayText() )
147 return;
148 #if QT_VERSION > 290
149 setCompletedText( input, hasSelectedText() );
150 #else
151 setCompletedText( input, hasMarkedText() );
152 #endif
153 }
154}
155
156void OLineEdit::makeCompletion( const QString& text )
157{
158 OCompletion *comp = compObj();
159 if ( !comp )
160 return; // No completion object...
161
162 QString match = comp->makeCompletion( text );
163 OGlobalSettings::Completion mode = completionMode();
164 if ( mode == OGlobalSettings::CompletionPopup )
165 {
166 if ( match.isNull() )
167 {
168 if ( d->completionBox ) {
169 d->completionBox->hide();
170 d->completionBox->clear();
171 }
172 }
173 else
174 setCompletedItems( comp->allMatches() );
175 }
176 else
177 {
178 // all other completion modes
179 // If no match or the same match, simply return without completing.
180 if ( match.isNull() || match == text )
181 return;
182
183 setCompletedText( match );
184 }
185}
186
187void OLineEdit::setReadOnly(bool readOnly)
188{
189 QPalette p = palette();
190 if (readOnly)
191 {
192 QColor color = p.color(QPalette::Disabled, QColorGroup::Background);
193 p.setColor(QColorGroup::Base, color);
194 p.setColor(QColorGroup::Background, color);
195 }
196 else
197 {
198 QColor color = p.color(QPalette::Normal, QColorGroup::Base);
199 p.setColor(QColorGroup::Base, color);
200 p.setColor(QColorGroup::Background, color);
201 }
202 setPalette(p);
203
204 QLineEdit::setReadOnly (readOnly);
205}
206
207void OLineEdit::keyPressEvent( QKeyEvent *e )
208{
209 qDebug( "OLineEdit::keyPressEvent()" );
210
211 /*
212
213 KKey key( e );
214
215 if ( KStdAccel::copy().contains( key ) ) {
216 copy();
217 return;
218 }
219 else if ( KStdAccel::paste().contains( key ) ) {
220 paste();
221 return;
222 }
223 else if ( KStdAccel::cut().contains( key ) ) {
224 cut();
225 return;
226 }
227 else if ( KStdAccel::undo().contains( key ) ) {
228 undo();
229 return;
230 }
231 else if ( KStdAccel::redo().contains( key ) ) {
232 redo();
233 return;
234 }
235 else if ( KStdAccel::deleteWordBack().contains( key ) )
236 {
237 cursorWordBackward(TRUE);
238 if ( hasSelectedText() )
239 del();
240
241 e->accept();
242 return;
243 }
244 else if ( KStdAccel::deleteWordForward().contains( key ) )
245 {
246 // Workaround for QT bug where
247 cursorWordForward(TRUE);
248 if ( hasSelectedText() )
249 del();
250
251 e->accept();
252 return;
253 }
254 */
255
256 // Filter key-events if EchoMode is normal &
257 // completion mode is not set to CompletionNone
258 if ( echoMode() == QLineEdit::Normal &&
259 completionMode() != OGlobalSettings::CompletionNone )
260 {
261 KeyBindingMap keys = getKeyBindings();
262 OGlobalSettings::Completion mode = completionMode();
263 bool noModifier = (e->state() == NoButton || e->state()== ShiftButton);
264
265 if ( (mode == OGlobalSettings::CompletionAuto ||
266 mode == OGlobalSettings::CompletionMan) && noModifier )
267 {
268 QString keycode = e->text();
269 if ( !keycode.isNull() && keycode.unicode()->isPrint() )
270 {
271 QLineEdit::keyPressEvent ( e );
272 QString txt = text();
273 int len = txt.length();
274 #if QT_VERSION > 290
275 if ( !hasSelectedText() && len && cursorPosition() == len )
276 #else
277 if ( !hasMarkedText() && len && cursorPosition() == len )
278 #endif
279 {
280 if ( emitSignals() )
281 emit completion( txt );
282 if ( handleSignals() )
283 makeCompletion( txt );
284 e->accept();
285 }
286 return;
287 }
288 }
289
290 else if ( mode == OGlobalSettings::CompletionPopup && noModifier )
291 {
292 qDebug( "OLineEdit::keyPressEvent() - global settings = CompletionPopup & noModifier" );
293
294 QString old_txt = text();
295 QLineEdit::keyPressEvent ( e );
296 QString txt = text();
297 int len = txt.length();
298 QString keycode = e->text();
299
300
301 if ( txt != old_txt && len && cursorPosition() == len &&
302 ( (!keycode.isNull() && keycode.unicode()->isPrint()) ||
303 e->key() == Key_Backspace ) )
304 {
305 if ( emitSignals() )
306 emit completion( txt ); // emit when requested...
307 if ( handleSignals() )
308 makeCompletion( txt ); // handle when requested...
309 e->accept();
310 }
311 else if (!len && d->completionBox && d->completionBox->isVisible())
312 d->completionBox->hide();
313
314 return;
315 }
316
317 /*else if ( mode == OGlobalSettings::CompletionShell )
318 {
319 // Handles completion.
320 KShortcut cut;
321 if ( keys[TextCompletion].isNull() )
322 cut = KStdAccel::shortcut(KStdAccel::TextCompletion);
323 else
324 cut = keys[TextCompletion];
325
326 if ( cut.contains( key ) )
327 {
328 // Emit completion if the completion mode is CompletionShell
329 // and the cursor is at the end of the string.
330 QString txt = text();
331 int len = txt.length();
332 if ( cursorPosition() == len && len != 0 )
333 {
334 if ( emitSignals() )
335 emit completion( txt );
336 if ( handleSignals() )
337 makeCompletion( txt );
338 return;
339 }
340 }
341 else if ( d->completionBox )
342 d->completionBox->hide();
343 }
344
345 // handle rotation
346 if ( mode != OGlobalSettings::CompletionNone )
347 {
348 // Handles previous match
349 KShortcut cut;
350 if ( keys[PrevCompletionMatch].isNull() )
351 cut = KStdAccel::shortcut(KStdAccel::PrevCompletion);
352 else
353 cut = keys[PrevCompletionMatch];
354
355 if ( cut.contains( key ) )
356 {
357 if ( emitSignals() )
358 emit textRotation( OCompletionBase::PrevCompletionMatch );
359 if ( handleSignals() )
360 rotateText( OCompletionBase::PrevCompletionMatch );
361 return;
362 }
363
364 // Handles next match
365 if ( keys[NextCompletionMatch].isNull() )
366 cut = KStdAccel::key(KStdAccel::NextCompletion);
367 else
368 cut = keys[NextCompletionMatch];
369
370 if ( cut.contains( key ) )
371 {
372 if ( emitSignals() )
373 emit textRotation( OCompletionBase::NextCompletionMatch );
374 if ( handleSignals() )
375 rotateText( OCompletionBase::NextCompletionMatch );
376 return;
377 }
378 }
379
380 // substring completion
381 if ( compObj() )
382 {
383 KShortcut cut;
384 if ( keys[SubstringCompletion].isNull() )
385 cut = KStdAccel::shortcut(KStdAccel::SubstringCompletion);
386 else
387 cut = keys[SubstringCompletion];
388
389 if ( cut.contains( key ) )
390 {
391 if ( emitSignals() )
392 emit substringCompletion( text() );
393 if ( handleSignals() )
394 {
395 setCompletedItems( compObj()->substringCompletion(text()));
396 e->accept();
397 }
398 return;
399 }
400 } */
401 }
402
403 // Let QLineEdit handle any other keys events.
404 QLineEdit::keyPressEvent ( e );
405}
406
407void OLineEdit::mouseDoubleClickEvent( QMouseEvent* e )
408{
409 if ( e->button() == Qt::LeftButton )
410 {
411 possibleTripleClick=true;
412 QTimer::singleShot( QApplication::doubleClickInterval(),this,
413 SLOT(tripleClickTimeout()) );
414 }
415 QLineEdit::mouseDoubleClickEvent( e );
416}
417
418void OLineEdit::mousePressEvent( QMouseEvent* e )
419{
420 if ( possibleTripleClick && e->button() == Qt::LeftButton )
421 {
422 selectAll();
423 return;
424 }
425 QLineEdit::mousePressEvent( e );
426}
427
428void OLineEdit::tripleClickTimeout()
429{
430 possibleTripleClick=false;
431}
432
433QPopupMenu *OLineEdit::createPopupMenu()
434{
435 // Return if popup menu is not enabled !!
436 if ( !m_bEnableMenu )
437 return 0;
438
439 #if QT_VERSION > 290
440 QPopupMenu *popup = QLineEdit::createPopupMenu();
441 #else
442 QPopupMenu *popup = new QPopupMenu();
443 #warning OLineEdit is not fully functional on Qt2
444 #endif
445
446 // completion object is present.
447 if ( compObj() )
448 {
449 QPopupMenu *subMenu = new QPopupMenu( popup );
450 connect( subMenu, SIGNAL( activated( int ) ),
451 this, SLOT( completionMenuActivated( int ) ) );
452
453 popup->insertSeparator();
454 //popup->insertItem( SmallIconSet("completion"), i18n("Text Completion"),
455 // subMenu );
456
457 popup->insertItem( tr("Text Completion"), subMenu );
458
459 subMenu->insertItem( tr("None"), NoCompletion );
460 subMenu->insertItem( tr("Manual"), ShellCompletion );
461 subMenu->insertItem( tr("Automatic"), AutoCompletion );
462 subMenu->insertItem( tr("Dropdown List"), PopupCompletion );
463 subMenu->insertItem( tr("Short Automatic"), SemiAutoCompletion );
464
465 //subMenu->setAccel( KStdAccel::completion(), ShellCompletion );
466 subMenu->setAccel( Key_Tab, ShellCompletion );
467
468 OGlobalSettings::Completion mode = completionMode();
469 subMenu->setItemChecked( NoCompletion,
470 mode == OGlobalSettings::CompletionNone );
471 subMenu->setItemChecked( ShellCompletion,
472 mode == OGlobalSettings::CompletionShell );
473 subMenu->setItemChecked( PopupCompletion,
474 mode == OGlobalSettings::CompletionPopup );
475 subMenu->setItemChecked( AutoCompletion,
476 mode == OGlobalSettings::CompletionAuto );
477 subMenu->setItemChecked( SemiAutoCompletion,
478 mode == OGlobalSettings::CompletionMan );
479 if ( mode != OGlobalSettings::completionMode() )
480 {
481 subMenu->insertSeparator();
482 subMenu->insertItem( tr("Default"), Default );
483 }
484 }
485 // ### do we really need this? Yes, Please do not remove! This
486 // allows applications to extend the popup menu without having to
487 // inherit from this class! (DA)
488 emit aboutToShowContextMenu( popup );
489
490 return popup;
491}
492
493void OLineEdit::completionMenuActivated( int id )
494{
495 OGlobalSettings::Completion oldMode = completionMode();
496
497 switch ( id )
498 {
499 case Default:
500 setCompletionMode( OGlobalSettings::completionMode() ); break;
501 case NoCompletion:
502 setCompletionMode( OGlobalSettings::CompletionNone ); break;
503 case AutoCompletion:
504 setCompletionMode( OGlobalSettings::CompletionAuto ); break;
505 case SemiAutoCompletion:
506 setCompletionMode( OGlobalSettings::CompletionMan ); break;
507 case ShellCompletion:
508 setCompletionMode( OGlobalSettings::CompletionShell ); break;
509 case PopupCompletion:
510 setCompletionMode( OGlobalSettings::CompletionPopup ); break;
511 default: return;
512 }
513
514 if ( oldMode != completionMode() )
515 {
516 if ( oldMode == OGlobalSettings::CompletionPopup &&
517 d->completionBox && d->completionBox->isVisible() )
518 d->completionBox->hide();
519 emit completionModeChanged( completionMode() );
520 }
521}
522
523/*void OLineEdit::dropEvent(QDropEvent *e)
524{
525 KURL::List urlList;
526 if( d->handleURLDrops && KURLDrag::decode( e, urlList ) )
527 {
528 QString dropText = text();
529 KURL::List::ConstIterator it;
530 for( it = urlList.begin() ; it != urlList.end() ; ++it )
531 {
532 if(!dropText.isEmpty())
533 dropText+=' ';
534
535 dropText += (*it).prettyURL();
536 }
537
538 validateAndSet( dropText, dropText.length(), 0, 0);
539
540 e->accept();
541 }
542 else
543 QLineEdit::dropEvent(e);
544}*/
545
546bool OLineEdit::eventFilter( QObject* o, QEvent* ev )
547{
548 if( o == this )
549 {
550 //OCursor::autoHideEventFilter( this, ev );
551 if ( ev->type() == QEvent::AccelOverride )
552 {
553 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
554 // if (overrideAccel (e))
555 // {
556 // e->accept();
557 // return true;
558 // }
559 }
560 else if( ev->type() == QEvent::KeyPress )
561 {
562 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
563
564 if( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
565 {
566 bool trap = d->completionBox && d->completionBox->isVisible();
567
568 // Qt will emit returnPressed() itself if we return false
569 if ( d->grabReturnKeyEvents || trap )
570 emit QLineEdit::returnPressed();
571
572 emit returnPressed( displayText() );
573
574 if ( trap )
575 d->completionBox->hide();
576
577 // Eat the event if the user asked for it, or if a completionbox was visible
578 return d->grabReturnKeyEvents || trap;
579 }
580 }
581 }
582 return QLineEdit::eventFilter( o, ev );
583}
584
585
586void OLineEdit::setURLDropsEnabled(bool enable)
587{
588 d->handleURLDrops=enable;
589}
590
591bool OLineEdit::isURLDropsEnabled() const
592{
593 return d->handleURLDrops;
594}
595
596void OLineEdit::setTrapReturnKey( bool grab )
597{
598 d->grabReturnKeyEvents = grab;
599}
600
601bool OLineEdit::trapReturnKey() const
602{
603 return d->grabReturnKeyEvents;
604}
605
606/*void OLineEdit::setURL( const KURL& url )
607{
608 QLineEdit::setText( url.prettyURL() );
609}*/
610
611void OLineEdit::makeCompletionBox()
612{
613 if ( d->completionBox )
614 return;
615
616 d->completionBox = new OCompletionBox( this, "completion box" );
617 if ( handleSignals() )
618 {
619 connect( d->completionBox, SIGNAL(highlighted( const QString& )),
620 SLOT(setText( const QString& )) );
621 connect( d->completionBox, SIGNAL(userCancelled( const QString& )),
622 SLOT(setText( const QString& )) );
623
624 // Nice lil' hacklet ;) KComboBox doesn't know when the completionbox
625 // is created (childEvent() is even more hacky, IMHO), so we simply
626 // forward the completionbox' activated signal from here.
627 if ( parentWidget() && parentWidget()->inherits("KComboBox") )
628 connect( d->completionBox, SIGNAL( activated( const QString& )),
629 parentWidget(), SIGNAL( activated( const QString & )));
630 }
631}
632
633/*bool OLineEdit::overrideAccel (const QKeyEvent* e)
634{
635 KShortcut scKey;
636
637 KKey key( e );
638 KeyBindingMap keys = getKeyBindings();
639
640 if (keys[TextCompletion].isNull())
641 scKey = KStdAccel::shortcut(KStdAccel::TextCompletion);
642 else
643 scKey = keys[TextCompletion];
644
645 if (scKey.contains( key ))
646 return true;
647
648 if (keys[NextCompletionMatch].isNull())
649 scKey = KStdAccel::shortcut(KStdAccel::NextCompletion);
650 else
651 scKey = keys[NextCompletionMatch];
652
653 if (scKey.contains( key ))
654 return true;
655
656 if (keys[PrevCompletionMatch].isNull())
657 scKey = KStdAccel::shortcut(KStdAccel::PrevCompletion);
658 else
659 scKey = keys[PrevCompletionMatch];
660
661 if (scKey.contains( key ))
662 return true;
663
664 if (KStdAccel::deleteWordBack().contains( key ))
665 return true;
666 if (KStdAccel::deleteWordForward().contains( key ))
667 return true;
668
669 if (d->completionBox && d->completionBox->isVisible ())
670 if (e->key () == Key_Backtab)
671 return true;
672
673 return false;
674}*/
675
676void OLineEdit::setCompletedItems( const QStringList& items )
677{
678 QString txt = text();
679 if ( !items.isEmpty() &&
680 !(items.count() == 1 && txt == items.first()) )
681 {
682 if ( !d->completionBox )
683 makeCompletionBox();
684
685 if ( !txt.isEmpty() )
686 d->completionBox->setCancelledText( txt );
687 d->completionBox->setItems( items );
688 d->completionBox->popup();
689 }
690 else
691 {
692 if ( d->completionBox && d->completionBox->isVisible() )
693 d->completionBox->hide();
694 }
695}
696
697OCompletionBox * OLineEdit::completionBox( bool create )
698{
699 if ( create )
700 makeCompletionBox();
701
702 return d->completionBox;
703}
704
705void OLineEdit::setCompletionObject( OCompletion* comp, bool hsig )
706{
707 OCompletion *oldComp = compObj();
708 if ( oldComp && handleSignals() )
709 disconnect( oldComp, SIGNAL( matches( const QStringList& )),
710 this, SLOT( setCompletedItems( const QStringList& )));
711
712 if ( comp && hsig )
713 connect( comp, SIGNAL( matches( const QStringList& )),
714 this, SLOT( setCompletedItems( const QStringList& )));
715
716 OCompletionBase::setCompletionObject( comp, hsig );
717}
718
719// QWidget::create() turns off mouse-Tracking which would break auto-hiding
720void OLineEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
721{
722 QLineEdit::create( id, initializeWindow, destroyOldWindow );
723 //OCursor::setAutoHideCursor( this, true, true );
724}
725
726void OLineEdit::clear()
727{
728 setText( QString::null );
729}
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 @@
1/*
2 This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
3 is part of the Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>, Dawit Alemayehu <adawit@kde.org>
4 Opie Project Copyright (C) 1999 Preston Brown <pbrown@kde.org>, Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
5 Copyright (C) 1997 Sven Radej (sven.radej@iname.com)
6 =.
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33#ifndef OLINEEDIT_H
34#define OLINEEDIT_H
35
36/* QT */
37
38#include <qlineedit.h>
39
40/* OPIE */
41
42#include <opie2/ocompletion.h>
43#include <opie2/ocompletionbase.h>
44
45class QPopupMenu;
46
47class OCompletionBox;
48typedef QString KURL; //class KURL;
49
50/**
51 * An enhanced QLineEdit widget for inputting text.
52 *
53 * @sect Detail
54 *
55 * This widget inherits from @ref QLineEdit and implements the following
56 * additional functionalities: q completion object that provides both
57 * automatic and manual text completion as well as multiple match iteration
58 * features, configurable key-bindings to activate these features and a
59 * popup-menu item that can be used to allow the user to set text completion
60 * modes on the fly based on their preference.
61 *
62 * To support these new features OLineEdit also emits a few more
63 * additional signals. These are: @ref completion( const QString& ),
64 * textRotation( KeyBindingType ), and @ref returnPressed( const QString& ).
65 * The completion signal can be connected to a slot that will assist the
66 * user in filling out the remaining text. The text rotation signal is
67 * intended to be used to iterate through the list of all possible matches
68 * whenever there is more than one match for the entered text. The
69 * @p returnPressed( const QString& ) signals are the same as QLineEdit's
70 * except it provides the current text in the widget as its argument whenever
71 * appropriate.
72 *
73 * This widget by default creates a completion object when you invoke
74 * the @ref completionObject( bool ) member function for the first time or
75 * use @ref setCompletionObject( OCompletion*, bool ) to assign your own
76 * completion object. Additionally, to make this widget more functional,
77 * OLineEdit will by default handle the text rotation and completion
78 * events internally when a completion object is created through either one
79 * of the methods mentioned above. If you do not need this functionality,
80 * simply use @ref OCompletionBase::setHandleSignals( bool ) or set the
81 * boolean parameter in the above functions to FALSE.
82 *
83 * The default key-bindings for completion and rotation is determined
84 * from the global settings in @ref OStdAccel. These values, however,
85 * can be overriden locally by invoking @ref OCompletionBase::setKeyBinding().
86 * The values can easily be reverted back to the default setting, by simply
87 * calling @ref useGlobalSettings(). An alternate method would be to default
88 * individual key-bindings by usning @ref setKeyBinding() with the default
89 * second argument.
90 *
91 * NOTE that if the @p EchoMode for this widget is set to something other
92 * than @p QLineEdit::Normal, the completion mode will always be defaulted
93 * to @ref PGlobalSettings::CompletionNone. This is done purposefully to guard
94 * against protected entries such as passwords being cached in @ref OCompletion's
95 * list. Hence, if the @p EchoMode is not @ref QLineEdit::Normal, the completion
96 * mode is automatically disabled.
97 *
98 * @sect Useage
99 *
100 * To enable the basic completion feature :
101 *
102 * <pre>
103 * OLineEdit *edit = new OLineEdit( this, "mywidget" );
104 * OCompletion *comp = edit->completionObject();
105 * // Fill the completion object with a list of possible matches
106 * QStringList list;
107 * list << "mickeyl@handhelds.org" << "mickey@tm.informatik.uni-frankfurt.de>" << "mickey@Vanille.de";
108 * comp->setItems( list );
109 * // Connect to the return pressed signal (optional)
110 * connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
111 * </pre>
112 *
113 * To use a customized completion objects or your
114 * own completion object :
115 *
116 * <pre>
117 * OLineEdit *edit = new OLineEdit( this,"mywidget" );
118 * KURLCompletion *comp = new KURLCompletion();
119 * edit->setCompletionObject( comp );
120 * // Connect to the return pressed signal - optional
121 * connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&));
122 * </pre>
123 *
124 * Note that you have to either delete the allocated completion object
125 * when you don't need it anymore, or call
126 * setAutoDeleteCompletionObject( true );
127 *
128 * @sect Miscellaneous function calls :
129 *
130 * <pre>
131 * // Tell the widget not to handle completion and
132 * // iteration internally.
133 * edit->setHandleSignals( false );
134 * // Set your own completion key for manual completions.
135 * edit->setKeyBinding( OCompletionBase::TextCompletion, Qt::End );
136 * // Hide the context (popup) menu
137 * edit->setContextMenuEnabled( false );
138 * // Temporarly disable signal emitions
139 * // (both completion & iteration signals)
140 * edit->disableSignals();
141 * // Default the key-bindings to system settings.
142 * edit->useGlobalKeyBindings();
143 * </pre>
144 *
145 * @short An enhanced single line input widget.
146 * @author Dawit Alemayehu <adawit@kde.org>
147 * @author Opie adaption by Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
148 */
149
150class OLineEdit : public QLineEdit, public OCompletionBase
151{
152 friend class OComboBox;
153
154 Q_OBJECT
155 Q_PROPERTY( bool contextMenuEnabled READ isContextMenuEnabled WRITE setContextMenuEnabled )
156 Q_PROPERTY( bool urlDropsEnabled READ isURLDropsEnabled WRITE setURLDropsEnabled )
157
158public:
159
160 /**
161 * Constructs a OLineEdit object with a default text, a parent,
162 * and a name.
163 *
164 * @param string Text to be shown in the edit widget.
165 * @param parent The parent object of this widget.
166 * @param name the name of this widget
167 */
168 OLineEdit( const QString &string, QWidget *parent, const char *name = 0 );
169
170 /**
171 * Constructs a OLineEdit object with a parent and a name.
172 *
173 * @param string Text to be shown in the edit widget.
174 * @param parent The parent object of this widget.
175 * @param name The name of this widget.
176 */
177 OLineEdit ( QWidget *parent=0, const char *name=0 );
178
179 /**
180 * Destructor.
181 */
182 virtual ~OLineEdit ();
183
184 /**
185 * Sets @p url into the lineedit. It uses @ref KURL::prettyURL() so
186 * that the url is properly decoded for displaying.
187 */
188 void setURL( const KURL& url );
189
190 /**
191 * Puts the text cursor at the end of the string.
192 *
193 * This method is deprecated. Use @ref QLineEdit::end()
194 * instead.
195 *
196 * @deprecated
197 * @ref QLineEdit::end()
198 */
199 void cursorAtEnd() { end( false ); }
200
201 /**
202 * Re-implemented from @ref OCompletionBase for internal reasons.
203 *
204 * This function is re-implemented in order to make sure that
205 * the EchoMode is acceptable before we set the completion mode.
206 *
207 * See @ref OCompletionBase::setCompletionMode
208 */
209 virtual void setCompletionMode( OGlobalSettings::Completion mode );
210
211 /**
212 * Enables/disables the popup (context) menu.
213 *
214 * Note that when this function is invoked with its argument
215 * set to @p true, then both the context menu and the completion
216 * menu item are enabled. If you do not want to the completion
217 * item to be visible simply invoke @ref hideModechanger() right
218 * after calling this method. Also by default, the context
219 * menu is automatically created if this widget is editable. Thus
220 * you need to call this function with the argument set to false
221 * if you do not want this behaviour.
222 *
223 * @param showMenu If @p true, show the context menu.
224 */
225 virtual void setContextMenuEnabled( bool showMenu ) { m_bEnableMenu = showMenu; }
226
227 /**
228 * Returns @p true when the context menu is enabled.
229 */
230 bool isContextMenuEnabled() const { return m_bEnableMenu; }
231
232 /**
233 * Enables/Disables handling of URL drops. If enabled and the user
234 * drops an URL, the decoded URL will be inserted. Otherwise the default
235 * behaviour of QLineEdit is used, which inserts the encoded URL.
236 *
237 * @param enable If @p true, insert decoded URLs
238 */
239 void setURLDropsEnabled( bool enable );
240
241 /**
242 * Returns @p true when decoded URL drops are enabled
243 */
244 bool isURLDropsEnabled() const;
245
246 /**
247 * By default, OLineEdit recognizes @p Key_Return and @p Key_Enter and emits
248 * the @ref returnPressed() signals, but it also lets the event pass,
249 * for example causing a dialog's default-button to be called.
250 *
251 * Call this method with @p trap = @p true to make @p OLineEdit stop these
252 * events. The signals will still be emitted of course.
253 *
254 * @see trapReturnKey()
255 */
256 void setTrapReturnKey( bool trap );
257
258 /**
259 * @returns @p true if keyevents of @p Key_Return or
260 * @p Key_Enter will be stopped or if they will be propagated.
261 *
262 * @see setTrapReturnKey ()
263 */
264 bool trapReturnKey() const;
265
266 /**
267 * Re-implemented for internal reasons. API not affected.
268 *
269 * @reimplemented
270 */
271 virtual bool eventFilter( QObject *, QEvent * );
272
273 /**
274 * @returns the completion-box, that is used in completion mode
275 * @ref KGlobalSettings::CompletionPopup.
276 * This method will create a completion-box if none is there, yet.
277 *
278 * @param create Set this to false if you don't want the box to be created
279 * i.e. to test if it is available.
280 */
281 OCompletionBox * completionBox( bool create = true );
282
283 /**
284 * Reimplemented for internal reasons, the API is not affected.
285 */
286 virtual void setCompletionObject( OCompletion *, bool hsig = true );
287
288
289signals:
290
291 /**
292 * Emitted when the user presses the return key.
293 *
294 * The argument is the current text. Note that this
295 * signal is @em not emitted if the widget's @p EchoMode is set to
296 * @ref QLineEdit::EchoMode.
297 */
298 void returnPressed( const QString& );
299
300 /**
301 * Emitted when the completion key is pressed.
302 *
303 * Please note that this signal is @em not emitted if the
304 * completion mode is set to @p CompletionNone or @p EchoMode is
305 * @em normal.
306 */
307 void completion( const QString& );
308
309 /**
310 * Emitted when the shortcut for substring completion is pressed.
311 */
312 void substringCompletion( const QString& );
313
314 /**
315 * Emitted when the text rotation key-bindings are pressed.
316 *
317 * The argument indicates which key-binding was pressed.
318 * In OLineEdit's case this can be either one of two values:
319 * @ref PrevCompletionMatch or @ref NextCompletionMatch. See
320 * @ref OCompletionBase::setKeyBinding for details.
321 *
322 * Note that this signal is @em not emitted if the completion
323 * mode is set to @p KGlobalSettings::CompletionNone or @p echoMode() is @em not normal.
324 */
325 void textRotation( OCompletionBase::KeyBindingType );
326
327 /**
328 * Emitted when the user changed the completion mode by using the
329 * popupmenu.
330 */
331 void completionModeChanged( OGlobalSettings::Completion );
332
333 /**
334 * Emitted before the context menu is displayed.
335 *
336 * The signal allows you to add your own entries into the
337 * the context menu that is created on demand.
338 *
339 * NOTE: Do not store the pointer to the QPopupMenu
340 * provided through since it is created and deleted
341 * on demand.
342 *
343 * @param the context menu about to be displayed
344 */
345 void aboutToShowContextMenu( QPopupMenu* );
346
347public slots:
348
349 /**
350 * Re-implemented for internal reasons. API not changed.
351 */
352 virtual void setReadOnly(bool);
353
354 /**
355 * Iterates through all possible matches of the completed text or
356 * the history list.
357 *
358 * This function simply iterates over all possible matches in case
359 * multimple matches are found as a result of a text completion request.
360 * It will have no effect if only a single match is found.
361 *
362 * @param type The key-binding invoked.
363 */
364 void rotateText( OCompletionBase::KeyBindingType /* type */ );
365
366 /**
367 * See @ref OCompletionBase::setCompletedText.
368 */
369 virtual void setCompletedText( const QString& );
370
371 /**
372 * Sets @p items into the completion-box if @ref completionMode() is
373 * CompletionPopup. The popup will be shown immediately.
374 */
375 void setCompletedItems( const QStringList& items );
376
377 /**
378 * Reimplemented to workaround a buggy QLineEdit::clear()
379 * (changing the clipboard to the text we just had in the lineedit)
380 */
381 virtual void clear();
382
383protected slots:
384
385 /**
386 * Completes the remaining text with a matching one from
387 * a given list.
388 */
389 virtual void makeCompletion( const QString& );
390
391 /**
392 * @deprecated. Will be removed in the next major release!
393 */
394 void slotAboutToShow() {}
395
396 /**
397 * @deprecated. Will be removed in the next major release!
398 */
399 void slotCancelled() {}
400
401protected:
402
403 /**
404 * Re-implemented for internal reasons. API not affected.
405 *
406 * See @ref QLineEdit::keyPressEvent().
407 */
408 virtual void keyPressEvent( QKeyEvent * );
409
410 /**
411 * Re-implemented for internal reasons. API not affected.
412 *
413 * See @ref QLineEdit::mousePressEvent().
414 */
415 virtual void mousePressEvent( QMouseEvent * );
416
417 /**
418 * Re-implemented for internal reasons. API not affected.
419 *
420 * See @ref QWidget::mouseDoubleClickEvent().
421 */
422 virtual void mouseDoubleClickEvent( QMouseEvent * );
423
424 /**
425 * Re-implemented for internal reasons. API not affected.
426 *
427 * See @ref QLineEdit::createPopupMenu().
428 */
429 virtual QPopupMenu *createPopupMenu();
430
431 /**
432 * Re-implemented to handle URI drops.
433 *
434 * See @ref QLineEdit::dropEvent().
435 */
436 //virtual void dropEvent( QDropEvent * );
437
438 /*
439 * This function simply sets the lineedit text and
440 * highlights the text appropriately if the boolean
441 * value is set to true.
442 *
443 * @param text
444 * @param marked
445 */
446 virtual void setCompletedText( const QString& /*text*/, bool /*marked*/ );
447
448 /**
449 * Reimplemented for internal reasons, the API is not affected.
450 */
451 virtual void create( WId = 0, bool initializeWindow = true,
452 bool destroyOldWindow = true );
453
454private slots:
455 void completionMenuActivated( int id );
456 void tripleClickTimeout(); // resets possibleTripleClick
457
458private:
459 // Constants that represent the ID's of the popup menu.
460 // TODO: See if we can replace this mess with KActionMenu
461 // in the future though it's working lovely.
462 enum MenuID {
463 Default = 42,
464 NoCompletion,
465 AutoCompletion,
466 ShellCompletion,
467 PopupCompletion,
468 SemiAutoCompletion
469 };
470
471 /**
472 * Initializes variables. Called from the constructors.
473 */
474 void init();
475
476 /**
477 * Creates the completion box
478 */
479 void makeCompletionBox();
480
481 /**
482 * Checks whether we should/should not consume a key used as
483 * an accelerator.
484 */
485 //bool overrideAccel (const QKeyEvent* e);
486
487 bool m_bEnableMenu;
488
489 bool possibleTripleClick; // set in mousePressEvent, deleted in tripleClickTimeout
490
491protected:
492 //virtual void virtual_hook( int id, void* data );
493private:
494 class OLineEditPrivate;
495 OLineEditPrivate *d;
496};
497
498#endif