author | mickeyl <mickeyl> | 2003-03-28 15:11:52 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2003-03-28 15:11:52 (UTC) |
commit | 11304d02942e9fa493e4e80943a828f9c65f6772 (patch) (unidiff) | |
tree | a0223c10c067e1afc70d15c2b82be3f3c15e41ae /libopie2 | |
parent | b271d575fa05cf570a1a829136517761bd47e69b (diff) | |
download | opie-11304d02942e9fa493e4e80943a828f9c65f6772.zip opie-11304d02942e9fa493e4e80943a828f9c65f6772.tar.gz opie-11304d02942e9fa493e4e80943a828f9c65f6772.tar.bz2 |
skeleton and the start of libopie2, please read README, ROADMAP and STATUS and comment...
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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 | -------------------------------------------------------- | ||
14 | 1. General Overview | ||
15 | -------------------------------------------------------- | ||
16 | |||
17 | libopie is functionally seperated into the following libraries: | ||
18 | - libopiecore | ||
19 | - libopieui | ||
20 | - libopiepim | ||
21 | - libopiedb | ||
22 | - libopienet | ||
23 | |||
24 | 1.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 | |||
50 | 1.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 | |||
84 | 1.3 Contents of libopiepim [ opiepim ] | ||
85 | -------------------------------------------------------- | ||
86 | |||
87 | - ocheckitem | ||
88 | - todoevent | ||
89 | - todoresource | ||
90 | - todayplugininterface | ||
91 | - todovcalresource | ||
92 | |||
93 | 1.4 Contents of libopiedb [ opiedb ] | ||
94 | -------------------------------------------------------- | ||
95 | |||
96 | - tododb | ||
97 | - xmltree | ||
98 | |||
99 | 1.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 | -------------------------------------------------------- | ||
128 | 2.0 Feature Description | ||
129 | -------------------------------------------------------- | ||
130 | |||
131 | 2.1 libopiecore | ||
132 | |||
133 | ... | ||
134 | |||
135 | 2.2 libopieui | ||
136 | |||
137 | ... | ||
138 | |||
139 | 2.3 libopiepim | ||
140 | |||
141 | ... | ||
142 | |||
143 | 2.4 libopiedb | ||
144 | |||
145 | ... | ||
146 | |||
147 | 2.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 | ================================================================== | ||
3 | March 2003 - Initial checkin into the Opie CVS: | ||
4 | ================================================================== | ||
5 | |||
6 | So, this is what I have been working on over the last months. | ||
7 | It's a part of what I think could migrate into our next generation | ||
8 | opielibs. | ||
9 | Of course this won't happen after we released Opie 1.0 and switched | ||
10 | to Qt3-Embedded and gcc 3. | ||
11 | |||
12 | Right now, there is content only in opiecore, opienet and opieui. | ||
13 | A good part of code has been adapted from the kdelibs, which overall | ||
14 | are pretty good however in details of heterogenous quality. I'm also | ||
15 | not sure if all I ported should be kept, e.g. the pixmapeffect stuff | ||
16 | seems unnecesary to me. However, we should not forget that Opie will | ||
17 | make its debut on more powerful devices with greater display | ||
18 | resolution, e.g. the Sharp C700, so we shouldn't limit ourselves in | ||
19 | what should go into the libraries. | ||
20 | |||
21 | Generally spoken, a lot of things are still very rough and messy, | ||
22 | but I will keep improving this. Some details about what is usable | ||
23 | and what is not follows: | ||
24 | (everything compiles of course, otherwise I wouldn't have checked in :-) | ||
25 | |||
26 | [-----------] | ||
27 | [ opiecore ] | ||
28 | [-----------] | ||
29 | oapplication, oconfig, oglobal seem to be usable yet, oglobalsettings | ||
30 | is still very messy and should be revised. A lot more thinking about how | ||
31 | we should keep opie preferences, especially when moving to multi-user, has to be made. | ||
32 | This will affect what goes into oglobalsettings and what configuration data | ||
33 | format we will use. If we switch to Qt3 we will have to decide if we stay | ||
34 | with OConfig deriving from Config or rewrite it using QSettings. | ||
35 | |||
36 | [-----------] | ||
37 | [ opiedb ] | ||
38 | [-----------] | ||
39 | There is nothing here yet. The sqlite stuff should be here. | ||
40 | |||
41 | [-----------] | ||
42 | [ opienet ] | ||
43 | [-----------] | ||
44 | onetwork*, omonitoring* and the opacket stuff are pretty usable and not | ||
45 | very far from being complete. documentation for these will come... | ||
46 | Over the next days, opie-wellenreiter, opie-wirelessapplet and the | ||
47 | forthcoming new opie-networkapplet will be using the | ||
48 | new network classes. | ||
49 | I think all the other network libraries spread throught opie, e.g. | ||
50 | libbend, libmail, ftplib should be revised and become part of | ||
51 | opienet eventually. | ||
52 | |||
53 | [-----------] | ||
54 | [ opiepim ] | ||
55 | [-----------] | ||
56 | Nothing here yet. The stuff currently in libopie/pim should be here. | ||
57 | |||
58 | [-----------] | ||
59 | [ opieui ] | ||
60 | [-----------] | ||
61 | Pretty messy yet, but some things are usable. Unfortunately, the UI | ||
62 | stuff is very hard to backport to Qt2, so some things only work | ||
63 | if compiled against Qt3, especially all the popupcompletion stuff. | ||
64 | OListView however works nice and is currently used in opie-wellenreiter. | ||
65 | |||
66 | ================================================================== | ||
67 | October 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 @@ | |||
1 | menu "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 | ||
9 | endmenu | ||
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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 @@ | |||
1 | TEMPLATE = subdirs | ||
2 | unix: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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 | |||
5 | int 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 @@ | |||
1 | TEMPLATE = app | ||
2 | CONFIG = qt warn_on debug | ||
3 | HEADERS = | ||
4 | SOURCES = oconfigdemo.cpp | ||
5 | |||
6 | INCLUDEPATH += $(OPIEDIR)/include | ||
7 | DEPENDPATH += $(OPIEDIR)/include | ||
8 | LIBS += -lopiecore2 | ||
9 | TARGET = oconfigdemo | ||
10 | MOC_DIR = moc | ||
11 | OBJECTS_DIR = obj | ||
12 | |||
13 | include ( $(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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 | |||
20 | class DemoApp : public OApplication | ||
21 | { | ||
22 | Q_OBJECT | ||
23 | public: | ||
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 | |||
86 | public 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 | |||
123 | private: | ||
124 | QButtonGroup* g; | ||
125 | int m; | ||
126 | QLineEdit* e; | ||
127 | }; | ||
128 | |||
129 | int 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 @@ | |||
1 | TEMPLATE = app | ||
2 | CONFIG = qt warn_on debug | ||
3 | HEADERS = | ||
4 | SOURCES = odebugdemo.cpp | ||
5 | INCLUDEPATH += $(OPIEDIR)/include | ||
6 | DEPENDPATH += $(OPIEDIR)/include | ||
7 | LIBS += -lopiecore2 | ||
8 | TARGET = odebugdemo | ||
9 | MOC_DIR = moc | ||
10 | OBJECTS_DIR = obj | ||
11 | |||
12 | include ( $(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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 | |||
4 | int 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 @@ | |||
1 | TEMPLATE = app | ||
2 | CONFIG = qt warn_on debug | ||
3 | HEADERS = | ||
4 | SOURCES = oglobalsettingsdemo.cpp | ||
5 | INCLUDEPATH += $(OPIEDIR)/include | ||
6 | DEPENDPATH += $(OPIEDIR)/include | ||
7 | LIBS += -lopiecore2 | ||
8 | TARGET = oglobalsettingsdemo | ||
9 | MOC_DIR = moc | ||
10 | OBJECTS_DIR = obj | ||
11 | |||
12 | include ( $(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 @@ | |||
1 | TEMPLATE = subdirs | ||
2 | unix: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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 | |||
14 | class 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 | |||
26 | QDict<Station> stations; | ||
27 | |||
28 | //======================== Application class =============================== | ||
29 | |||
30 | class Wellenreiter : public QApplication | ||
31 | { | ||
32 | Q_OBJECT | ||
33 | public: | ||
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 | |||
162 | public 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 | } | ||
185 | private: | ||
186 | OPacketCapturer* cap; | ||
187 | OWirelessNetworkInterface* wiface; | ||
188 | }; | ||
189 | |||
190 | |||
191 | int 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 @@ | |||
1 | TEMPLATE = app | ||
2 | CONFIG = qt warn_on debug | ||
3 | HEADERS = | ||
4 | SOURCES = miniwellenreiter.cpp | ||
5 | INCLUDEPATH += $(OPIEDIR)/include | ||
6 | DEPENDPATH += $(OPIEDIR)/include | ||
7 | LIBS += -lopiecore2 -lopienet2 | ||
8 | TARGET = miniwellenreiter | ||
9 | MOC_DIR = moc | ||
10 | OBJECTS_DIR = obj | ||
11 | |||
12 | include ( $(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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 | |||
3 | int 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 @@ | |||
1 | TEMPLATE = app | ||
2 | CONFIG = qt warn_on debug | ||
3 | HEADERS = | ||
4 | SOURCES = onetworkdemo.cpp | ||
5 | INCLUDEPATH += $(OPIEDIR)/include | ||
6 | DEPENDPATH += $(OPIEDIR)/include | ||
7 | LIBS += -lopiecore2 -lopienet2 | ||
8 | TARGET = onetworkdemo | ||
9 | MOC_DIR = moc | ||
10 | OBJECTS_DIR = obj | ||
11 | |||
12 | include ( $(OPIEDIR)/include.pro ) | ||
diff --git a/libopie2/examples/opienet/opienet.pro b/libopie2/examples/opienet/opienet.pro new file mode 100644 index 0000000..c7800a9 --- a/dev/null +++ b/libopie2/examples/opienet/opienet.pro | |||
@@ -0,0 +1,3 @@ | |||
1 | TEMPLATE = subdirs | ||
2 | SUBDIRS = 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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 | |||
20 | int 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 @@ | |||
1 | TEMPLATE = app | ||
2 | CONFIG = qt warn_on debug | ||
3 | HEADERS = opieuidemo.h \ | ||
4 | oversatileviewdemo.h | ||
5 | SOURCES = opieuidemo.cpp \ | ||
6 | oversatileviewdemo.cpp \ | ||
7 | main.cpp | ||
8 | INCLUDEPATH += $(OPIEDIR)/include | ||
9 | DEPENDPATH += $(OPIEDIR)/include | ||
10 | LIBS += -lopieui2 -lopiecore2 | ||
11 | TARGET = opieuidemo | ||
12 | MOC_DIR = moc | ||
13 | OBJECTS_DIR = obj | ||
14 | |||
15 | include ( $(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> | ||
37 | using 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 | |||
54 | enum Demos { ocompletionbox, olineedit, ocombobox, oeditlistbox, oselector }; | ||
55 | |||
56 | OpieUIDemo::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 | |||
74 | OpieUIDemo::~OpieUIDemo() | ||
75 | { | ||
76 | } | ||
77 | |||
78 | void 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 | |||
88 | void 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 | |||
102 | void 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 | |||
118 | void 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 | |||
138 | void 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 | |||
163 | void 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 | |||
188 | void 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 | |||
200 | void 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 | |||
21 | class OVersatileView; | ||
22 | class QTabWidget; | ||
23 | class QVBox; | ||
24 | |||
25 | class OpieUIDemo : public QMainWindow { | ||
26 | Q_OBJECT | ||
27 | |||
28 | public: | ||
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 | |||
39 | public slots: | ||
40 | void demo( int ); | ||
41 | void messageBox( const QString& text ); | ||
42 | |||
43 | protected: | ||
44 | void build(); | ||
45 | void buildVV( QVBox* b ); | ||
46 | |||
47 | private: | ||
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 | |||
41 | OVersatileViewDemo::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 | |||
97 | OVersatileViewDemo::~OVersatileViewDemo() | ||
98 | { | ||
99 | } | ||
100 | |||
101 | void OVersatileViewDemo::selectionChanged() | ||
102 | { | ||
103 | qDebug( "received signal selectionChanged()" ); | ||
104 | } | ||
105 | void OVersatileViewDemo::selectionChanged( OVersatileViewItem * item ) | ||
106 | { | ||
107 | qDebug( "received signal selectionChanged(OVersatileViewItem*)" ); | ||
108 | } | ||
109 | void OVersatileViewDemo::currentChanged( OVersatileViewItem * item ) | ||
110 | { | ||
111 | qDebug( "received signal currentChanged( OVersatileViewItem * )" ); | ||
112 | } | ||
113 | void OVersatileViewDemo::clicked( OVersatileViewItem * item ) | ||
114 | { | ||
115 | qDebug( "received signal clicked( OVersatileViewItem * )" ); | ||
116 | } | ||
117 | void OVersatileViewDemo::pressed( OVersatileViewItem * item ) | ||
118 | { | ||
119 | qDebug( "received signal pressed( OVersatileViewItem * )" ); | ||
120 | } | ||
121 | |||
122 | void OVersatileViewDemo::doubleClicked( OVersatileViewItem *item ) | ||
123 | { | ||
124 | qDebug( "received signal doubleClicked( OVersatileViewItem *item )" ); | ||
125 | } | ||
126 | void OVersatileViewDemo::returnPressed( OVersatileViewItem *item ) | ||
127 | { | ||
128 | qDebug( "received signal returnPressed( OVersatileViewItem *item )" ); | ||
129 | } | ||
130 | |||
131 | void OVersatileViewDemo::onItem( OVersatileViewItem *item ) | ||
132 | { | ||
133 | qDebug( "received signal onItem( OVersatileViewItem *item )" ); | ||
134 | } | ||
135 | void OVersatileViewDemo::onViewport() | ||
136 | { | ||
137 | qDebug( "received signal onViewport()" ); | ||
138 | } | ||
139 | |||
140 | void OVersatileViewDemo::expanded( OVersatileViewItem *item ) | ||
141 | { | ||
142 | qDebug( "received signal expanded( OVersatileViewItem *item )" ); | ||
143 | } | ||
144 | |||
145 | void OVersatileViewDemo::collapsed( OVersatileViewItem *item ) | ||
146 | { | ||
147 | qDebug( "received signal collapsed( OVersatileViewItem *item )" ); | ||
148 | } | ||
149 | |||
150 | void OVersatileViewDemo::moved() | ||
151 | { | ||
152 | qDebug( "received signal moved( OVersatileViewItem *item )" ); | ||
153 | } | ||
154 | |||
155 | void 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 | |||
37 | class OVersatileView; | ||
38 | class OVersatileViewItem; | ||
39 | |||
40 | class 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 @@ | |||
1 | Files: $OPIEDIR/lib/libopiecore2.so.1.8.1 $OPIEDIR/lib/libopiecore2.so.1.8 $OPIEDIR/lib/libopiecore2.so.1 $OPIEDIR/lib/libopienet2.so.1.8.1 $OPIEDIR/lib/libopienet2.so.1.8 $OPIEDIR/lib/libopienet2.so.1 $OPIEDIR/lib/libopieui2.so.1.8.1 $OPIEDIR/lib/libopieui2.so.1.8 $OPIEDIR/lib/libopieui2.so.1 | ||
2 | Priority: optional | ||
3 | Section: opie/system | ||
4 | Maintainer: Opie Team <opie@handhelds.org> | ||
5 | Architecture: arm | ||
6 | Version: 1.8.1 | ||
7 | Depends: libqpe1 | ||
8 | Provides: libopie2 | ||
9 | Replaces: libopie2 | ||
10 | Description: Opie library 2.0 | ||
diff --git a/libopie2/libopie2.postinst b/libopie2/libopie2.postinst new file mode 100755 index 0000000..0c37b3d --- a/dev/null +++ b/libopie2/libopie2.postinst | |||
@@ -0,0 +1,4 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | [ -x /sbin/ldconfig ] && /sbin/ldconfig | ||
4 | exit 0 | ||
diff --git a/libopie2/libopie2.pro b/libopie2/libopie2.pro new file mode 100644 index 0000000..0b52abc --- a/dev/null +++ b/libopie2/libopie2.pro | |||
@@ -0,0 +1,4 @@ | |||
1 | TEMPLATE = subdirs | ||
2 | unix:SUBDIRS = opiecore opiedb opiepim opieui opienet examples | ||
3 | |||
4 | include ( $(OPIEDIR)/include.pro ) | ||
diff --git a/libopie2/opiecore/.cvsignore b/libopie2/opiecore/.cvsignore new file mode 100644 index 0000000..8f7300c --- a/dev/null +++ b/libopie2/opiecore/.cvsignore | |||
@@ -0,0 +1,6 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 | |||
34 | OApplication* OApplication::_instance = 0; | ||
35 | |||
36 | /**************************************************************************************************/ | ||
37 | /* OApplicationPrivate | ||
38 | /**************************************************************************************************/ | ||
39 | |||
40 | class OApplicationPrivate | ||
41 | { | ||
42 | public: | ||
43 | OApplicationPrivate() {}; | ||
44 | ~OApplicationPrivate() {}; | ||
45 | }; | ||
46 | |||
47 | /**************************************************************************************************/ | ||
48 | /* OApplication | ||
49 | /**************************************************************************************************/ | ||
50 | |||
51 | |||
52 | OApplication::OApplication( int& argc, char** argv, const QCString& rAppName ) | ||
53 | :OApplicationBaseClass( argc, argv ), | ||
54 | _appname( rAppName ), | ||
55 | _config( 0 ) | ||
56 | { | ||
57 | init(); | ||
58 | } | ||
59 | |||
60 | |||
61 | OApplication::~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 | |||
72 | OConfig* OApplication::config() | ||
73 | { | ||
74 | if ( not _config ) | ||
75 | { | ||
76 | _config = new OConfig( _appname ); | ||
77 | } | ||
78 | return _config; | ||
79 | } | ||
80 | |||
81 | |||
82 | void 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 | |||
95 | void OApplication::setMainWidget( QWidget* widget ) | ||
96 | { | ||
97 | showMainWidget( widget ); | ||
98 | } | ||
99 | |||
100 | void 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 | |||
44 | class OApplicationPrivate; | ||
45 | class OConfig; | ||
46 | |||
47 | class 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 | |||
41 | OConfig::OConfig( const QString &name, Domain domain ) | ||
42 | :Config( name, domain ) | ||
43 | { | ||
44 | } | ||
45 | |||
46 | OConfig::~OConfig() | ||
47 | { | ||
48 | } | ||
49 | |||
50 | QColor 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 | |||
110 | QFont 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 | |||
39 | class QColor; | ||
40 | class 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 | |||
47 | class 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 | |||
135 | class 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 | |||
85 | enum 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 | |||
100 | static 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 | |||
228 | odbgstream& perror( odbgstream &s) | ||
229 | { | ||
230 | return s << QString::fromLocal8Bit(strerror(errno)); | ||
231 | } | ||
232 | |||
233 | odbgstream odDebug(int area) | ||
234 | { | ||
235 | return odbgstream(area, ODEBUG_INFO); | ||
236 | } | ||
237 | odbgstream odDebug(bool cond, int area) | ||
238 | { | ||
239 | if (cond) return odbgstream(area, ODEBUG_INFO); | ||
240 | else return odbgstream(0, 0, false); | ||
241 | } | ||
242 | |||
243 | odbgstream odError(int area) | ||
244 | { | ||
245 | return odbgstream("ERROR: ", area, ODEBUG_ERROR); | ||
246 | } | ||
247 | |||
248 | odbgstream odError(bool cond, int area) | ||
249 | { | ||
250 | if (cond) return odbgstream("ERROR: ", area, ODEBUG_ERROR); else return odbgstream(0,0,false); | ||
251 | } | ||
252 | |||
253 | odbgstream odWarning(int area) | ||
254 | { | ||
255 | return odbgstream("WARNING: ", area, ODEBUG_WARN); | ||
256 | } | ||
257 | |||
258 | odbgstream odWarning(bool cond, int area) | ||
259 | { | ||
260 | if (cond) return odbgstream("WARNING: ", area, ODEBUG_WARN); else return odbgstream(0,0,false); | ||
261 | } | ||
262 | |||
263 | odbgstream odFatal(int area) | ||
264 | { | ||
265 | return odbgstream("FATAL: ", area, ODEBUG_FATAL); | ||
266 | } | ||
267 | |||
268 | odbgstream odFatal(bool cond, int area) | ||
269 | { | ||
270 | if (cond) return odbgstream("FATAL: ", area, ODEBUG_FATAL); else return odbgstream(0,0,false); | ||
271 | } | ||
272 | |||
273 | odbgstream::odbgstream(unsigned int _area, unsigned int _level, bool _print) | ||
274 | :area(_area), level(_level), print(_print) | ||
275 | { | ||
276 | } | ||
277 | |||
278 | |||
279 | odbgstream::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 | |||
285 | odbgstream::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 | |||
292 | odbgstream::odbgstream(const odbgstream &str) | ||
293 | :output(str.output), area(str.area), level(str.level), print(str.print) | ||
294 | { | ||
295 | } | ||
296 | |||
297 | odbgstream& odbgstream::operator<<(bool i) | ||
298 | { | ||
299 | if (!print) return *this; | ||
300 | output += QString::fromLatin1(i ? "true" : "false"); | ||
301 | return *this; | ||
302 | } | ||
303 | |||
304 | |||
305 | odbgstream& odbgstream::operator<<(short i) | ||
306 | { | ||
307 | if (!print) return *this; | ||
308 | QString tmp; tmp.setNum(i); output += tmp; | ||
309 | return *this; | ||
310 | } | ||
311 | |||
312 | |||
313 | odbgstream& 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 | |||
321 | odbgstream& odbgstream::operator<<(unsigned char i) | ||
322 | { | ||
323 | return operator<<( static_cast<char>( i ) ); | ||
324 | } | ||
325 | |||
326 | |||
327 | odbgstream& odbgstream::operator<<(int i) | ||
328 | { | ||
329 | if (!print) return *this; | ||
330 | QString tmp; tmp.setNum(i); output += tmp; | ||
331 | return *this; | ||
332 | } | ||
333 | |||
334 | |||
335 | odbgstream& 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 | |||
343 | odbgstream& odbgstream::operator<<(long i) | ||
344 | { | ||
345 | if (!print) return *this; | ||
346 | QString tmp; tmp.setNum(i); output += tmp; | ||
347 | return *this; | ||
348 | } | ||
349 | |||
350 | |||
351 | odbgstream& 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 | |||
359 | odbgstream& 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 | |||
369 | odbgstream& 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 | |||
379 | odbgstream& odbgstream::operator<<(const QCString& string) | ||
380 | { | ||
381 | *this << string.data(); | ||
382 | return *this; | ||
383 | } | ||
384 | |||
385 | |||
386 | odbgstream& odbgstream::operator<<(const void * p) | ||
387 | { | ||
388 | form("%p", p); | ||
389 | return *this; | ||
390 | } | ||
391 | |||
392 | odbgstream& odbgstream::operator<<(double d) | ||
393 | { | ||
394 | QString tmp; tmp.setNum(d); output += tmp; | ||
395 | return *this; | ||
396 | } | ||
397 | |||
398 | /* | ||
399 | odbgstream::odbgstream &form(const char *format, ...) | ||
400 | #ifdef __GNUC__ | ||
401 | __attribute__ ( ( format ( printf, 2, 3 ) ) ) | ||
402 | #endif | ||
403 | ; | ||
404 | */ | ||
405 | |||
406 | void 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 | |||
419 | odbgstream& 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 | |||
431 | odbgstream::~odbgstream() | ||
432 | { | ||
433 | if (!output.isEmpty()) | ||
434 | { | ||
435 | fprintf(stderr, "ASSERT: debug output not ended with \\n\n"); | ||
436 | *this << "\n"; | ||
437 | } | ||
438 | } | ||
439 | |||
440 | odbgstream& 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 | |||
455 | odbgstream& 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 | */ | ||
495 | odbgstream& odbgstream::operator<<( const QDateTime& time) | ||
496 | { | ||
497 | *this << time.toString(); | ||
498 | return *this; | ||
499 | } | ||
500 | |||
501 | |||
502 | odbgstream& odbgstream::operator<<( const QDate& date) | ||
503 | { | ||
504 | *this << date.toString(); | ||
505 | |||
506 | return *this; | ||
507 | } | ||
508 | |||
509 | |||
510 | odbgstream& odbgstream::operator<<( const QTime& time ) | ||
511 | { | ||
512 | *this << time.toString(); | ||
513 | return *this; | ||
514 | } | ||
515 | |||
516 | |||
517 | odbgstream& odbgstream::operator<<( const QPoint& p ) | ||
518 | { | ||
519 | *this << "(" << p.x() << ", " << p.y() << ")"; | ||
520 | return *this; | ||
521 | } | ||
522 | |||
523 | |||
524 | odbgstream& odbgstream::operator<<( const QSize& s ) | ||
525 | { | ||
526 | *this << "[" << s.width() << "x" << s.height() << "]"; | ||
527 | return *this; | ||
528 | } | ||
529 | |||
530 | |||
531 | odbgstream& odbgstream::operator<<( const QRect& r ) | ||
532 | { | ||
533 | *this << "[" << r.left() << ", " << r.top() << " - " << r.right() << ", " << r.bottom() << "]"; | ||
534 | return *this; | ||
535 | } | ||
536 | |||
537 | |||
538 | odbgstream& 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 | |||
551 | odbgstream& odbgstream::operator<<( const QStringList& l ) | ||
552 | { | ||
553 | *this << "("; | ||
554 | *this << l.join(","); | ||
555 | *this << ")"; | ||
556 | |||
557 | return *this; | ||
558 | } | ||
559 | |||
560 | |||
561 | odbgstream& 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 | |||
571 | odbgstream& 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 | |||
595 | QString 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 | |||
617 | void 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 | |||
38 | class QWidget; | ||
39 | class QDateTime; | ||
40 | class QDate; | ||
41 | class QTime; | ||
42 | class QPoint; | ||
43 | class QSize; | ||
44 | class QRect; | ||
45 | class QRegion; | ||
46 | class QStringList; | ||
47 | class QColor; | ||
48 | class QBrush; | ||
49 | |||
50 | class odbgstream; | ||
51 | class 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 | |||
67 | class 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 | |||
86 | class 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 | */ | ||
282 | inline 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 | */ | ||
288 | inline odbgstream& flush( odbgstream &s) { s.flush(); return s; } | ||
289 | |||
290 | odbgstream &perror( odbgstream &s); | ||
291 | |||
292 | /** | ||
293 | * ondbgstream is a dummy variant of @ref odbgstream. All functions do | ||
294 | * nothing. | ||
295 | * @see ondDebug() | ||
296 | */ | ||
297 | class 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 | */ | ||
408 | inline ondbgstream& endl( ondbgstream & s) { return s; } | ||
409 | /** | ||
410 | * Does nothing. | ||
411 | * @param a stream | ||
412 | * @return the given @p s | ||
413 | */ | ||
414 | inline ondbgstream& flush( ondbgstream & s) { return s; } | ||
415 | inline 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 | */ | ||
422 | odbgstream odDebug(int area = 0); | ||
423 | odbgstream 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 | */ | ||
429 | QString 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 | */ | ||
435 | inline ondbgstream ondDebug(int = 0) { return ondbgstream(); } | ||
436 | inline ondbgstream ondDebug(bool , int = 0) { return ondbgstream(); } | ||
437 | inline QString ondBacktrace() { return QString::null; } | ||
438 | inline 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 | */ | ||
445 | odbgstream odWarning(int area = 0); | ||
446 | odbgstream 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 | */ | ||
452 | odbgstream odError(int area = 0); | ||
453 | odbgstream 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 | */ | ||
459 | odbgstream odFatal(int area = 0); | ||
460 | odbgstream odFatal(bool cond, int area = 0); | ||
461 | |||
462 | /** | ||
463 | * Deletes the odebugrc cache and therefore forces KDebug to reread the | ||
464 | * config file | ||
465 | */ | ||
466 | void 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 | |||
33 | OConfig* 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 | |||
37 | static OConfig globalconfig = OConfig( "global" ); | ||
38 | |||
39 | //FIXME: Is it wise or even necessary to inherit OGlobal from Global? | ||
40 | |||
41 | class 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 | |||
49 | QString* OGlobalSettings::s_desktopPath = 0; | ||
50 | QString* OGlobalSettings::s_autostartPath = 0; | ||
51 | QString* OGlobalSettings::s_trashPath = 0; | ||
52 | QString* OGlobalSettings::s_documentPath = 0; | ||
53 | QFont *OGlobalSettings::_generalFont = 0; | ||
54 | QFont *OGlobalSettings::_fixedFont = 0; | ||
55 | QFont *OGlobalSettings::_toolBarFont = 0; | ||
56 | QFont *OGlobalSettings::_menuFont = 0; | ||
57 | QFont *OGlobalSettings::_windowTitleFont = 0; | ||
58 | QFont *OGlobalSettings::_taskbarFont = 0; | ||
59 | |||
60 | QColor *OGlobalSettings::OpieGray = 0; | ||
61 | QColor *OGlobalSettings::OpieHighlight = 0; | ||
62 | QColor *OGlobalSettings::OpieAlternate = 0; | ||
63 | |||
64 | OGlobalSettings::OMouseSettings *OGlobalSettings::s_mouseSettings = 0; | ||
65 | |||
66 | //FIXME: Add manipulators to the accessors | ||
67 | |||
68 | int OGlobalSettings::dndEventDelay() | ||
69 | { | ||
70 | OConfig *c = OGlobal::config(); | ||
71 | OConfigGroupSaver cgs( c, "General" ); | ||
72 | return c->readNumEntry("DndDelay", 2); | ||
73 | } | ||
74 | |||
75 | bool OGlobalSettings::singleClick() | ||
76 | { | ||
77 | OConfig *c = OGlobal::config(); | ||
78 | OConfigGroupSaver cgs( c, "OPIE" ); | ||
79 | return c->readBoolEntry("SingleClick", OPIE_DEFAULT_SINGLECLICK); | ||
80 | } | ||
81 | |||
82 | bool OGlobalSettings::insertTearOffHandle() | ||
83 | { | ||
84 | OConfig *c = OGlobal::config(); | ||
85 | OConfigGroupSaver cgs( c, "OPIE" ); | ||
86 | return c->readBoolEntry("InsertTearOffHandle", OPIE_DEFAULT_INSERTTEAROFFHANDLES); | ||
87 | } | ||
88 | |||
89 | bool OGlobalSettings::changeCursorOverIcon() | ||
90 | { | ||
91 | OConfig *c = OGlobal::config(); | ||
92 | OConfigGroupSaver cgs( c, "OPIE" ); | ||
93 | return c->readBoolEntry("ChangeCursor", OPIE_DEFAULT_CHANGECURSOR); | ||
94 | } | ||
95 | |||
96 | bool OGlobalSettings::visualActivate() | ||
97 | { | ||
98 | OConfig *c = OGlobal::config(); | ||
99 | OConfigGroupSaver cgs( c, "OPIE" ); | ||
100 | return c->readBoolEntry("VisualActivate", OPIE_DEFAULT_VISUAL_ACTIVATE); | ||
101 | } | ||
102 | |||
103 | unsigned 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 | |||
114 | int OGlobalSettings::autoSelectDelay() | ||
115 | { | ||
116 | OConfig *c = OGlobal::config(); | ||
117 | OConfigGroupSaver cgs( c, "OPIE" ); | ||
118 | return c->readNumEntry("AutoSelectDelay", OPIE_DEFAULT_AUTOSELECTDELAY); | ||
119 | } | ||
120 | |||
121 | OGlobalSettings::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 | |||
136 | bool OGlobalSettings::showContextMenusOnPress () | ||
137 | { | ||
138 | OConfig *c = OGlobal::config(); | ||
139 | OConfigGroupSaver cgs (c, "ContextMenus"); | ||
140 | |||
141 | return cgs.config()->readBoolEntry("ShowOnPress", true); | ||
142 | } | ||
143 | |||
144 | |||
145 | int 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 | |||
157 | OGlobalSettings::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 | |||
170 | QString 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 | |||
189 | QColor 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 | |||
197 | QColor 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 | |||
205 | QColor OGlobalSettings::inactiveTextColor() | ||
206 | { | ||
207 | OConfig *c = OGlobal::config(); | ||
208 | OConfigGroupSaver cgs( c, QString::fromLatin1("WM") ); | ||
209 | return c->readColorEntry( "inactiveForeground", &Qt::darkGray ); | ||
210 | } | ||
211 | |||
212 | QColor 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 | |||
220 | QColor OGlobalSettings::activeTextColor() | ||
221 | { | ||
222 | OConfig *c = OGlobal::config(); | ||
223 | OConfigGroupSaver cgs( c, QString::fromLatin1("WM") ); | ||
224 | return c->readColorEntry( "activeForeground", &Qt::white ); | ||
225 | } | ||
226 | |||
227 | int 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 | |||
236 | QColor OGlobalSettings::baseColor() | ||
237 | { | ||
238 | OConfig *c = OGlobal::config(); | ||
239 | OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") ); | ||
240 | return c->readColorEntry( "Base", &Qt::white ); | ||
241 | } | ||
242 | |||
243 | QColor OGlobalSettings::textColor() | ||
244 | { | ||
245 | OConfig *c = OGlobal::config(); | ||
246 | OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") ); | ||
247 | return c->readColorEntry( "Text", &Qt::black ); | ||
248 | } | ||
249 | |||
250 | QColor OGlobalSettings::highlightedTextColor() | ||
251 | { | ||
252 | OConfig *c = OGlobal::config(); | ||
253 | OConfigGroupSaver cgs( c, QString::fromLatin1("Appearance") ); | ||
254 | return c->readColorEntry( "HighlightedText", &Qt::white ); | ||
255 | } | ||
256 | |||
257 | QColor 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 | |||
265 | QColor 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 | |||
274 | QColor 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 | |||
291 | QColor 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 | |||
299 | QColor 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 | |||
310 | QFont 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 | |||
326 | QFont 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 | |||
342 | QFont 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 | |||
358 | QFont 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 | |||
374 | QFont 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 | |||
390 | QFont 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 | |||
408 | void 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 | |||
473 | void 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 | |||
480 | void 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 | |||
496 | void 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 | |||
509 | OGlobalSettings::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 | |||
532 | void 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 | |||
540 | bool 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 | */ | ||
55 | class 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 | |||
322 | private: | ||
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 @@ | |||
1 | TEMPLATE = lib | ||
2 | CONFIG += qt warn_on debug | ||
3 | DESTDIR = $(OPIEDIR)/lib | ||
4 | HEADERS = oapplication.h \ | ||
5 | oconfig.h \ | ||
6 | ocompletionbase.h \ | ||
7 | ocompletion.h \ | ||
8 | odebug.h \ | ||
9 | oglobal.h \ | ||
10 | oglobalsettings.h \ | ||
11 | osortablevaluelist.h | ||
12 | |||
13 | SOURCES = oapplication.cpp \ | ||
14 | oconfig.cpp \ | ||
15 | ocompletionbase.cpp \ | ||
16 | ocompletion.cpp \ | ||
17 | odebug.cpp \ | ||
18 | oglobal.cpp \ | ||
19 | oglobalsettings.cpp | ||
20 | |||
21 | INTERFACES = | ||
22 | TARGET = opiecore2 | ||
23 | VERSION = 1.8.1 | ||
24 | INCLUDEPATH += $(OPIEDIR)/include | ||
25 | DEPENDPATH += $(OPIEDIR)/include | ||
26 | LIBS = -lqpe | ||
27 | MOC_DIR = moc | ||
28 | OBJECTS_DIR = obj | ||
29 | |||
30 | include ( $(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 @@ | |||
1 | TEMPLATE = lib | ||
2 | CONFIG += qt warn_on debug | ||
3 | DESTDIR = $(OPIEDIR)/lib | ||
4 | HEADERS = | ||
5 | |||
6 | SOURCES = | ||
7 | INTERFACES = | ||
8 | TARGET = opiedb2 | ||
9 | VERSION = 1.8.1 | ||
10 | INCLUDEPATH += $(OPIEDIR)/include | ||
11 | DEPENDPATH += $(OPIEDIR)/include | ||
12 | |||
13 | MOC_DIR = moc | ||
14 | OBJECTS_DIR = obj | ||
15 | |||
16 | include ( $(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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 | |||
4 | enum 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 nonAssociated 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 | |||
34 | struct 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 | |||
47 | struct 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 | |||
58 | struct 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 | |||
69 | struct 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 | |||
79 | struct 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 | } | ||
153 | struct 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 | |||
236 | struct 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 | |||
246 | struct 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 | |||
264 | struct ssid_t { | ||
265 | u_int8_telement_id; | ||
266 | u_int8_tlength; | ||
267 | u_char ssid[33]; /* 32 + 1 for null */ | ||
268 | }; | ||
269 | |||
270 | |||
271 | struct rates_t { | ||
272 | u_int8_telement_id; | ||
273 | u_int8_tlength; | ||
274 | u_int8_trate[8]; | ||
275 | }; | ||
276 | |||
277 | |||
278 | struct challenge_t { | ||
279 | u_int8_telement_id; | ||
280 | u_int8_tlength; | ||
281 | u_int8_ttext[254]; /* 1-253 + 1 for null */ | ||
282 | }; | ||
283 | |||
284 | |||
285 | struct 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 | |||
295 | struct ds_t { | ||
296 | u_int8_telement_id; | ||
297 | u_int8_tlength; | ||
298 | u_int8_tchannel; | ||
299 | }; | ||
300 | |||
301 | |||
302 | struct 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 | |||
312 | struct 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 | |||
332 | struct 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 | |||
353 | struct ieee_802_11_data_body { | ||
354 | //FIXME | ||
355 | }; | ||
356 | |||
357 | struct 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 | |||
367 | struct 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 | |||
376 | struct 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 | |||
385 | struct 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 | |||
395 | struct 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 | |||
405 | struct 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> | ||
37 | using namespace std; | ||
38 | |||
39 | /*====================================================================================== | ||
40 | * OMacAddress | ||
41 | *======================================================================================*/ | ||
42 | |||
43 | // static initializer for broadcast and unknown MAC Adresses | ||
44 | const unsigned char __broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
45 | const OMacAddress& OMacAddress::broadcast = OMacAddress( __broadcast ); | ||
46 | const unsigned char __unknown[6] = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }; | ||
47 | const OMacAddress& OMacAddress::unknown = OMacAddress( __unknown ); | ||
48 | |||
49 | |||
50 | //TODO: Incorporate Ethernet Manufacturer database here! | ||
51 | |||
52 | OMacAddress::OMacAddress( unsigned char* p ) | ||
53 | { | ||
54 | memcpy( _bytes, p, 6 ); // D'OH! memcpy in my sources... eeek... | ||
55 | } | ||
56 | |||
57 | |||
58 | OMacAddress::OMacAddress( const unsigned char* p ) | ||
59 | { | ||
60 | memcpy( _bytes, p, 6 ); | ||
61 | } | ||
62 | |||
63 | |||
64 | OMacAddress::OMacAddress( struct ifreq& ifr ) | ||
65 | { | ||
66 | memcpy( _bytes, ifr.ifr_hwaddr.sa_data, 6 ); | ||
67 | } | ||
68 | |||
69 | |||
70 | OMacAddress::~OMacAddress() | ||
71 | { | ||
72 | } | ||
73 | |||
74 | |||
75 | QString 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 | |||
85 | bool operator==( const OMacAddress &m1, const OMacAddress &m2 ) | ||
86 | { | ||
87 | return memcmp( &m1._bytes, &m2._bytes, 6 ) == 0; | ||
88 | } | ||
89 | |||
90 | void 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 | |||
40 | struct ifreq; | ||
41 | |||
42 | /*====================================================================================== | ||
43 | * OMacAddress | ||
44 | *======================================================================================*/ | ||
45 | |||
46 | class 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 | |||
67 | bool operator==( const OMacAddress &m1, const OMacAddress &m2 ); | ||
68 | |||
69 | |||
70 | /*====================================================================================== | ||
71 | * OHostAddress | ||
72 | *======================================================================================*/ | ||
73 | |||
74 | class OHostAddress : public QHostAddress | ||
75 | { | ||
76 | public: | ||
77 | OHostAddress(); | ||
78 | ~OHostAddress(); | ||
79 | }; | ||
80 | |||
81 | |||
82 | /*====================================================================================== | ||
83 | * Miscellaneous | ||
84 | *======================================================================================*/ | ||
85 | |||
86 | /* dump bytes */ | ||
87 | |||
88 | void 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 | |||
56 | using namespace std; | ||
57 | |||
58 | /*====================================================================================== | ||
59 | * ONetwork | ||
60 | *======================================================================================*/ | ||
61 | |||
62 | ONetwork* ONetwork::_instance = 0; | ||
63 | |||
64 | ONetwork::ONetwork() | ||
65 | { | ||
66 | qDebug( "ONetwork::ONetwork()" ); | ||
67 | synchronize(); | ||
68 | } | ||
69 | |||
70 | void 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 | |||
108 | ONetworkInterface* ONetwork::interface( QString iface ) const | ||
109 | { | ||
110 | return _interfaces[iface]; | ||
111 | } | ||
112 | |||
113 | |||
114 | ONetwork* ONetwork::instance() | ||
115 | { | ||
116 | if ( !_instance ) _instance = new ONetwork(); | ||
117 | return _instance; | ||
118 | } | ||
119 | |||
120 | |||
121 | ONetwork::InterfaceIterator ONetwork::iterator() const | ||
122 | { | ||
123 | return ONetwork::InterfaceIterator( _interfaces ); | ||
124 | } | ||
125 | |||
126 | |||
127 | bool 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 | |||
145 | ONetworkInterface::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 | |||
153 | ifreqstruct& ONetworkInterface::ifr() const | ||
154 | { | ||
155 | return _ifr; | ||
156 | } | ||
157 | |||
158 | |||
159 | void 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 | |||
173 | bool 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 | |||
184 | bool ONetworkInterface::ioctl( int call ) const | ||
185 | { | ||
186 | strcpy( _ifr.ifr_name, (const char*) _name ); | ||
187 | return ioctl( call, _ifr ); | ||
188 | } | ||
189 | |||
190 | |||
191 | bool ONetworkInterface::isLoopback() const | ||
192 | { | ||
193 | ioctl( SIOCGIFFLAGS ); | ||
194 | return _ifr.ifr_flags & IFF_LOOPBACK; | ||
195 | } | ||
196 | |||
197 | |||
198 | bool 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 | |||
207 | bool ONetworkInterface::isUp() const | ||
208 | { | ||
209 | ioctl( SIOCGIFFLAGS ); | ||
210 | return _ifr.ifr_flags & IFF_UP; | ||
211 | } | ||
212 | |||
213 | |||
214 | QString 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 | |||
227 | OMacAddress 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 | |||
240 | void ONetworkInterface::setMonitoring( OMonitoringInterface* m ) | ||
241 | { | ||
242 | _mon = m; | ||
243 | qDebug( "ONetwork::setMonitoring(): Installed monitoring interface '%s'", (const char*) m->name() ); | ||
244 | } | ||
245 | |||
246 | |||
247 | OMonitoringInterface* ONetworkInterface::monitoring() const | ||
248 | { | ||
249 | return _mon; | ||
250 | } | ||
251 | |||
252 | |||
253 | const QString& ONetworkInterface::name() const | ||
254 | { | ||
255 | return _name; | ||
256 | } | ||
257 | |||
258 | |||
259 | ONetworkInterface::~ONetworkInterface() | ||
260 | { | ||
261 | qDebug( "ONetworkInterface::~ONetworkInterface()" ); | ||
262 | if ( _sfd != -1 ) ::close( _sfd ); | ||
263 | } | ||
264 | |||
265 | |||
266 | bool 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 | |||
275 | bool ONetworkInterface::promiscuousMode() const | ||
276 | { | ||
277 | ioctl( SIOCGIFFLAGS ); | ||
278 | return _ifr.ifr_flags & IFF_PROMISC; | ||
279 | } | ||
280 | |||
281 | |||
282 | bool ONetworkInterface::isWireless() const | ||
283 | { | ||
284 | return ioctl( SIOCGIWNAME ); | ||
285 | } | ||
286 | |||
287 | |||
288 | /*====================================================================================== | ||
289 | * OChannelHopper | ||
290 | *======================================================================================*/ | ||
291 | |||
292 | OChannelHopper::OChannelHopper( OWirelessNetworkInterface* iface ) | ||
293 | :QObject( 0, "Mickey's funky hopper" ), | ||
294 | _iface( iface ), _interval( 0 ), _channel( 0 ), _tid( 0 ) | ||
295 | { | ||
296 | } | ||
297 | |||
298 | |||
299 | OChannelHopper::~OChannelHopper() | ||
300 | { | ||
301 | } | ||
302 | |||
303 | |||
304 | void 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 | |||
314 | void 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 | |||
331 | int OChannelHopper::interval() const | ||
332 | { | ||
333 | return _interval; | ||
334 | } | ||
335 | |||
336 | |||
337 | /*====================================================================================== | ||
338 | * OWirelessNetworkInterface | ||
339 | *======================================================================================*/ | ||
340 | |||
341 | OWirelessNetworkInterface::OWirelessNetworkInterface( const QString& name ) | ||
342 | :ONetworkInterface( name ), _hopper( this ) | ||
343 | { | ||
344 | qDebug( "OWirelessNetworkInterface::OWirelessNetworkInterface()" ); | ||
345 | init(); | ||
346 | } | ||
347 | |||
348 | |||
349 | OWirelessNetworkInterface::~OWirelessNetworkInterface() | ||
350 | { | ||
351 | } | ||
352 | |||
353 | |||
354 | iwreqstruct& OWirelessNetworkInterface::iwr() const | ||
355 | { | ||
356 | return _iwr; | ||
357 | } | ||
358 | |||
359 | |||
360 | void 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*) ⦥ | ||
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 | |||
390 | QString 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 | |||
413 | int 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 | |||
427 | void 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 | |||
443 | double 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 | |||
456 | int OWirelessNetworkInterface::channels() const | ||
457 | { | ||
458 | return _channels.count(); | ||
459 | } | ||
460 | |||
461 | |||
462 | void OWirelessNetworkInterface::setChannelHopping( int interval ) | ||
463 | { | ||
464 | _hopper.setInterval( interval ); | ||
465 | } | ||
466 | |||
467 | |||
468 | int OWirelessNetworkInterface::channelHopping() const | ||
469 | { | ||
470 | return _hopper.interval(); | ||
471 | } | ||
472 | |||
473 | |||
474 | void 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 | |||
482 | bool OWirelessNetworkInterface::monitorMode() const | ||
483 | { | ||
484 | return _mon ? _mon->enabled() : false; | ||
485 | } | ||
486 | |||
487 | |||
488 | QString 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 | |||
505 | QString 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 | |||
521 | void 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 | |||
529 | bool 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 | |||
540 | bool 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 | |||
551 | OMonitoringInterface::OMonitoringInterface( ONetworkInterface* iface ) | ||
552 | :_enabled( false ), _if( static_cast<OWirelessNetworkInterface*>( iface ) ) | ||
553 | { | ||
554 | } | ||
555 | |||
556 | |||
557 | OMonitoringInterface::~OMonitoringInterface() | ||
558 | { | ||
559 | } | ||
560 | |||
561 | |||
562 | void 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 | |||
572 | bool OMonitoringInterface::enabled() const | ||
573 | { | ||
574 | return _enabled; | ||
575 | } | ||
576 | |||
577 | void 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 | |||
599 | OCiscoMonitoringInterface::OCiscoMonitoringInterface( ONetworkInterface* iface ) | ||
600 | :OMonitoringInterface( iface ) | ||
601 | { | ||
602 | iface->setMonitoring( this ); | ||
603 | } | ||
604 | |||
605 | |||
606 | OCiscoMonitoringInterface::~OCiscoMonitoringInterface() | ||
607 | { | ||
608 | } | ||
609 | |||
610 | |||
611 | void 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 | |||
633 | QString OCiscoMonitoringInterface::name() const | ||
634 | { | ||
635 | return "cisco"; | ||
636 | } | ||
637 | |||
638 | |||
639 | void OCiscoMonitoringInterface::setChannel( int ) | ||
640 | { | ||
641 | // cisco devices automatically switch channels when in monitor mode | ||
642 | } | ||
643 | |||
644 | |||
645 | /*====================================================================================== | ||
646 | * OWlanNGMonitoringInterface | ||
647 | *======================================================================================*/ | ||
648 | |||
649 | |||
650 | OWlanNGMonitoringInterface::OWlanNGMonitoringInterface( ONetworkInterface* iface ) | ||
651 | :OMonitoringInterface( iface ) | ||
652 | { | ||
653 | iface->setMonitoring( this ); | ||
654 | } | ||
655 | |||
656 | |||
657 | OWlanNGMonitoringInterface::~OWlanNGMonitoringInterface() | ||
658 | { | ||
659 | } | ||
660 | |||
661 | |||
662 | void 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 | |||
675 | QString OWlanNGMonitoringInterface::name() const | ||
676 | { | ||
677 | return "wlan-ng"; | ||
678 | } | ||
679 | |||
680 | |||
681 | void OWlanNGMonitoringInterface::setChannel( int ) | ||
682 | { | ||
683 | // wlan-ng devices automatically switch channels when in monitor mode | ||
684 | } | ||
685 | |||
686 | |||
687 | /*====================================================================================== | ||
688 | * OHostAPMonitoringInterface | ||
689 | *======================================================================================*/ | ||
690 | |||
691 | OHostAPMonitoringInterface::OHostAPMonitoringInterface( ONetworkInterface* iface ) | ||
692 | :OMonitoringInterface( iface ) | ||
693 | { | ||
694 | iface->setMonitoring( this ); | ||
695 | } | ||
696 | |||
697 | OHostAPMonitoringInterface::~OHostAPMonitoringInterface() | ||
698 | { | ||
699 | } | ||
700 | |||
701 | void 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 | |||
720 | QString OHostAPMonitoringInterface::name() const | ||
721 | { | ||
722 | return "hostap"; | ||
723 | } | ||
724 | |||
725 | |||
726 | /*====================================================================================== | ||
727 | * OOrinocoNetworkInterface | ||
728 | *======================================================================================*/ | ||
729 | |||
730 | OOrinocoMonitoringInterface::OOrinocoMonitoringInterface( ONetworkInterface* iface ) | ||
731 | :OMonitoringInterface( iface ) | ||
732 | { | ||
733 | iface->setMonitoring( this ); | ||
734 | } | ||
735 | |||
736 | |||
737 | OOrinocoMonitoringInterface::~OOrinocoMonitoringInterface() | ||
738 | { | ||
739 | } | ||
740 | |||
741 | |||
742 | void 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 | |||
752 | void 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 | |||
771 | QString 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 | |||
55 | class ONetworkInterface; | ||
56 | class OWirelessNetworkInterface; | ||
57 | class OChannelHopper; | ||
58 | class OMonitoringInterface; | ||
59 | |||
60 | typedef struct ifreq ifreqstruct; | ||
61 | typedef struct iwreq iwreqstruct; | ||
62 | typedef struct iw_event iweventstruct; | ||
63 | typedef struct iw_freq iwfreqstruct; | ||
64 | typedef struct iw_priv_args iwprivargsstruct; | ||
65 | typedef struct iw_range iwrangestruct; | ||
66 | |||
67 | /*====================================================================================== | ||
68 | * ONetwork | ||
69 | *======================================================================================*/ | ||
70 | |||
71 | class 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 | |||
99 | class 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 | |||
140 | class 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 | |||
161 | class 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 | |||
219 | class 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 | |||
245 | class 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 | |||
261 | class 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 | |||
278 | class 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 | |||
293 | class 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 | |||
47 | OPacket::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 | |||
65 | OPacket::~OPacket() | ||
66 | { | ||
67 | } | ||
68 | |||
69 | |||
70 | OPacketCapturer* OPacket::packetCapturer() const | ||
71 | { | ||
72 | return parent()->inherits( "OPacketCapturer" ) ? static_cast<OPacketCapturer*>( parent() ) : 0; | ||
73 | } | ||
74 | |||
75 | |||
76 | timevalstruct OPacket::timeval() const | ||
77 | { | ||
78 | return _hdr.ts; | ||
79 | } | ||
80 | |||
81 | |||
82 | int OPacket::caplen() const | ||
83 | { | ||
84 | return _hdr.caplen; | ||
85 | } | ||
86 | |||
87 | |||
88 | void 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 | |||
103 | int OPacket::len() const | ||
104 | { | ||
105 | return _hdr.len; | ||
106 | } | ||
107 | |||
108 | /*====================================================================================== | ||
109 | * OEthernetPacket | ||
110 | *======================================================================================*/ | ||
111 | |||
112 | OEthernetPacket::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 | |||
136 | OEthernetPacket::~OEthernetPacket() | ||
137 | { | ||
138 | } | ||
139 | |||
140 | |||
141 | OMacAddress OEthernetPacket::sourceAddress() const | ||
142 | { | ||
143 | return OMacAddress( _ether->ether_shost ); | ||
144 | } | ||
145 | |||
146 | |||
147 | OMacAddress OEthernetPacket::destinationAddress() const | ||
148 | { | ||
149 | return OMacAddress( _ether->ether_dhost ); | ||
150 | } | ||
151 | |||
152 | int OEthernetPacket::type() const | ||
153 | { | ||
154 | return ntohs( _ether->ether_type ); | ||
155 | } | ||
156 | |||
157 | |||
158 | /*====================================================================================== | ||
159 | * OIPPacket | ||
160 | *======================================================================================*/ | ||
161 | |||
162 | |||
163 | OIPPacket::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 | |||
184 | OIPPacket::~OIPPacket() | ||
185 | { | ||
186 | } | ||
187 | |||
188 | |||
189 | QHostAddress OIPPacket::fromIPAddress() const | ||
190 | { | ||
191 | return EXTRACT_32BITS( &_iphdr->saddr ); | ||
192 | } | ||
193 | |||
194 | |||
195 | QHostAddress OIPPacket::toIPAddress() const | ||
196 | { | ||
197 | return EXTRACT_32BITS( &_iphdr->saddr ); | ||
198 | } | ||
199 | |||
200 | |||
201 | int OIPPacket::tos() const | ||
202 | { | ||
203 | return _iphdr->tos; | ||
204 | } | ||
205 | |||
206 | |||
207 | int OIPPacket::len() const | ||
208 | { | ||
209 | return EXTRACT_16BITS( &_iphdr->tot_len ); | ||
210 | } | ||
211 | |||
212 | |||
213 | int OIPPacket::id() const | ||
214 | { | ||
215 | return EXTRACT_16BITS( &_iphdr->id ); | ||
216 | } | ||
217 | |||
218 | |||
219 | int OIPPacket::offset() const | ||
220 | { | ||
221 | return EXTRACT_16BITS( &_iphdr->frag_off ); | ||
222 | } | ||
223 | |||
224 | |||
225 | int OIPPacket::ttl() const | ||
226 | { | ||
227 | return _iphdr->ttl; | ||
228 | } | ||
229 | |||
230 | |||
231 | int OIPPacket::protocol() const | ||
232 | { | ||
233 | return _iphdr->protocol; | ||
234 | } | ||
235 | |||
236 | |||
237 | int OIPPacket::checksum() const | ||
238 | { | ||
239 | return EXTRACT_16BITS( &_iphdr->check ); | ||
240 | } | ||
241 | |||
242 | /*====================================================================================== | ||
243 | * OUDPPacket | ||
244 | *======================================================================================*/ | ||
245 | |||
246 | |||
247 | OUDPPacket::OUDPPacket( const struct udphdr* data, QObject* parent ) | ||
248 | :QObject( parent, "UDP" ), _udphdr( data ) | ||
249 | |||
250 | { | ||
251 | qDebug( "OUDPPacket::OUDPPacket(): decoding UDP header..." ); | ||
252 | } | ||
253 | |||
254 | OUDPPacket::~OUDPPacket() | ||
255 | { | ||
256 | } | ||
257 | |||
258 | |||
259 | /*====================================================================================== | ||
260 | * OTCPPacket | ||
261 | *======================================================================================*/ | ||
262 | |||
263 | |||
264 | OTCPPacket::OTCPPacket( const struct tcphdr* data, QObject* parent ) | ||
265 | :QObject( parent, "TCP" ), _tcphdr( data ) | ||
266 | |||
267 | { | ||
268 | qDebug( "OTCPPacket::OTCPPacket(): decoding TCP header..." ); | ||
269 | } | ||
270 | |||
271 | OTCPPacket::~OTCPPacket() | ||
272 | { | ||
273 | } | ||
274 | |||
275 | |||
276 | /*====================================================================================== | ||
277 | * OWaveLanPacket | ||
278 | *======================================================================================*/ | ||
279 | |||
280 | |||
281 | OWaveLanPacket::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 | |||
305 | OWaveLanPacket::~OWaveLanPacket() | ||
306 | { | ||
307 | } | ||
308 | |||
309 | |||
310 | int OWaveLanPacket::duration() const | ||
311 | { | ||
312 | return _wlanhdr->duration; | ||
313 | } | ||
314 | |||
315 | |||
316 | OMacAddress OWaveLanPacket::macAddress1() const | ||
317 | { | ||
318 | return OMacAddress( _wlanhdr->mac1 ); | ||
319 | } | ||
320 | |||
321 | |||
322 | OMacAddress OWaveLanPacket::macAddress2() const | ||
323 | { | ||
324 | return OMacAddress( _wlanhdr->mac2 ); | ||
325 | } | ||
326 | |||
327 | |||
328 | OMacAddress OWaveLanPacket::macAddress3() const | ||
329 | { | ||
330 | return OMacAddress( _wlanhdr->mac3 ); | ||
331 | } | ||
332 | |||
333 | |||
334 | OMacAddress OWaveLanPacket::macAddress4() const | ||
335 | { | ||
336 | return OMacAddress( _wlanhdr->mac4 ); | ||
337 | } | ||
338 | |||
339 | |||
340 | int OWaveLanPacket::subType() const | ||
341 | { | ||
342 | return FC_SUBTYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); | ||
343 | } | ||
344 | |||
345 | |||
346 | int OWaveLanPacket::type() const | ||
347 | { | ||
348 | return FC_TYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); | ||
349 | } | ||
350 | |||
351 | |||
352 | int OWaveLanPacket::version() const | ||
353 | { | ||
354 | return FC_VERSION( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); | ||
355 | } | ||
356 | |||
357 | |||
358 | bool OWaveLanPacket::fromDS() const | ||
359 | { | ||
360 | return FC_FROM_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); | ||
361 | } | ||
362 | |||
363 | |||
364 | bool OWaveLanPacket::toDS() const | ||
365 | { | ||
366 | return FC_TO_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); | ||
367 | } | ||
368 | |||
369 | |||
370 | bool OWaveLanPacket::usesPowerManagement() const | ||
371 | { | ||
372 | return FC_POWER_MGMT( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); | ||
373 | } | ||
374 | |||
375 | |||
376 | bool OWaveLanPacket::usesWep() const | ||
377 | { | ||
378 | return FC_WEP( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); | ||
379 | } | ||
380 | |||
381 | |||
382 | /*====================================================================================== | ||
383 | * OWaveLanManagementPacket | ||
384 | *======================================================================================*/ | ||
385 | |||
386 | OWaveLanManagementPacket::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 | |||
404 | OWaveLanManagementPacket::~OWaveLanManagementPacket() | ||
405 | { | ||
406 | } | ||
407 | |||
408 | |||
409 | QString 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 | |||
424 | OWaveLanDataPacket::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 | |||
438 | OWaveLanDataPacket::~OWaveLanDataPacket() | ||
439 | { | ||
440 | } | ||
441 | |||
442 | |||
443 | /*====================================================================================== | ||
444 | * OLLCPacket | ||
445 | *======================================================================================*/ | ||
446 | |||
447 | OLLCPacket::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 | |||
466 | OLLCPacket::~OLLCPacket() | ||
467 | { | ||
468 | } | ||
469 | |||
470 | /*====================================================================================== | ||
471 | * OPacketCapturer | ||
472 | *======================================================================================*/ | ||
473 | |||
474 | OPacketCapturer::OPacketCapturer( QObject* parent, const char* name ) | ||
475 | :QObject( parent, name ), _name( QString::null ), _open( false ), | ||
476 | _pch( 0 ) | ||
477 | { | ||
478 | } | ||
479 | |||
480 | |||
481 | OPacketCapturer::~OPacketCapturer() | ||
482 | { | ||
483 | if ( _open ) | ||
484 | { | ||
485 | qDebug( "OPacketCapturer::~OPacketCapturer(): pcap still open, autoclosing." ); | ||
486 | close(); | ||
487 | } | ||
488 | } | ||
489 | |||
490 | |||
491 | void 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 | |||
504 | bool 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 | |||
516 | void OPacketCapturer::close() | ||
517 | { | ||
518 | if ( _open ) | ||
519 | { | ||
520 | pcap_close( _pch ); | ||
521 | _open = false; | ||
522 | } | ||
523 | } | ||
524 | |||
525 | |||
526 | int OPacketCapturer::dataLink() const | ||
527 | { | ||
528 | return pcap_datalink( _pch ); | ||
529 | } | ||
530 | |||
531 | |||
532 | int OPacketCapturer::fileno() const | ||
533 | { | ||
534 | if ( _open ) | ||
535 | { | ||
536 | return pcap_fileno( _pch ); | ||
537 | } | ||
538 | else | ||
539 | { | ||
540 | return -1; | ||
541 | } | ||
542 | } | ||
543 | |||
544 | |||
545 | OPacket* 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 | |||
556 | bool 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 | |||
598 | bool OPacketCapturer::isOpen() const | ||
599 | { | ||
600 | return _open; | ||
601 | } | ||
602 | |||
603 | |||
604 | void 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 */ | ||
38 | extern "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 */ | ||
58 | typedef struct timeval timevalstruct; | ||
59 | typedef struct pcap_pkthdr packetheaderstruct; | ||
60 | |||
61 | /* FORWARDS */ | ||
62 | class OPacketCapturer; | ||
63 | |||
64 | /*====================================================================================== | ||
65 | * OPacket - A frame on the wire | ||
66 | *======================================================================================*/ | ||
67 | |||
68 | class 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 | |||
93 | class 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 | |||
114 | class 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 | |||
144 | class 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 | |||
164 | class 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 | |||
180 | class 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 | |||
196 | class 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 | |||
223 | class 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 | |||
242 | class 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 | |||
262 | class 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 @@ | |||
1 | TEMPLATE = lib | ||
2 | CONFIG += qt warn_on debug | ||
3 | DESTDIR = $(OPIEDIR)/lib | ||
4 | HEADERS = onetutils.cpp onetwork.h opcap.h | ||
5 | |||
6 | SOURCES = onetutils.cpp onetwork.cpp opcap.cpp | ||
7 | INTERFACES = | ||
8 | TARGET = opienet2 | ||
9 | VERSION = 1.8.1 | ||
10 | INCLUDEPATH += $(OPIEDIR)/include | ||
11 | DEPENDPATH += $(OPIEDIR)/include | ||
12 | LIBS += -lpcap | ||
13 | |||
14 | MOC_DIR = moc | ||
15 | OBJECTS_DIR = obj | ||
16 | |||
17 | include ( $(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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 @@ | |||
1 | TEMPLATE = lib | ||
2 | CONFIG += qt warn_on debug | ||
3 | DESTDIR = $(OPIEDIR)/lib | ||
4 | HEADERS = | ||
5 | |||
6 | SOURCES = | ||
7 | INTERFACES = | ||
8 | TARGET = opiepim2 | ||
9 | VERSION = 1.8.1 | ||
10 | INCLUDEPATH += $(OPIEDIR)/include | ||
11 | DEPENDPATH += $(OPIEDIR)/include | ||
12 | |||
13 | MOC_DIR = moc | ||
14 | OBJECTS_DIR = obj | ||
15 | |||
16 | include ( $(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 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
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 | |||
34 | int ODialog::mMarginSize = 5; // 11 like in KDialog is probably too much for PDA | ||
35 | int ODialog::mSpacingSize = 2; // 6 like in KDialog is probably too much for PDA | ||
36 | |||
37 | ODialog::ODialog(QWidget *parent, const char *name, bool modal, WFlags f) | ||
38 | : QDialog(parent, name, modal, f) | ||
39 | { | ||
40 | } | ||
41 | |||
42 | int ODialog::marginHint() | ||
43 | { | ||
44 | return( mMarginSize ); | ||
45 | } | ||
46 | |||
47 | |||
48 | int 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 | |||
35 | class 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 | |||
55 | class 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 | |||
7 | Redistribution and use in source and binary forms, with or without | ||
8 | modification, are permitted provided that the following conditions | ||
9 | are met: | ||
10 | |||
11 | 1. Redistributions of source code must retain the above copyright | ||
12 | notice, this list of conditions and the following disclaimer. | ||
13 | 2. 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 | |||
17 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
18 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
20 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
22 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
26 | THIS 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 | |||
43 | using namespace std; | ||
44 | |||
45 | inline 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 | |||
58 | QImage 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 | |||
322 | QImage 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 | |||
573 | QImage& 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 | |||
639 | QImage& 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 | // | ||
730 | QImage& 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 | ||
860 | QImage& 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 | ||
903 | QImage& 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 | |||
955 | QImage& 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 | // | ||
1163 | QImage& 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 | // | ||
1181 | QImage& 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 | |||
1256 | unsigned 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 | |||
1270 | unsigned 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 | |||
1284 | QImage& 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 | |||
1365 | QImage& 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 | |||
1462 | QImage& 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). | ||
1544 | QImage& 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 | ||
1594 | QImage& 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) | ||
1617 | QImage& 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. | ||
1667 | QImage& 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 | |||
1754 | int 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 | |||
1784 | bool 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... | ||
1843 | bool 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 | |||
1856 | bool 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 | |||
1920 | bool 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 | ||
1991 | QImage& 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 | |||
2003 | void 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 | |||
2119 | void 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 | |||
2204 | QImage 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 | |||
2297 | void 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 | |||
2313 | QImage 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 | |||
2325 | void 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 | |||
2405 | QImage 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 | |||
2516 | unsigned 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 | |||
2611 | QImage 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 | |||
2650 | unsigned 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 | |||
2741 | QImage 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 | |||
2822 | QImage 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 | |||
2920 | void 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 | |||
2943 | QImage 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 | |||
2994 | QImage 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 | |||
3072 | QImage 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 | |||
3098 | QImage 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 | |||
3174 | QImage 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 | |||
3271 | QImage 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 | |||
3422 | QImage 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 | |||
3520 | QImage 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 | |||
3654 | QImage 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) | ||
3756 | void 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 | |||
9 | Redistribution and use in source and binary forms, with or without | ||
10 | modification, are permitted provided that the following conditions | ||
11 | are met: | ||
12 | |||
13 | 1. Redistributions of source code must retain the above copyright | ||
14 | notice, this list of conditions and the following disclaimer. | ||
15 | 2. 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 | |||
19 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
21 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
22 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
23 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
24 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
28 | THIS 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 | |||
37 | class QImage; | ||
38 | class QSize; | ||
39 | class 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 | |||
50 | class OImageEffect | ||
51 | { | ||
52 | public: | ||
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 | |||
536 | private: | ||
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 | |||
46 | OListView::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 | |||
56 | OListView::~OListView() | ||
57 | { | ||
58 | } | ||
59 | |||
60 | void 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 | |||
68 | bool OListView::fullWidth() const | ||
69 | { | ||
70 | return m_fullWidth; | ||
71 | } | ||
72 | |||
73 | int 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 | |||
85 | int 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 | |||
97 | void 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 | |||
108 | const QColor& OListView::alternateBackground() const | ||
109 | { | ||
110 | return m_alternateBackground; | ||
111 | } | ||
112 | |||
113 | void OListView::setAlternateBackground( const QColor &c ) | ||
114 | { | ||
115 | m_alternateBackground = c; | ||
116 | repaint(); | ||
117 | } | ||
118 | |||
119 | const QPen& OListView::columnSeparator() const | ||
120 | { | ||
121 | return m_columnSeparator; | ||
122 | } | ||
123 | |||
124 | void OListView::setColumnSeparator( const QPen& p ) | ||
125 | { | ||
126 | m_columnSeparator = p; | ||
127 | repaint(); | ||
128 | } | ||
129 | |||
130 | OListViewItem* OListView::childFactory() | ||
131 | { | ||
132 | return new OListViewItem( this ); | ||
133 | } | ||
134 | |||
135 | #ifndef QT_NO_DATASTREAM | ||
136 | void 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 | |||
167 | void 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 | |||
200 | QDataStream& operator<<( QDataStream& s, const OListView& lv ) | ||
201 | { | ||
202 | lv.serializeTo( s ); | ||
203 | } | ||
204 | |||
205 | QDataStream& operator>>( QDataStream& s, OListView& lv ) | ||
206 | { | ||
207 | lv.serializeFrom( s ); | ||
208 | } | ||
209 | #endif // QT_NO_DATASTREAM | ||
210 | |||
211 | /*====================================================================================== | ||
212 | * OListViewItem | ||
213 | *======================================================================================*/ | ||
214 | |||
215 | OListViewItem::OListViewItem(QListView *parent) | ||
216 | : QListViewItem(parent) | ||
217 | { | ||
218 | init(); | ||
219 | } | ||
220 | |||
221 | OListViewItem::OListViewItem(QListViewItem *parent) | ||
222 | : QListViewItem(parent) | ||
223 | { | ||
224 | init(); | ||
225 | } | ||
226 | |||
227 | OListViewItem::OListViewItem(QListView *parent, QListViewItem *after) | ||
228 | : QListViewItem(parent, after) | ||
229 | { | ||
230 | init(); | ||
231 | } | ||
232 | |||
233 | OListViewItem::OListViewItem(QListViewItem *parent, QListViewItem *after) | ||
234 | : QListViewItem(parent, after) | ||
235 | { | ||
236 | init(); | ||
237 | } | ||
238 | |||
239 | OListViewItem::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 | |||
247 | OListViewItem::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 | |||
255 | OListViewItem::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 | |||
263 | OListViewItem::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 | |||
271 | OListViewItem::~OListViewItem() | ||
272 | { | ||
273 | } | ||
274 | |||
275 | void OListViewItem::init() | ||
276 | { | ||
277 | m_known = false; | ||
278 | } | ||
279 | |||
280 | const QColor &OListViewItem::backgroundColor() | ||
281 | { | ||
282 | return isAlternate() ? static_cast<OListView*>(listView())->alternateBackground() : | ||
283 | listView()->viewport()->colorGroup().base(); | ||
284 | } | ||
285 | |||
286 | bool 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 | |||
329 | void 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 | |||
351 | OListViewItem* OListViewItem::childFactory() | ||
352 | { | ||
353 | return new OListViewItem( this ); | ||
354 | } | ||
355 | |||
356 | #ifndef QT_NO_DATASTREAM | ||
357 | void 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 | } | ||
388 | void 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 | |||
414 | QDataStream& operator<<( QDataStream& s, const OListViewItem& lvi ) | ||
415 | { | ||
416 | lvi.serializeTo( s ); | ||
417 | } | ||
418 | |||
419 | QDataStream& 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 | |||
39 | class 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 | */ | ||
147 | QDataStream& 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 | */ | ||
152 | QDataStream& operator>>( QDataStream& s, OListView& lv ); | ||
153 | #endif // QT_NO_DATASTREAM | ||
154 | |||
155 | //****************************** OListViewItem ****************************************************************** | ||
156 | |||
157 | class 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 | */ | ||
227 | QDataStream& 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 | */ | ||
232 | QDataStream& 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 @@ | |||
1 | TEMPLATE = lib | ||
2 | CONFIG += qt warn_on debug | ||
3 | DESTDIR = $(QTDIR)/lib | ||
4 | HEADERS = 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 | |||
20 | SOURCES = 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 | |||
36 | INTERFACES = | ||
37 | TARGET = opieui2 | ||
38 | VERSION = 1.8.1 | ||
39 | INCLUDEPATH += $(OPIEDIR)/include | ||
40 | DEPENDPATH += $(OPIEDIR)/include | ||
41 | LIBS += -lopiecore2 | ||
42 | MOC_DIR = moc | ||
43 | OBJECTS_DIR = obj | ||
44 | |||
45 | include ( $(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 | |||
27 | OPixmap& 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 | |||
91 | OPixmap& 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 | |||
112 | OPixmap& 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 | |||
124 | OPixmap& 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 | |||
143 | OPixmap& 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 | |||
182 | OPixmap& 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 | ||
216 | void 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 | |||
226 | OPixmap 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 | |||
243 | OPixmap 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 | |||
260 | OPixmap& 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 | // ----------------------------------------------------------------------------- | ||
271 | OPixmap& 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 | // ----------------------------------------------------------------------------- | ||
281 | OPixmap& 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 | // ----------------------------------------------------------------------------- | ||
290 | OPixmap& 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 | // ----------------------------------------------------------------------------- | ||
306 | OPixmap& 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 | |||
321 | OPixmap 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> | ||
15 | typedef QPixmap OPixmap; | ||
16 | class 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 | */ | ||
26 | class OPixmapEffect | ||
27 | { | ||
28 | public: | ||
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 | |||
23 | OPixmapProvider::~OPixmapProvider() {} | ||
24 | |||
25 | void 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 | */ | ||
37 | class OPixmapProvider | ||
38 | { | ||
39 | public: | ||
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; | ||
49 | protected: | ||
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 | |||
37 | OPopupTitle::OPopupTitle(QWidget *parent, const char *name) | ||
38 | : QWidget(parent, name) | ||
39 | { | ||
40 | setMinimumSize(16, fontMetrics().height()+8); | ||
41 | } | ||
42 | |||
43 | OPopupTitle::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 | |||
51 | OPopupTitle::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 | |||
59 | void 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 | |||
72 | void 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 | |||
80 | void 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 | |||
88 | void 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 | |||
124 | QSize OPopupTitle::sizeHint() const | ||
125 | { | ||
126 | return(minimumSize()); | ||
127 | } | ||
128 | |||
129 | class OPopupMenu::OPopupMenuPrivate | ||
130 | { | ||
131 | public: | ||
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 | |||
166 | int OPopupMenu::OPopupMenuPrivate::s_highlightedItem(-1); | ||
167 | OPopupMenu* OPopupMenu::OPopupMenuPrivate::s_contextedMenu(0); | ||
168 | bool OPopupMenu::OPopupMenuPrivate::s_continueCtxMenuShow(true); | ||
169 | |||
170 | OPopupMenu::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 | |||
178 | OPopupMenu::~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 | |||
189 | int 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 | |||
198 | int 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 | |||
208 | void 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 | |||
225 | void 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 | |||
242 | QString 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 | |||
258 | QPixmap 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 | */ | ||
276 | void OPopupMenu::closeEvent(QCloseEvent*e) | ||
277 | { | ||
278 | if (d->shortcuts) | ||
279 | resetKeyboardVars(); | ||
280 | QPopupMenu::closeEvent(e); | ||
281 | } | ||
282 | |||
283 | void 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 | |||
437 | QString 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 | |||
447 | void 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 | |||
462 | void OPopupMenu::setKeyboardShortcutsEnabled(bool enable) | ||
463 | { | ||
464 | d->shortcuts = enable; | ||
465 | } | ||
466 | |||
467 | void OPopupMenu::setKeyboardShortcutsExecute(bool enable) | ||
468 | { | ||
469 | d->autoExec = enable; | ||
470 | } | ||
471 | /** | ||
472 | * End keyboard navigation. | ||
473 | */ | ||
474 | |||
475 | /** | ||
476 | * RMB menus on menus | ||
477 | */ | ||
478 | QPopupMenu* 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 | |||
490 | void OPopupMenu::cancelContextMenuShow() | ||
491 | { | ||
492 | OPopupMenuPrivate::s_continueCtxMenuShow = false; | ||
493 | } | ||
494 | |||
495 | int OPopupMenu::contextMenuFocusItem() | ||
496 | { | ||
497 | return OPopupMenuPrivate::s_highlightedItem; | ||
498 | } | ||
499 | |||
500 | OPopupMenu* OPopupMenu::contextMenuFocus() | ||
501 | { | ||
502 | return OPopupMenuPrivate::s_contextedMenu; | ||
503 | } | ||
504 | |||
505 | void 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 | |||
516 | void 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 | |||
539 | void OPopupMenu::ctxMenuHiding() | ||
540 | { | ||
541 | disconnect(this, SIGNAL(highlighted(int)), this, SLOT(itemHighlighted(int))); | ||
542 | OPopupMenuPrivate::s_continueCtxMenuShow = true; | ||
543 | } | ||
544 | |||
545 | bool 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 | |||
571 | void 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 | ||
583 | OPopupMenu::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 | ||
591 | void 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 | |||
599 | void OPopupTitle::virtual_hook( int, void* ) | ||
600 | { /*BASE::virtual_hook( id, data );*/ } | ||
601 | |||
602 | void 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 | */ | ||
41 | class OPopupTitle : public QWidget | ||
42 | { | ||
43 | Q_OBJECT | ||
44 | |||
45 | public: | ||
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 | |||
82 | public slots: | ||
83 | /// @since 3.1 | ||
84 | void setText( const QString &text ); | ||
85 | /// @since 3.1 | ||
86 | void setIcon( const QPixmap &pix ); | ||
87 | |||
88 | protected: | ||
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 | |||
100 | protected: | ||
101 | virtual void virtual_hook( int id, void* data ); | ||
102 | private: | ||
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 | */ | ||
124 | class OPopupMenu : public QPopupMenu { | ||
125 | Q_OBJECT | ||
126 | public: | ||
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 | |||
224 | signals: | ||
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 | |||
234 | protected: | ||
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 | |||
242 | protected 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 | |||
251 | private: | ||
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 | |||
40 | OXYSelector::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 | |||
54 | OXYSelector::~OXYSelector() | ||
55 | {} | ||
56 | |||
57 | |||
58 | void 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 | |||
68 | void 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 | |||
89 | QRect OXYSelector::contentsRect() const | ||
90 | { | ||
91 | return QRect( 2, 2, width()-4, height()-4 ); | ||
92 | } | ||
93 | |||
94 | void 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 | |||
121 | void 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 | |||
130 | void 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 | |||
139 | void 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 | |||
151 | void 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 | |||
167 | void 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 | |||
193 | void OXYSelector::drawContents( QPainter * ) | ||
194 | {} | ||
195 | |||
196 | |||
197 | void 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 | |||
214 | OSelector::OSelector( QWidget *parent, const char *name ) | ||
215 | : QWidget( parent, name ), QRangeControl() | ||
216 | { | ||
217 | _orientation = Horizontal; | ||
218 | _indent = TRUE; | ||
219 | } | ||
220 | |||
221 | OSelector::OSelector( Orientation o, QWidget *parent, const char *name ) | ||
222 | : QWidget( parent, name ), QRangeControl() | ||
223 | { | ||
224 | _orientation = o; | ||
225 | _indent = TRUE; | ||
226 | } | ||
227 | |||
228 | |||
229 | OSelector::~OSelector() | ||
230 | {} | ||
231 | |||
232 | |||
233 | QRect 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 | |||
241 | void 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 | |||
267 | void OSelector::mousePressEvent( QMouseEvent *e ) | ||
268 | { | ||
269 | moveArrow( e->pos() ); | ||
270 | } | ||
271 | |||
272 | void OSelector::mouseMoveEvent( QMouseEvent *e ) | ||
273 | { | ||
274 | moveArrow( e->pos() ); | ||
275 | } | ||
276 | |||
277 | void OSelector::wheelEvent( QWheelEvent *e ) | ||
278 | { | ||
279 | int val = value() + e->delta()/120; | ||
280 | emit valueChanged( val ); | ||
281 | setValue( val ); | ||
282 | } | ||
283 | |||
284 | void 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 | |||
300 | void 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 | |||
320 | QPoint 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 | |||
340 | void OSelector::drawContents( QPainter * ) | ||
341 | {} | ||
342 | |||
343 | void 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 | |||
381 | OGradientSelector::OGradientSelector( QWidget *parent, const char *name ) | ||
382 | : OSelector( parent, name ) | ||
383 | { | ||
384 | init(); | ||
385 | } | ||
386 | |||
387 | |||
388 | OGradientSelector::OGradientSelector( Orientation o, QWidget *parent, | ||
389 | const char *name ) | ||
390 | : OSelector( o, parent, name ) | ||
391 | { | ||
392 | init(); | ||
393 | } | ||
394 | |||
395 | |||
396 | OGradientSelector::~OGradientSelector() | ||
397 | {} | ||
398 | |||
399 | |||
400 | void OGradientSelector::init() | ||
401 | { | ||
402 | color1.setRgb( 0, 0, 0 ); | ||
403 | color2.setRgb( 255, 255, 255 ); | ||
404 | |||
405 | text1 = text2 = ""; | ||
406 | } | ||
407 | |||
408 | |||
409 | void 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 | |||
499 | static QColor *standardPalette = 0; | ||
500 | |||
501 | #define STANDARD_PAL_SIZE 17 | ||
502 | |||
503 | OColor::OColor() | ||
504 | : QColor() | ||
505 | { | ||
506 | r = 0; g = 0; b = 0; h = 0; s = 0; v = 0; | ||
507 | }; | ||
508 | |||
509 | OColor::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 | |||
516 | OColor::OColor( const QColor &col) | ||
517 | : QColor( col ) | ||
518 | { | ||
519 | QColor::rgb(&r, &g, &b); | ||
520 | QColor::hsv(&h, &s, &v); | ||
521 | }; | ||
522 | |||
523 | bool 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 | |||
529 | OColor& 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 | |||
537 | void | ||
538 | OColor::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 | |||
545 | void | ||
546 | OColor::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 | |||
553 | void | ||
554 | OColor::rgb(int *_r, int *_g, int *_b) const | ||
555 | { | ||
556 | *_r = r; *_g = g; *_b = b; | ||
557 | } | ||
558 | |||
559 | void | ||
560 | OColor::hsv(int *_h, int *_s, int *_v) const | ||
561 | { | ||
562 | *_h = h; *_s = s; *_v = v; | ||
563 | } | ||
564 | |||
565 | static 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 | |||
594 | OHSSelector::OHSSelector( QWidget *parent, const char *name ) | ||
595 | : OXYSelector( parent, name ) | ||
596 | { | ||
597 | setRange( 0, 0, 359, 255 ); | ||
598 | } | ||
599 | |||
600 | void OHSSelector::updateContents() | ||
601 | { | ||
602 | drawPalette(&pixmap); | ||
603 | } | ||
604 | |||
605 | void OHSSelector::resizeEvent( QResizeEvent * ) | ||
606 | { | ||
607 | updateContents(); | ||
608 | } | ||
609 | |||
610 | void OHSSelector::drawContents( QPainter *painter ) | ||
611 | { | ||
612 | painter->drawPixmap( contentsRect().x(), contentsRect().y(), pixmap ); | ||
613 | } | ||
614 | |||
615 | void 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 | |||
645 | OValueSelector::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 | |||
652 | OValueSelector::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 | |||
660 | void OValueSelector::updateContents() | ||
661 | { | ||
662 | drawPalette(&pixmap); | ||
663 | } | ||
664 | |||
665 | void OValueSelector::resizeEvent( QResizeEvent * ) | ||
666 | { | ||
667 | updateContents(); | ||
668 | } | ||
669 | |||
670 | void OValueSelector::drawContents( QPainter *painter ) | ||
671 | { | ||
672 | painter->drawPixmap( contentsRect().x(), contentsRect().y(), pixmap ); | ||
673 | } | ||
674 | |||
675 | void 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 | */ | ||
41 | class OXYSelector : public QWidget | ||
42 | { | ||
43 | Q_OBJECT | ||
44 | |||
45 | public: | ||
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 | |||
80 | signals: | ||
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 | |||
87 | protected: | ||
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 | |||
121 | private: | ||
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 | |||
133 | private: | ||
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 | */ | ||
148 | class 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 ) | ||
154 | public: | ||
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 | |||
235 | signals: | ||
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 | |||
242 | protected: | ||
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 | |||
280 | private: | ||
281 | QPoint calcArrowPos( int val ); | ||
282 | void moveArrow( const QPoint &pos ); | ||
283 | |||
284 | Orientation _orientation; | ||
285 | bool _indent; | ||
286 | |||
287 | private: | ||
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 | */ | ||
298 | class 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 | |||
307 | public: | ||
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 | |||
356 | protected: | ||
357 | /** | ||
358 | * @reimplemented | ||
359 | */ | ||
360 | virtual void drawContents( QPainter * ); | ||
361 | |||
362 | /** | ||
363 | * @reimplemented | ||
364 | */ | ||
365 | virtual QSize minimumSize() const | ||
366 | { return sizeHint(); } | ||
367 | |||
368 | private: | ||
369 | void init(); | ||
370 | QColor color1; | ||
371 | QColor color2; | ||
372 | QString text1; | ||
373 | QString text2; | ||
374 | |||
375 | private: | ||
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 | */ | ||
389 | class OHSSelector : public OXYSelector | ||
390 | { | ||
391 | Q_OBJECT | ||
392 | |||
393 | public: | ||
394 | /** | ||
395 | * Constructs a hue/saturation selection widget. | ||
396 | */ | ||
397 | OHSSelector( QWidget *parent=0, const char *name=0 ); | ||
398 | |||
399 | protected: | ||
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 | |||
416 | private: | ||
417 | void updateContents(); | ||
418 | QPixmap pixmap; | ||
419 | |||
420 | private: | ||
421 | class OHSSelectorPrivate; | ||
422 | OHSSelectorPrivate *d; | ||
423 | }; | ||
424 | |||
425 | |||
426 | class OValueSelectorPrivate; | ||
427 | /** | ||
428 | * Widget for color value selection. | ||
429 | * | ||
430 | * @see OHSSelector, OColorDialog | ||
431 | * @author Martin Jones (mjones@kde.org) | ||
432 | * @version $Id$ | ||
433 | */ | ||
434 | class OValueSelector : public OSelector | ||
435 | { | ||
436 | Q_OBJECT | ||
437 | |||
438 | public: | ||
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(); | ||
458 | protected: | ||
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 | |||
475 | private: | ||
476 | int _hue; | ||
477 | int _sat; | ||
478 | QPixmap pixmap; | ||
479 | |||
480 | private: | ||
481 | class OValueSelectorPrivate; | ||
482 | OValueSelectorPrivate *d; | ||
483 | }; | ||
484 | |||
485 | |||
486 | class OColor : public QColor | ||
487 | { | ||
488 | public: | ||
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; | ||
502 | protected: | ||
503 | int h; | ||
504 | int s; | ||
505 | int v; | ||
506 | int r; | ||
507 | int g; | ||
508 | int b; | ||
509 | |||
510 | private: | ||
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 | |||
41 | OSeparator::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 | |||
51 | OSeparator::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 | |||
61 | void 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 | |||
84 | int 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 | |||
95 | void 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 | |||
119 | QSize 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 | */ | ||
45 | class 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 | |||
82 | protected: | ||
83 | virtual void drawFrame( QPainter * ); | ||
84 | |||
85 | private: | ||
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 */ | ||
54 | static 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 */ | ||
90 | static 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 | |||
126 | OVersatileView::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 | |||
235 | OVersatileView::~OVersatileView() | ||
236 | { | ||
237 | } | ||
238 | |||
239 | QPopupMenu* OVersatileView::contextMenu() const | ||
240 | { | ||
241 | return _contextmenu; | ||
242 | } | ||
243 | |||
244 | void 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 | |||
252 | void OVersatileView::contextMenuRequested( QIconViewItem* item, const QPoint& pos ) | ||
253 | { | ||
254 | // see above | ||
255 | popupContextMenu( static_cast<OVersatileViewItem*>( item ), pos, -1 ); | ||
256 | } | ||
257 | |||
258 | void 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 | |||
266 | void OVersatileView::setSynchronization( bool sync ) | ||
267 | { | ||
268 | _synchronization = sync; | ||
269 | } | ||
270 | |||
271 | bool OVersatileView::synchronization() | ||
272 | { | ||
273 | return _synchronization; | ||
274 | } | ||
275 | |||
276 | void 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 | |||
296 | QIconView* OVersatileView::iconView() const | ||
297 | { | ||
298 | return _iconview; | ||
299 | } | ||
300 | |||
301 | OListView* OVersatileView::listView() const | ||
302 | { | ||
303 | return _listview; | ||
304 | } | ||
305 | |||
306 | void 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 | |||
324 | void OVersatileView::setIconViewMode() | ||
325 | { | ||
326 | setViewMode( Icons ); | ||
327 | } | ||
328 | |||
329 | void OVersatileView::setTreeViewMode() | ||
330 | { | ||
331 | setViewMode( Tree ); | ||
332 | } | ||
333 | |||
334 | bool 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 | } | ||
365 | void OVersatileView::setWarningPolicy( int policy ) const | ||
366 | { | ||
367 | _warningpolicy = policy; | ||
368 | } | ||
369 | bool 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 | |||
379 | void OVersatileView::selectionChanged( QListViewItem * item ) | ||
380 | { | ||
381 | emit( selectionChanged( static_cast<OVersatileViewItem*>( item ) ) ); | ||
382 | } | ||
383 | |||
384 | void OVersatileView::selectionChanged( QIconViewItem * item ) | ||
385 | { | ||
386 | emit( selectionChanged( static_cast<OVersatileViewItem*>( item ) ) ); | ||
387 | } | ||
388 | |||
389 | void OVersatileView::currentChanged( QListViewItem * item ) | ||
390 | { | ||
391 | emit( currentChanged( static_cast<OVersatileViewItem*>( item ) ) ); | ||
392 | } | ||
393 | |||
394 | void OVersatileView::currentChanged( QIconViewItem * item ) | ||
395 | { | ||
396 | emit( currentChanged( static_cast<OVersatileViewItem*>( item ) ) ); | ||
397 | } | ||
398 | |||
399 | void OVersatileView::clicked( QListViewItem * item ) | ||
400 | { | ||
401 | emit( clicked( static_cast<OVersatileViewItem*>( item ) ) ); | ||
402 | } | ||
403 | |||
404 | void OVersatileView::clicked( QIconViewItem * item ) | ||
405 | { | ||
406 | emit( clicked( static_cast<OVersatileViewItem*>( item ) ) ); | ||
407 | } | ||
408 | |||
409 | void OVersatileView::pressed( QListViewItem * item ) | ||
410 | { | ||
411 | emit( pressed( static_cast<OVersatileViewItem*>( item ) ) ); | ||
412 | } | ||
413 | |||
414 | void OVersatileView::pressed( QIconViewItem * item ) | ||
415 | { | ||
416 | emit( pressed( static_cast<OVersatileViewItem*>( item ) ) ); | ||
417 | } | ||
418 | |||
419 | void OVersatileView::doubleClicked( QListViewItem * item ) | ||
420 | { | ||
421 | emit( doubleClicked( static_cast<OVersatileViewItem*>( item ) ) ); | ||
422 | } | ||
423 | |||
424 | void OVersatileView::doubleClicked( QIconViewItem * item ) | ||
425 | { | ||
426 | emit( doubleClicked( static_cast<OVersatileViewItem*>( item ) ) ); | ||
427 | } | ||
428 | |||
429 | void OVersatileView::returnPressed( QListViewItem * item ) | ||
430 | { | ||
431 | emit( returnPressed( static_cast<OVersatileViewItem*>( item ) ) ); | ||
432 | } | ||
433 | |||
434 | void OVersatileView::returnPressed( QIconViewItem * item ) | ||
435 | { | ||
436 | emit( returnPressed( static_cast<OVersatileViewItem*>( item ) ) ); | ||
437 | } | ||
438 | |||
439 | void OVersatileView::onItem( QListViewItem * item ) | ||
440 | { | ||
441 | emit( onItem( static_cast<OVersatileViewItem*>( item ) ) ); | ||
442 | } | ||
443 | |||
444 | void OVersatileView::onItem( QIconViewItem * item ) | ||
445 | { | ||
446 | emit( onItem( static_cast<OVersatileViewItem*>( item ) ) ); | ||
447 | } | ||
448 | |||
449 | void 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 | } | ||
456 | void 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 | |||
467 | int 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 | |||
484 | QHeader * 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 | |||
511 | void 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 | } | ||
535 | QString 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 | } | ||
551 | int 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 | } | ||
567 | int 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 | } | ||
584 | int OVersatileView::columnAlignment( int column ) const // QListView | ||
585 | { | ||
586 | if ( not isValidViewMode( Tree ) ) | ||
587 | { | ||
588 | return -1; | ||
589 | } | ||
590 | return _listview->columnAlignment( column ); | ||
591 | } | ||
592 | |||
593 | OVersatileViewItem * 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 | } | ||
601 | QRect 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 | } | ||
609 | int OVersatileView::itemPos( const OVersatileViewItem * item ) // QListView | ||
610 | { | ||
611 | if ( not isValidViewMode( Tree ) ) | ||
612 | { | ||
613 | return -1; | ||
614 | } | ||
615 | return _listview->itemPos( item ); | ||
616 | } | ||
617 | |||
618 | bool 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 | } | ||
631 | bool OVersatileView::isMultiSelection() const | ||
632 | { | ||
633 | return _listview->isMultiSelection(); | ||
634 | } | ||
635 | |||
636 | OVersatileViewItem * 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 | } | ||
652 | bool 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 | |||
661 | OVersatileViewItem * OVersatileView::firstChild() const // QListView | ||
662 | { | ||
663 | if ( not isValidViewMode( Tree ) ) | ||
664 | { | ||
665 | return 0; | ||
666 | } | ||
667 | return static_cast<OVersatileViewItem*>( _listview->firstChild() ); | ||
668 | } | ||
669 | int 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 | } | ||
686 | bool 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 | } | ||
703 | int 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 | } | ||
720 | bool OVersatileView::rootIsDecorated() const // QListView | ||
721 | { | ||
722 | if ( not isValidViewMode( Tree ) ) | ||
723 | { | ||
724 | return false; | ||
725 | } | ||
726 | return _listview->rootIsDecorated(); | ||
727 | } | ||
728 | |||
729 | void OVersatileView::setShowSortIndicator( bool show ) // QListView | ||
730 | { | ||
731 | if ( not isValidViewMode( Tree ) ) | ||
732 | { | ||
733 | return; | ||
734 | } | ||
735 | _listview->setShowSortIndicator( show ); | ||
736 | } | ||
737 | bool OVersatileView::showSortIndicator() const // QListView | ||
738 | { | ||
739 | if ( not isValidViewMode( Tree ) ) | ||
740 | { | ||
741 | return false; | ||
742 | } | ||
743 | return _listview->showSortIndicator(); | ||
744 | } | ||
745 | |||
746 | void 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 | |||
759 | uint OVersatileView::count() const // QIconView | ||
760 | { | ||
761 | if ( not isValidViewMode( Icons ) ) | ||
762 | { | ||
763 | return 0; | ||
764 | } | ||
765 | return _iconview->count(); | ||
766 | } | ||
767 | |||
768 | int 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 | |||
777 | OVersatileViewItem* OVersatileView::firstItem() const // QIconView | ||
778 | { | ||
779 | if ( not isValidViewMode( Icons ) ) | ||
780 | { | ||
781 | return 0; | ||
782 | } | ||
783 | return static_cast<OVersatileViewItem*>( _iconview->firstItem() ); | ||
784 | } | ||
785 | OVersatileViewItem* OVersatileView::lastItem() const // QIconView | ||
786 | { | ||
787 | if ( not isValidViewMode( Icons ) ) | ||
788 | { | ||
789 | return 0; | ||
790 | } | ||
791 | return static_cast<OVersatileViewItem*>( _iconview->lastItem() ); | ||
792 | } | ||
793 | |||
794 | OVersatileViewItem* 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 | } | ||
802 | OVersatileViewItem* 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 | |||
811 | OVersatileViewItem* 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 | } | ||
819 | OVersatileViewItem* 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 | } | ||
844 | int OVersatileView::gridX() const // QIconView | ||
845 | { | ||
846 | if ( not isValidViewMode( Icons ) ) | ||
847 | { | ||
848 | return -1; | ||
849 | } | ||
850 | return _iconview->gridX(); | ||
851 | } | ||
852 | int 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 | } | ||
868 | int 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 | } | ||
884 | QIconView::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 | } | ||
900 | QBrush 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 | } | ||
916 | QIconView::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 | } | ||
932 | QIconView::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 | } | ||
948 | int 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 | } | ||
964 | int 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 | } | ||
980 | bool 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 | } | ||
996 | bool OVersatileView::showToolTips() const // QIconView | ||
997 | { | ||
998 | if ( not isValidViewMode( Icons ) ) | ||
999 | { | ||
1000 | return false; | ||
1001 | } | ||
1002 | return _iconview->showToolTips(); | ||
1003 | } | ||
1004 | |||
1005 | bool OVersatileView::sorting() const // QIconView | ||
1006 | { | ||
1007 | if ( not isValidViewMode( Icons ) ) | ||
1008 | { | ||
1009 | return false; | ||
1010 | } | ||
1011 | return _iconview->sorting(); | ||
1012 | } | ||
1013 | bool 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 | } | ||
1030 | bool OVersatileView::itemsMovable() const // QIconView | ||
1031 | { | ||
1032 | if ( not isValidViewMode( Icons ) ) | ||
1033 | { | ||
1034 | return false; | ||
1035 | } | ||
1036 | return _iconview->itemsMovable(); | ||
1037 | } | ||
1038 | void OVersatileView::setWordWrapIconText( bool b ) // QIconView | ||
1039 | { | ||
1040 | if ( not isValidViewMode( Icons ) ) | ||
1041 | { | ||
1042 | return; | ||
1043 | } | ||
1044 | _iconview->setWordWrapIconText( b ); | ||
1045 | } | ||
1046 | bool OVersatileView::wordWrapIconText() const // QIconView | ||
1047 | { | ||
1048 | if ( not isValidViewMode( Icons ) ) | ||
1049 | { | ||
1050 | return false; | ||
1051 | } | ||
1052 | return _iconview->wordWrapIconText(); | ||
1053 | } | ||
1054 | |||
1055 | void OVersatileView::arrangeItemsInGrid( const QSize &grid, bool update ) // QIconView | ||
1056 | { | ||
1057 | if ( not isValidViewMode( Icons ) ) | ||
1058 | { | ||
1059 | return; | ||
1060 | } | ||
1061 | _iconview->arrangeItemsInGrid( grid, update ); | ||
1062 | } | ||
1063 | void OVersatileView::arrangeItemsInGrid( bool update ) // QIconView | ||
1064 | { | ||
1065 | if ( not isValidViewMode( Icons ) ) | ||
1066 | { | ||
1067 | return; | ||
1068 | } | ||
1069 | _iconview->arrangeItemsInGrid( update ); | ||
1070 | } | ||
1071 | void 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 | |||
1084 | void OVersatileView::clear() | ||
1085 | { | ||
1086 | _iconview->clear(); | ||
1087 | _listview->clear(); | ||
1088 | } | ||
1089 | |||
1090 | void OVersatileView::setFont( const QFont & font ) | ||
1091 | { | ||
1092 | _iconview->setFont( font ); | ||
1093 | _listview->setFont( font ); | ||
1094 | } | ||
1095 | void OVersatileView::setPalette( const QPalette & palette ) | ||
1096 | { | ||
1097 | _iconview->setPalette( palette ); | ||
1098 | _listview->setPalette( palette ); | ||
1099 | } | ||
1100 | |||
1101 | void OVersatileView::takeItem( OVersatileViewItem * item ) | ||
1102 | { | ||
1103 | _iconview->takeItem( item ); | ||
1104 | _listview->takeItem( item ); | ||
1105 | } | ||
1106 | |||
1107 | void OVersatileView::setSelectionMode( SelectionMode mode ) | ||
1108 | { | ||
1109 | _iconview->setSelectionMode( (QIconView::SelectionMode) mode ); | ||
1110 | _listview->setSelectionMode( (QListView::SelectionMode) mode ); | ||
1111 | } | ||
1112 | OVersatileView::SelectionMode OVersatileView::selectionMode() const | ||
1113 | { | ||
1114 | return (OVersatileView::SelectionMode) _iconview->selectionMode(); | ||
1115 | } | ||
1116 | |||
1117 | void OVersatileView::selectAll( bool select ) | ||
1118 | { | ||
1119 | _iconview->selectAll( select ); | ||
1120 | } | ||
1121 | void OVersatileView::clearSelection() | ||
1122 | { | ||
1123 | _iconview->clearSelection(); | ||
1124 | _listview->clearSelection(); | ||
1125 | } | ||
1126 | void OVersatileView::invertSelection() | ||
1127 | { | ||
1128 | _iconview->invertSelection(); | ||
1129 | _listview->invertSelection(); | ||
1130 | } | ||
1131 | |||
1132 | void OVersatileView::ensureItemVisible( const OVersatileViewItem * item ) | ||
1133 | { | ||
1134 | _iconview->ensureItemVisible( const_cast<OVersatileViewItem*>( item ) ); | ||
1135 | _listview->ensureItemVisible( item ); | ||
1136 | } | ||
1137 | void OVersatileView::repaintItem( const OVersatileViewItem * item ) const | ||
1138 | { | ||
1139 | _iconview->repaintItem( const_cast<OVersatileViewItem*>( item ) ); | ||
1140 | _listview->repaintItem( item ); | ||
1141 | } | ||
1142 | |||
1143 | void OVersatileView::setCurrentItem( OVersatileViewItem * item ) | ||
1144 | { | ||
1145 | _iconview->setCurrentItem( item ); | ||
1146 | _listview->setCurrentItem( item ); | ||
1147 | } | ||
1148 | OVersatileViewItem * 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 | ||
1172 | void OVersatileView::setSorting( bool sort, bool ascending = TRUE ) // QIconView | ||
1173 | |||
1174 | void 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 | |||
45 | class QHeader; | ||
46 | class QIconSet; | ||
47 | class QIconViewItem; | ||
48 | class OListView; | ||
49 | class QListViewItem; | ||
50 | class QPopupMenu; | ||
51 | class QString; | ||
52 | |||
53 | #ifndef QT_NO_DRAGANDDROP | ||
54 | class QIconDragItem; | ||
55 | #endif | ||
56 | |||
57 | class 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 | |||
160 | public: | ||
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 | |||
34 | OVersatileViewItem::OVersatileViewItem( OVersatileView * parent ) | ||
35 | :OListViewItem( parent->_listview ), QIconViewItem( parent->_iconview ), | ||
36 | _versatileview( parent ) | ||
37 | { | ||
38 | init(); | ||
39 | } | ||
40 | |||
41 | OVersatileViewItem::OVersatileViewItem( OVersatileView * parent, OVersatileViewItem * after ) | ||
42 | :OListViewItem( parent->_listview, after ), QIconViewItem( parent->_iconview, after ), | ||
43 | _versatileview( parent ) | ||
44 | { | ||
45 | init(); | ||
46 | } | ||
47 | |||
48 | OVersatileViewItem::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 | |||
58 | OVersatileViewItem::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 | |||
68 | OVersatileViewItem::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 | |||
78 | OVersatileViewItem::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 | |||
88 | OVersatileViewItem::~OVersatileViewItem() | ||
89 | { | ||
90 | } | ||
91 | |||
92 | OVersatileView* OVersatileViewItem::versatileView() const | ||
93 | { | ||
94 | return _versatileview; | ||
95 | } | ||
96 | |||
97 | void 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 | |||
124 | void 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 | |||
43 | class OVersatileView; | ||
44 | |||
45 | class 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 */ | ||
2 | static 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 */ | ||
2 | static 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 | |||
33 | class OCompTreeNode; | ||
34 | |||
35 | /**************************************************************************************************/ | ||
36 | /* OCompTreeNodeList | ||
37 | /**************************************************************************************************/ | ||
38 | |||
39 | class OCompTreeNodeList | ||
40 | { | ||
41 | public: | ||
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 | |||
53 | private: | ||
54 | OCompTreeNode *first, *last; | ||
55 | uint m_count; | ||
56 | }; | ||
57 | |||
58 | typedef OCompTreeNodeList OCompTreeChildren; | ||
59 | typedef 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 | |||
95 | class OCompTreeNode : public QChar | ||
96 | { | ||
97 | public: | ||
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 | |||
139 | private: | ||
140 | uint myWeight; | ||
141 | OCompTreeNodeListmyChildren; | ||
142 | //static OZoneAllocator alloc; // FIXME: Do we need this for Opie? | ||
143 | }; | ||
144 | |||
145 | /**************************************************************************************************/ | ||
146 | /* OCompletionMatchesWrapper | ||
147 | /**************************************************************************************************/ | ||
148 | |||
149 | class OCompletionMatchesWrapper | ||
150 | { | ||
151 | public: | ||
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 | |||
219 | class OCompletionPrivate | ||
220 | { | ||
221 | public: | ||
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 | |||
231 | OCompletion::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 | |||
245 | OCompletion::~OCompletion() | ||
246 | { | ||
247 | delete d; | ||
248 | delete myTreeRoot; | ||
249 | } | ||
250 | |||
251 | |||
252 | void OCompletion::setOrder( CompOrder order ) | ||
253 | { | ||
254 | myOrder = order; | ||
255 | d->matches.setSorting( order == Weighted ); | ||
256 | } | ||
257 | |||
258 | |||
259 | void OCompletion::setIgnoreCase( bool ignoreCase ) | ||
260 | { | ||
261 | myIgnoreCase = ignoreCase; | ||
262 | } | ||
263 | |||
264 | |||
265 | void OCompletion::setItems( const QStringList& items ) | ||
266 | { | ||
267 | clear(); | ||
268 | insertItems( items ); | ||
269 | } | ||
270 | |||
271 | |||
272 | void 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 | |||
285 | QStringList 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 | |||
295 | void 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 | |||
305 | void 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 | |||
331 | void 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 | |||
357 | void 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 | |||
367 | void 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 | |||
378 | QString 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 | |||
439 | QStringList 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 | |||
478 | void OCompletion::setCompletionMode( OGlobalSettings::Completion mode ) | ||
479 | { | ||
480 | myCompletionMode = mode; | ||
481 | } | ||
482 | |||
483 | |||
484 | QStringList 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 | |||
498 | OCompletionMatches 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 | |||
511 | QStringList 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 | |||
521 | OCompletionMatches 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 | |||
535 | QString 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 | |||
568 | QString 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 | ||
603 | QString 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 | |||
679 | void 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 | |||
734 | void 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 | |||
775 | void 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 | |||
811 | void 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 | |||
846 | OCompTreeNode::~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. | ||
860 | OCompTreeNode * 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 :-) | ||
896 | void 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 | |||
916 | QStringList 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 | |||
932 | OCompletionMatches::OCompletionMatches( bool sort_P ) | ||
933 | : _sorting( sort_P ) | ||
934 | { | ||
935 | } | ||
936 | |||
937 | OCompletionMatches::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 | |||
951 | OCompletionMatches::~OCompletionMatches() | ||
952 | { | ||
953 | } | ||
954 | |||
955 | QStringList 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 | |||
966 | void 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 | |||
983 | void 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 | |||
997 | void 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 | |||
1010 | void 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 | |||
1026 | OCompTreeNode *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 | |||
1047 | OCompTreeNode *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 | |||
50 | class OCompTreeNode; | ||
51 | class OCompletionPrivate; | ||
52 | class OCompletionBasePrivate; | ||
53 | class OCompletionMatchesWrapper; | ||
54 | class OCompletionMatches; | ||
55 | class QPopupMenu; | ||
56 | |||
57 | // FIXME: Do we need special ShortCut handling in Opie? If so, revise this. | ||
58 | class OShortcut | ||
59 | { | ||
60 | public: | ||
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 | |||
156 | class 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 | |||
513 | private: | ||
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 | ||
548 | typedef OSortableValueList<QString> OCompletionMatchesList; | ||
549 | class 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 | |||
570 | class 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 | } | ||
598 | private: | ||
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 | |||
36 | OCompletionBase::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 | |||
52 | OCompletionBase::~OCompletionBase() | ||
53 | { | ||
54 | if( m_bAutoDelCompObj && m_pCompObj ) | ||
55 | { | ||
56 | delete m_pCompObj; | ||
57 | } | ||
58 | } | ||
59 | |||
60 | void 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 | |||
73 | OCompletion* 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 | |||
86 | void 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) | ||
104 | void OCompletionBase::setHandleSignals( bool handle ) | ||
105 | { | ||
106 | if ( m_delegate ) | ||
107 | m_delegate->setHandleSignals( handle ); | ||
108 | else | ||
109 | m_bHandleSignals = handle; | ||
110 | } | ||
111 | |||
112 | void 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 | |||
126 | bool 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 | |||
141 | void 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 | |||
161 | void 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 | |||
51 | class 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 | |||
358 | protected: | ||
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 | |||
372 | private: | ||
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 | |||
47 | template <class T1, class T2> | ||
48 | struct 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 | |||
64 | template <class T1, class T2> | ||
65 | inline 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 | |||
70 | template <class T1, class T2> | ||
71 | inline 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 | |||
77 | template <class T1, class T2> | ||
78 | inline 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 | ||
84 | template <class T1, class T2> | ||
85 | inline QDataStream& operator>>( QDataStream& s, QPair<T1, T2>& p ) | ||
86 | { | ||
87 | s >> p.first >> p.second; | ||
88 | return s; | ||
89 | } | ||
90 | |||
91 | template <class T1, class T2> | ||
92 | inline 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 | |||
43 | template<class T, class Key = int> class OSortableItem : public QPair<Key,T> | ||
44 | { | ||
45 | public: | ||
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 | ||
92 | template <class T, class Key = int> | ||
93 | class OSortableValueList : public QValueList<OSortableItem<T, Key> > | ||
94 | { | ||
95 | public: | ||
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 | ||
51 | template <class T> | ||
52 | class QTextOStreamIterator | ||
53 | { | ||
54 | protected: | ||
55 | QTextOStream& stream; | ||
56 | QString separator; | ||
57 | |||
58 | public: | ||
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 | |||
74 | template <class InputIterator, class OutputIterator> | ||
75 | inline OutputIterator qCopy( InputIterator _begin, InputIterator _end, | ||
76 | OutputIterator _dest ) | ||
77 | { | ||
78 | while( _begin != _end ) | ||
79 | *_dest++ = *_begin++; | ||
80 | return _dest; | ||
81 | } | ||
82 | |||
83 | template <class BiIterator, class BiOutputIterator> | ||
84 | inline BiOutputIterator qCopyBackward( BiIterator _begin, BiIterator _end, | ||
85 | BiOutputIterator _dest ) | ||
86 | { | ||
87 | while ( _begin != _end ) | ||
88 | *--_dest = *--_end; | ||
89 | return _dest; | ||
90 | } | ||
91 | |||
92 | template <class InputIterator1, class InputIterator2> | ||
93 | inline 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 | |||
102 | template <class ForwardIterator, class T> | ||
103 | inline void qFill( ForwardIterator first, ForwardIterator last, const T& val ) | ||
104 | { | ||
105 | for ( ; first != last; ++first ) | ||
106 | *first = val; | ||
107 | } | ||
108 | |||
109 | #if 0 | ||
110 | template <class BiIterator, class OutputIterator> | ||
111 | inline 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 | |||
124 | template <class InputIterator, class T> | ||
125 | inline InputIterator qFind( InputIterator first, InputIterator last, | ||
126 | const T& val ) | ||
127 | { | ||
128 | while ( first != last && *first != val ) | ||
129 | ++first; | ||
130 | return first; | ||
131 | } | ||
132 | |||
133 | template <class InputIterator, class T, class Size> | ||
134 | inline 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 | |||
142 | template <class T> | ||
143 | inline void qSwap( T& _value1, T& _value2 ) | ||
144 | { | ||
145 | T tmp = _value1; | ||
146 | _value1 = _value2; | ||
147 | _value2 = tmp; | ||
148 | } | ||
149 | |||
150 | |||
151 | template <class InputIterator> | ||
152 | inline 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 | |||
185 | template <class Container> | ||
186 | inline void qBubbleSort( Container &c ) | ||
187 | { | ||
188 | qBubbleSort( c.begin(), c.end() ); | ||
189 | } | ||
190 | |||
191 | |||
192 | template <class Value> | ||
193 | inline 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 | |||
221 | template <class InputIterator, class Value> | ||
222 | inline 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 | |||
252 | template <class InputIterator> | ||
253 | inline 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 | |||
273 | template <class Container> | ||
274 | inline 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 | |||
284 | template <class Container> | ||
285 | class QBackInsertIterator | ||
286 | { | ||
287 | public: | ||
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 | |||
315 | protected: | ||
316 | Container *container; | ||
317 | }; | ||
318 | |||
319 | template <class Container> | ||
320 | inline 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 | |||
50 | class OComboBox::OComboBoxPrivate | ||
51 | { | ||
52 | public: | ||
53 | OComboBoxPrivate() | ||
54 | { | ||
55 | olineEdit = 0L; | ||
56 | } | ||
57 | ~OComboBoxPrivate() | ||
58 | { | ||
59 | } | ||
60 | |||
61 | OLineEdit *olineEdit; | ||
62 | }; | ||
63 | |||
64 | /*====================================================================================== | ||
65 | * OComboBox | ||
66 | *======================================================================================*/ | ||
67 | |||
68 | OComboBox::OComboBox( QWidget *parent, const char *name ) | ||
69 | : QComboBox( parent, name ) | ||
70 | { | ||
71 | init(); | ||
72 | } | ||
73 | |||
74 | OComboBox::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 | |||
86 | OComboBox::~OComboBox() | ||
87 | { | ||
88 | delete d; | ||
89 | } | ||
90 | |||
91 | void 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 | |||
116 | bool 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 | |||
128 | void 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 | |||
145 | void OComboBox::setContextMenuEnabled( bool showMenu ) | ||
146 | { | ||
147 | if( d->olineEdit ) | ||
148 | { | ||
149 | d->olineEdit->setContextMenuEnabled( showMenu ); | ||
150 | m_bEnableMenu = showMenu; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | void OComboBox::setURLDropsEnabled( bool enable ) | ||
156 | { | ||
157 | if ( d->olineEdit ) | ||
158 | d->olineEdit->setURLDropsEnabled( enable ); | ||
159 | } | ||
160 | |||
161 | bool OComboBox::isURLDropsEnabled() const | ||
162 | { | ||
163 | return d->olineEdit && d->olineEdit->isURLDropsEnabled(); | ||
164 | } | ||
165 | */ | ||
166 | |||
167 | void OComboBox::setCompletedText( const QString& text, bool marked ) | ||
168 | { | ||
169 | if ( d->olineEdit ) | ||
170 | d->olineEdit->setCompletedText( text, marked ); | ||
171 | } | ||
172 | |||
173 | void OComboBox::setCompletedText( const QString& text ) | ||
174 | { | ||
175 | if ( d->olineEdit ) | ||
176 | d->olineEdit->setCompletedText( text ); | ||
177 | } | ||
178 | |||
179 | void 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 | |||
196 | void OComboBox::rotateText( OCompletionBase::KeyBindingType type ) | ||
197 | { | ||
198 | if ( d->olineEdit ) | ||
199 | d->olineEdit->rotateText( type ); | ||
200 | } | ||
201 | |||
202 | bool 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 | |||
260 | void OComboBox::setTrapReturnKey( bool grab ) | ||
261 | { | ||
262 | m_trapReturnKey = grab; | ||
263 | } | ||
264 | |||
265 | bool OComboBox::trapReturnKey() const | ||
266 | { | ||
267 | return m_trapReturnKey; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | void OComboBox::setEditURL( const OURL& url ) | ||
272 | { | ||
273 | QComboBox::setEditText( url.prettyURL() ); | ||
274 | } | ||
275 | |||
276 | void OComboBox::insertURL( const OURL& url, int index ) | ||
277 | { | ||
278 | QComboBox::insertItem( url.prettyURL(), index ); | ||
279 | } | ||
280 | |||
281 | void OComboBox::insertURL( const QPixmap& pixmap, const OURL& url, int index ) | ||
282 | { | ||
283 | QComboBox::insertItem( pixmap, url.prettyURL(), index ); | ||
284 | } | ||
285 | |||
286 | void OComboBox::changeURL( const OURL& url, int index ) | ||
287 | { | ||
288 | QComboBox::changeItem( url.prettyURL(), index ); | ||
289 | } | ||
290 | |||
291 | void OComboBox::changeURL( const QPixmap& pixmap, const OURL& url, int index ) | ||
292 | { | ||
293 | QComboBox::changeItem( pixmap, url.prettyURL(), index ); | ||
294 | } | ||
295 | */ | ||
296 | |||
297 | |||
298 | void OComboBox::setCompletedItems( const QStringList& items ) | ||
299 | { | ||
300 | if ( d->olineEdit ) | ||
301 | d->olineEdit->setCompletedItems( items ); | ||
302 | } | ||
303 | |||
304 | |||
305 | OCompletionBox * 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 | ||
313 | void OComboBox::create( WId id, bool initializeWindow, bool destroyOldWindow ) | ||
314 | { | ||
315 | QComboBox::create( id, initializeWindow, destroyOldWindow ); | ||
316 | //OCursor::setAutoHideCursor( lineEdit(), true, true ); | ||
317 | } | ||
318 | |||
319 | void 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 | ||
349 | void 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 | |||
362 | void 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 | |||
375 | void 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 | |||
395 | void OComboBox::setCurrentItem(int index) | ||
396 | { | ||
397 | QComboBox::setCurrentItem(index); | ||
398 | } | ||
399 | |||
400 | |||
401 | /*====================================================================================== | ||
402 | * OHistoryCombo | ||
403 | *======================================================================================*/ | ||
404 | |||
405 | // we are always read-write | ||
406 | OHistoryCombo::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 | ||
413 | OHistoryCombo::OHistoryCombo( bool useCompletion, | ||
414 | QWidget *parent, const char *name ) | ||
415 | : OComboBox( true, parent, name ) | ||
416 | { | ||
417 | init( useCompletion ); | ||
418 | } | ||
419 | |||
420 | void 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 | |||
436 | OHistoryCombo::~OHistoryCombo() | ||
437 | { | ||
438 | delete myPixProvider; | ||
439 | } | ||
440 | |||
441 | void 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 | |||
463 | QStringList 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 | |||
472 | void OHistoryCombo::clearHistory() | ||
473 | { | ||
474 | OComboBox::clear(); | ||
475 | if ( useCompletion() ) | ||
476 | completionObject()->clear(); | ||
477 | } | ||
478 | |||
479 | void 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 | |||
488 | void 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 | |||
527 | bool 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 | |||
548 | void 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 | |||
619 | void OHistoryCombo::slotReset() | ||
620 | { | ||
621 | myIterateIndex = -1; | ||
622 | myRotated = false; | ||
623 | } | ||
624 | |||
625 | |||
626 | void 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 | |||
644 | void 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 | |||
661 | void 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 | |||
48 | class QListBoxItem; | ||
49 | class QPopupMenu; | ||
50 | class OCompletionBox; | ||
51 | typedef 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 | */ | ||
143 | class 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 | |||
151 | public: | ||
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 | |||
341 | signals: | ||
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 | |||
416 | public 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 | |||
460 | protected 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 | |||
480 | protected: | ||
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 | |||
497 | private: | ||
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 ); | ||
534 | private: | ||
535 | class OComboBoxPrivate; | ||
536 | OComboBoxPrivate *d; | ||
537 | }; | ||
538 | |||
539 | |||
540 | class 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 | */ | ||
552 | class OHistoryCombo : public OComboBox | ||
553 | { | ||
554 | Q_OBJECT | ||
555 | Q_PROPERTY( QStringList historyItems READ historyItems WRITE setHistoryItems ) | ||
556 | |||
557 | public: | ||
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 | |||
691 | public 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 | |||
718 | signals: | ||
719 | /** | ||
720 | * Emitted when the history was cleared by the entry in the popup menu. | ||
721 | */ | ||
722 | void cleared(); | ||
723 | |||
724 | protected: | ||
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 | |||
746 | private 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 | |||
763 | private: | ||
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 | |||
783 | private: | ||
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 | |||
41 | class OCompletionBox::OCompletionBoxPrivate | ||
42 | { | ||
43 | public: | ||
44 | QWidget *m_parent; // necessary to set the focus back | ||
45 | QString cancelText; | ||
46 | bool tabHandling; | ||
47 | bool down_workaround; | ||
48 | }; | ||
49 | |||
50 | OCompletionBox::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 | |||
80 | OCompletionBox::~OCompletionBox() | ||
81 | { | ||
82 | d->m_parent = 0L; | ||
83 | delete d; | ||
84 | } | ||
85 | |||
86 | QStringList 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 | |||
95 | void OCompletionBox::slotActivated( QListBoxItem *item ) | ||
96 | { | ||
97 | if ( !item ) | ||
98 | return; | ||
99 | |||
100 | hide(); | ||
101 | emit activated( item->text() ); | ||
102 | } | ||
103 | |||
104 | bool 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 | |||
205 | void 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 | |||
223 | void 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 | |||
252 | void OCompletionBox::hide() | ||
253 | { | ||
254 | if ( d->m_parent ) | ||
255 | qApp->removeEventFilter( this ); | ||
256 | d->cancelText = QString::null; | ||
257 | OListBox::hide(); | ||
258 | } | ||
259 | |||
260 | QSize 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 | |||
271 | void 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 | |||
286 | void OCompletionBox::up() | ||
287 | { | ||
288 | if ( currentItem() > 0 ) | ||
289 | setCurrentItem( currentItem() - 1 ); | ||
290 | } | ||
291 | |||
292 | void OCompletionBox::pageDown() | ||
293 | { | ||
294 | int i = currentItem() + numItemsVisible(); | ||
295 | i = i > (int)count() - 1 ? (int)count() - 1 : i; | ||
296 | setCurrentItem( i ); | ||
297 | } | ||
298 | |||
299 | void OCompletionBox::pageUp() | ||
300 | { | ||
301 | int i = currentItem() - numItemsVisible(); | ||
302 | i = i < 0 ? 0 : i; | ||
303 | setCurrentItem( i ); | ||
304 | } | ||
305 | |||
306 | void OCompletionBox::home() | ||
307 | { | ||
308 | setCurrentItem( 0 ); | ||
309 | } | ||
310 | |||
311 | void OCompletionBox::end() | ||
312 | { | ||
313 | setCurrentItem( count() -1 ); | ||
314 | } | ||
315 | |||
316 | void OCompletionBox::setTabHandling( bool enable ) | ||
317 | { | ||
318 | d->tabHandling = enable; | ||
319 | } | ||
320 | |||
321 | bool OCompletionBox::isTabHandling() const | ||
322 | { | ||
323 | return d->tabHandling; | ||
324 | } | ||
325 | |||
326 | void OCompletionBox::setCancelledText( const QString& text ) | ||
327 | { | ||
328 | d->cancelText = text; | ||
329 | } | ||
330 | |||
331 | QString OCompletionBox::cancelledText() const | ||
332 | { | ||
333 | return d->cancelText; | ||
334 | } | ||
335 | |||
336 | void OCompletionBox::cancelled() | ||
337 | { | ||
338 | if ( !d->cancelText.isNull() ) | ||
339 | emit userCancelled( d->cancelText ); | ||
340 | if ( isVisible() ) | ||
341 | hide(); | ||
342 | } | ||
343 | |||
344 | class OCompletionBoxItem : public QListBoxItem | ||
345 | { | ||
346 | public: | ||
347 | void reuse( const QString &text ) { setText( text ); } | ||
348 | }; | ||
349 | |||
350 | |||
351 | void 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 | |||
360 | void 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 | |||
391 | void OCompletionBox::slotCurrentChanged() | ||
392 | { | ||
393 | d->down_workaround = false; | ||
394 | } | ||
395 | |||
396 | void 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 | |||
36 | class 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 | */ | ||
57 | class 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 | |||
63 | public: | ||
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 | |||
84 | public 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 | |||
193 | signals: | ||
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 | |||
206 | protected: | ||
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 | |||
213 | protected slots: | ||
214 | /** | ||
215 | * Called when an item was activated. Emits | ||
216 | * @ref activated() with the item. | ||
217 | */ | ||
218 | virtual void slotActivated( QListBoxItem * ); | ||
219 | |||
220 | private slots: | ||
221 | void slotSetCurrentItem( QListBoxItem *i ) { setCurrentItem( i ); } // grrr | ||
222 | void slotCurrentChanged(); | ||
223 | void cancelled(); | ||
224 | void slotItemClicked( QListBoxItem * ); | ||
225 | |||
226 | private: | ||
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 | |||
46 | class OEditListBoxPrivate | ||
47 | { | ||
48 | public: | ||
49 | bool m_checkAtEntering; | ||
50 | int buttons; | ||
51 | }; | ||
52 | |||
53 | /*====================================================================================== | ||
54 | * OEditListBox | ||
55 | *======================================================================================*/ | ||
56 | |||
57 | OEditListBox::OEditListBox(QWidget *parent, const char *name, | ||
58 | bool checkAtEntering, int buttons ) | ||
59 | :QGroupBox(parent, name ) | ||
60 | { | ||
61 | init( checkAtEntering, buttons ); | ||
62 | } | ||
63 | |||
64 | OEditListBox::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 | |||
71 | OEditListBox::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 | |||
80 | OEditListBox::~OEditListBox() | ||
81 | { | ||
82 | delete d; | ||
83 | d=0; | ||
84 | } | ||
85 | |||
86 | void 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 | |||
166 | void 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 | |||
206 | void 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 | |||
229 | void 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 | |||
252 | void 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 | |||
300 | int 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 | |||
311 | void 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 | |||
331 | void 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 | |||
367 | void OEditListBox::clear() | ||
368 | { | ||
369 | m_lineEdit->clear(); | ||
370 | m_listBox->clear(); | ||
371 | emit changed(); | ||
372 | } | ||
373 | |||
374 | void OEditListBox::insertStringList(const QStringList& list, int index) | ||
375 | { | ||
376 | m_listBox->insertStringList(list,index); | ||
377 | } | ||
378 | |||
379 | void OEditListBox::insertStrList(const QStrList* list, int index) | ||
380 | { | ||
381 | m_listBox->insertStrList(list,index); | ||
382 | } | ||
383 | |||
384 | void OEditListBox::insertStrList(const QStrList& list, int index) | ||
385 | { | ||
386 | m_listBox->insertStrList(list,index); | ||
387 | } | ||
388 | |||
389 | void OEditListBox::insertStrList(const char ** list, int numStrings, int index) | ||
390 | { | ||
391 | m_listBox->insertStrList(list,numStrings,index); | ||
392 | } | ||
393 | |||
394 | QStringList 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 | |||
403 | void OEditListBox::virtual_hook( int, void* ) | ||
404 | { /*BASE::virtual_hook( id, data );*/ } | ||
405 | |||
406 | |||
407 | /*====================================================================================== | ||
408 | * CustomEditor | ||
409 | *======================================================================================*/ | ||
410 | |||
411 | OEditListBox::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 | |||
26 | class OLineEdit; | ||
27 | class OComboBox; | ||
28 | class 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 | |||
40 | class 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 | */ | ||
49 | class OEditListBox : public QGroupBox | ||
50 | { | ||
51 | Q_OBJECT | ||
52 | |||
53 | public: | ||
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 | |||
62 | class 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 | |||
80 | template class QPtrList<QListViewItem>; | ||
81 | |||
82 | /*====================================================================================== | ||
83 | * OJanusWidget | ||
84 | *======================================================================================*/ | ||
85 | |||
86 | OJanusWidget::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 | |||
197 | OJanusWidget::~OJanusWidget() | ||
198 | { | ||
199 | delete mPageList; | ||
200 | mPageList = 0; | ||
201 | delete mTitleList; | ||
202 | mTitleList = 0; | ||
203 | } | ||
204 | |||
205 | |||
206 | bool OJanusWidget::isValid() const | ||
207 | { | ||
208 | return( mValid ); | ||
209 | } | ||
210 | |||
211 | |||
212 | QFrame *OJanusWidget::plainPage() | ||
213 | { | ||
214 | return( mPlainPage ); | ||
215 | } | ||
216 | |||
217 | |||
218 | int OJanusWidget::face() const | ||
219 | { | ||
220 | return( mFace ); | ||
221 | } | ||
222 | |||
223 | QWidget *OJanusWidget::FindParent() | ||
224 | { | ||
225 | if( mFace == Tabbed ) { | ||
226 | return mTabControl; | ||
227 | } | ||
228 | else { | ||
229 | return this; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | QFrame *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 | |||
248 | void OJanusWidget::pageGone( QObject *obj ) | ||
249 | { | ||
250 | removePage( static_cast<QWidget*>( obj ) ); | ||
251 | } | ||
252 | |||
253 | void OJanusWidget::slotReopen( QListViewItem * item ) | ||
254 | { | ||
255 | if( item ) | ||
256 | item->setOpen( true ); | ||
257 | } | ||
258 | |||
259 | QFrame *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 | |||
269 | QVBox *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 | |||
286 | QVBox *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 | |||
295 | QHBox *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 | |||
311 | QHBox *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 | |||
320 | QGrid *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 | |||
339 | QGrid *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 | |||
349 | void 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 | |||
423 | void 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 | |||
490 | void OJanusWidget::setFolderIcon(const QStringList &path, const QPixmap &pixmap) | ||
491 | { | ||
492 | QString key = path.join("_/_"); | ||
493 | mFolderIconMap.insert(key,pixmap); | ||
494 | } | ||
495 | |||
496 | |||
497 | |||
498 | bool 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 | |||
550 | bool 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 | |||
577 | bool 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 | |||
590 | bool 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 | |||
652 | int 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 | |||
676 | int 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 | |||
708 | void 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 | ||
732 | void OJanusWidget::slotItemClicked(QListViewItem *it) | ||
733 | { | ||
734 | if(it && (it->childCount()>0)) | ||
735 | it->setOpen(!it->isOpen()); | ||
736 | } | ||
737 | |||
738 | void 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 | |||
764 | QSize 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 | |||
823 | QSize OJanusWidget::sizeHint() const | ||
824 | { | ||
825 | return( minimumSizeHint() ); | ||
826 | } | ||
827 | |||
828 | |||
829 | void 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 | |||
841 | void OJanusWidget::setIconListAllVisible( bool state ) | ||
842 | { | ||
843 | if( mFace == IconList ) | ||
844 | { | ||
845 | mIconList->setShowAll( state ); | ||
846 | } | ||
847 | } | ||
848 | |||
849 | void OJanusWidget::setShowIconsInTreeList( bool state ) | ||
850 | { | ||
851 | mShowIconsInTreeList = state; | ||
852 | } | ||
853 | |||
854 | void OJanusWidget::setRootIsDecorated( bool state ) | ||
855 | { | ||
856 | if( mFace == TreeList ) { | ||
857 | mTreeList->setRootIsDecorated(state); | ||
858 | } | ||
859 | } | ||
860 | |||
861 | void 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 | |||
875 | void 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 | // | ||
890 | bool 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 | |||
921 | OJanusWidget::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 | |||
929 | void 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 | |||
944 | void 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 | |||
971 | void OJanusWidget::IconListBox::invalidateHeight() | ||
972 | { | ||
973 | mHeightValid = false; | ||
974 | } | ||
975 | |||
976 | |||
977 | void OJanusWidget::IconListBox::invalidateWidth() | ||
978 | { | ||
979 | mWidthValid = false; | ||
980 | } | ||
981 | |||
982 | |||
983 | void OJanusWidget::IconListBox::setShowAll( bool showAll ) | ||
984 | { | ||
985 | mShowAll = showAll; | ||
986 | mHeightValid = false; | ||
987 | } | ||
988 | |||
989 | |||
990 | |||
991 | OJanusWidget::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 | |||
1005 | int OJanusWidget::IconListItem::expandMinimumWidth( int width ) | ||
1006 | { | ||
1007 | mMinimumWidth = QMAX( mMinimumWidth, width ); | ||
1008 | return( mMinimumWidth ); | ||
1009 | } | ||
1010 | |||
1011 | |||
1012 | const 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 | |||
1037 | void 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 | |||
1052 | int 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 | |||
1065 | int 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> | ||
1077 | void 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 | |||
43 | class QGrid; | ||
44 | class QHBox; | ||
45 | class QLabel; | ||
46 | class QTabWidget; | ||
47 | class QVBox; | ||
48 | class QWidgetStack; | ||
49 | class OSeparator; | ||
50 | class QListView; | ||
51 | class 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 | */ | ||
100 | class 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 | |||
46 | typedef QString KURL; //FIXME: Revise for Opie | ||
47 | |||
48 | /*====================================================================================== | ||
49 | * OLineEditPrivate | ||
50 | *======================================================================================*/ | ||
51 | |||
52 | class OLineEdit::OLineEditPrivate | ||
53 | { | ||
54 | public: | ||
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 | |||
76 | OLineEdit::OLineEdit( const QString &string, QWidget *parent, const char *name ) | ||
77 | : QLineEdit( string, parent, name ) | ||
78 | { | ||
79 | init(); | ||
80 | } | ||
81 | |||
82 | OLineEdit::OLineEdit( QWidget *parent, const char *name ) | ||
83 | : QLineEdit( parent, name ) | ||
84 | { | ||
85 | init(); | ||
86 | } | ||
87 | |||
88 | OLineEdit::~OLineEdit () | ||
89 | { | ||
90 | delete d; | ||
91 | } | ||
92 | |||
93 | void 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 | |||
103 | void 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 | |||
118 | void 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 | |||
128 | void 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 | |||
137 | void 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 | |||
156 | void 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 | |||
187 | void 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 | |||
207 | void 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 | |||
407 | void 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 | |||
418 | void OLineEdit::mousePressEvent( QMouseEvent* e ) | ||
419 | { | ||
420 | if ( possibleTripleClick && e->button() == Qt::LeftButton ) | ||
421 | { | ||
422 | selectAll(); | ||
423 | return; | ||
424 | } | ||
425 | QLineEdit::mousePressEvent( e ); | ||
426 | } | ||
427 | |||
428 | void OLineEdit::tripleClickTimeout() | ||
429 | { | ||
430 | possibleTripleClick=false; | ||
431 | } | ||
432 | |||
433 | QPopupMenu *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 | |||
493 | void 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 | |||
546 | bool 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 | |||
586 | void OLineEdit::setURLDropsEnabled(bool enable) | ||
587 | { | ||
588 | d->handleURLDrops=enable; | ||
589 | } | ||
590 | |||
591 | bool OLineEdit::isURLDropsEnabled() const | ||
592 | { | ||
593 | return d->handleURLDrops; | ||
594 | } | ||
595 | |||
596 | void OLineEdit::setTrapReturnKey( bool grab ) | ||
597 | { | ||
598 | d->grabReturnKeyEvents = grab; | ||
599 | } | ||
600 | |||
601 | bool 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 | |||
611 | void 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 | |||
676 | void 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 | |||
697 | OCompletionBox * OLineEdit::completionBox( bool create ) | ||
698 | { | ||
699 | if ( create ) | ||
700 | makeCompletionBox(); | ||
701 | |||
702 | return d->completionBox; | ||
703 | } | ||
704 | |||
705 | void 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 | ||
720 | void OLineEdit::create( WId id, bool initializeWindow, bool destroyOldWindow ) | ||
721 | { | ||
722 | QLineEdit::create( id, initializeWindow, destroyOldWindow ); | ||
723 | //OCursor::setAutoHideCursor( this, true, true ); | ||
724 | } | ||
725 | |||
726 | void 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 | |||
45 | class QPopupMenu; | ||
46 | |||
47 | class OCompletionBox; | ||
48 | typedef 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 | |||
150 | class 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 | |||
158 | public: | ||
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 | |||
289 | signals: | ||
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 | |||
347 | public 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 | |||
383 | protected 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 | |||
401 | protected: | ||
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 | |||
454 | private slots: | ||
455 | void completionMenuActivated( int id ); | ||
456 | void tripleClickTimeout(); // resets possibleTripleClick | ||
457 | |||
458 | private: | ||
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 | |||
491 | protected: | ||
492 | //virtual void virtual_hook( int id, void* data ); | ||
493 | private: | ||
494 | class OLineEditPrivate; | ||
495 | OLineEditPrivate *d; | ||
496 | }; | ||
497 | |||
498 | #endif | ||