summaryrefslogtreecommitdiff
path: root/inputmethods
authorkergoth <kergoth>2002-01-25 22:14:26 (UTC)
committer kergoth <kergoth>2002-01-25 22:14:26 (UTC)
commit15318cad33835e4e2dc620d033e43cd930676cdd (patch) (unidiff)
treec2fa0399a2c47fda8e2cd0092c73a809d17f68eb /inputmethods
downloadopie-15318cad33835e4e2dc620d033e43cd930676cdd.zip
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2
Initial revision
Diffstat (limited to 'inputmethods') (more/less context) (ignore whitespace changes)
-rw-r--r--inputmethods/.cvsignore1
-rw-r--r--inputmethods/handwriting/.cvsignore5
-rw-r--r--inputmethods/handwriting/Makefile.in281
-rw-r--r--inputmethods/handwriting/handwriting.pro33
-rw-r--r--inputmethods/handwriting/handwritingimpl.cpp113
-rw-r--r--inputmethods/handwriting/handwritingimpl.h51
-rw-r--r--inputmethods/handwriting/qimpenchar.cpp505
-rw-r--r--inputmethods/handwriting/qimpenchar.h157
-rw-r--r--inputmethods/handwriting/qimpencombining.cpp141
-rw-r--r--inputmethods/handwriting/qimpencombining.h41
-rw-r--r--inputmethods/handwriting/qimpenhelp.cpp410
-rw-r--r--inputmethods/handwriting/qimpenhelp.h85
-rw-r--r--inputmethods/handwriting/qimpeninput.cpp515
-rw-r--r--inputmethods/handwriting/qimpeninput.h94
-rw-r--r--inputmethods/handwriting/qimpenmatch.cpp365
-rw-r--r--inputmethods/handwriting/qimpenmatch.h107
-rw-r--r--inputmethods/handwriting/qimpenprefbase.ui185
-rw-r--r--inputmethods/handwriting/qimpenprofile.cpp245
-rw-r--r--inputmethods/handwriting/qimpenprofile.h70
-rw-r--r--inputmethods/handwriting/qimpensetup.cpp656
-rw-r--r--inputmethods/handwriting/qimpensetup.h124
-rw-r--r--inputmethods/handwriting/qimpenstroke.cpp646
-rw-r--r--inputmethods/handwriting/qimpenstroke.h91
-rw-r--r--inputmethods/handwriting/qimpenwidget.cpp446
-rw-r--r--inputmethods/handwriting/qimpenwidget.h88
-rw-r--r--inputmethods/handwriting/qimpenwordpick.cpp113
-rw-r--r--inputmethods/handwriting/qimpenwordpick.h49
-rw-r--r--inputmethods/handwriting/qpe-handwriting.control9
-rwxr-xr-xinputmethods/handwriting/qpe-handwriting.postinst2
-rwxr-xr-xinputmethods/handwriting/qpe-handwriting.postrm2
-rw-r--r--inputmethods/keyboard/.cvsignore3
-rw-r--r--inputmethods/keyboard/Makefile.in151
-rw-r--r--inputmethods/keyboard/keyboard.cpp794
-rw-r--r--inputmethods/keyboard/keyboard.h103
-rw-r--r--inputmethods/keyboard/keyboard.pro18
-rw-r--r--inputmethods/keyboard/keyboardimpl.cpp131
-rw-r--r--inputmethods/keyboard/keyboardimpl.h51
-rw-r--r--inputmethods/keyboard/qpe-keyboard.control9
-rwxr-xr-xinputmethods/keyboard/qpe-keyboard.postinst2
-rwxr-xr-xinputmethods/keyboard/qpe-keyboard.postrm2
-rw-r--r--inputmethods/pickboard/.cvsignore3
-rw-r--r--inputmethods/pickboard/Makefile.in147
-rw-r--r--inputmethods/pickboard/pickboard.cpp89
-rw-r--r--inputmethods/pickboard/pickboard.h43
-rw-r--r--inputmethods/pickboard/pickboard.pro12
-rw-r--r--inputmethods/pickboard/pickboardcfg.cpp731
-rw-r--r--inputmethods/pickboard/pickboardcfg.h213
-rw-r--r--inputmethods/pickboard/pickboardimpl.cpp101
-rw-r--r--inputmethods/pickboard/pickboardimpl.h51
-rw-r--r--inputmethods/pickboard/pickboardpicks.cpp418
-rw-r--r--inputmethods/pickboard/pickboardpicks.h66
-rw-r--r--inputmethods/pickboard/qpe-pickboard.control9
-rwxr-xr-xinputmethods/pickboard/qpe-pickboard.postinst2
-rwxr-xr-xinputmethods/pickboard/qpe-pickboard.postrm2
-rw-r--r--inputmethods/unikeyboard/.cvsignore3
-rw-r--r--inputmethods/unikeyboard/Makefile.in115
-rw-r--r--inputmethods/unikeyboard/qpe-unikeyboard.control9
-rwxr-xr-xinputmethods/unikeyboard/qpe-unikeyboard.postinst2
-rwxr-xr-xinputmethods/unikeyboard/qpe-unikeyboard.postrm2
-rw-r--r--inputmethods/unikeyboard/unikeyboard.cpp278
-rw-r--r--inputmethods/unikeyboard/unikeyboard.h77
-rw-r--r--inputmethods/unikeyboard/unikeyboard.pro12
-rw-r--r--inputmethods/unikeyboard/unikeyboardimpl.cpp105
-rw-r--r--inputmethods/unikeyboard/unikeyboardimpl.h49
64 files changed, 9433 insertions, 0 deletions
diff --git a/inputmethods/.cvsignore b/inputmethods/.cvsignore
new file mode 100644
index 0000000..f3c7a7c
--- a/dev/null
+++ b/inputmethods/.cvsignore
@@ -0,0 +1 @@
Makefile
diff --git a/inputmethods/handwriting/.cvsignore b/inputmethods/handwriting/.cvsignore
new file mode 100644
index 0000000..285856f
--- a/dev/null
+++ b/inputmethods/handwriting/.cvsignore
@@ -0,0 +1,5 @@
1moc_*
2*.moc
3Makefile
4qimpenprefbase.h
5qimpenprefbase.cpp
diff --git a/inputmethods/handwriting/Makefile.in b/inputmethods/handwriting/Makefile.in
new file mode 100644
index 0000000..aabb5aa
--- a/dev/null
+++ b/inputmethods/handwriting/Makefile.in
@@ -0,0 +1,281 @@
1#############################################################################
2
3####### Compiler, tools and options
4
5 CXX =$(SYSCONF_CXX) $(QT_CXX_MT)
6 CXXFLAGS=$(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB)
7 CC =$(SYSCONF_CC) $(QT_C_MT)
8 CFLAGS =$(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB)
9 INCPATH =-I$(QPEDIR)/include
10 LFLAGS =$(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
11 LIBS =$(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP)
12 MOC =$(SYSCONF_MOC)
13 UIC =$(SYSCONF_UIC)
14
15####### Target
16
17DESTDIR = ../../plugins/inputmethods/
18VER_MAJ = 1
19VER_MIN = 0
20VER_PATCH = 0
21 TARGET= qhandwriting
22TARGET1 = lib$(TARGET).so.$(VER_MAJ)
23
24####### Files
25
26 HEADERS =qimpenchar.h \
27 qimpenprofile.h \
28 qimpencombining.h \
29 qimpenhelp.h \
30 qimpeninput.h \
31 qimpenmatch.h \
32 qimpensetup.h \
33 qimpenstroke.h \
34 qimpenwidget.h \
35 qimpenwordpick.h \
36 handwritingimpl.h
37 SOURCES =qimpenchar.cpp \
38 qimpenprofile.cpp \
39 qimpencombining.cpp \
40 qimpenhelp.cpp \
41 qimpeninput.cpp \
42 qimpenmatch.cpp \
43 qimpensetup.cpp \
44 qimpenstroke.cpp \
45 qimpenwidget.cpp \
46 qimpenwordpick.cpp \
47 handwritingimpl.cpp
48 OBJECTS =qimpenchar.o \
49 qimpenprofile.o \
50 qimpencombining.o \
51 qimpenhelp.o \
52 qimpeninput.o \
53 qimpenmatch.o \
54 qimpensetup.o \
55 qimpenstroke.o \
56 qimpenwidget.o \
57 qimpenwordpick.o \
58 handwritingimpl.o \
59 qimpenprefbase.o
60INTERFACES = qimpenprefbase.ui
61UICDECLS = qimpenprefbase.h
62UICIMPLS = qimpenprefbase.cpp
63 SRCMOC =moc_qimpenhelp.cpp \
64 moc_qimpeninput.cpp \
65 moc_qimpenmatch.cpp \
66 moc_qimpensetup.cpp \
67 moc_qimpenwidget.cpp \
68 moc_qimpenwordpick.cpp \
69 moc_qimpenprefbase.cpp
70 OBJMOC =moc_qimpenhelp.o \
71 moc_qimpeninput.o \
72 moc_qimpenmatch.o \
73 moc_qimpensetup.o \
74 moc_qimpenwidget.o \
75 moc_qimpenwordpick.o \
76 moc_qimpenprefbase.o
77
78
79####### Implicit rules
80
81.SUFFIXES: .cpp .cxx .cc .C .c
82
83.cpp.o:
84 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
85
86.cxx.o:
87 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
88
89.cc.o:
90 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
91
92.C.o:
93 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
94
95.c.o:
96 $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
97
98####### Build rules
99
100
101all: $(DESTDIR)$(SYSCONF_LINK_TARGET)
102
103$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
104 $(SYSCONF_LINK_LIB)
105
106moc: $(SRCMOC)
107
108tmake:
109 tmake handwriting.pro
110
111clean:
112 -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
113 -rm -f *~ core
114 -rm -f allmoc.cpp
115
116####### Extension Modules
117
118listpromodules:
119 @echo
120
121listallmodules:
122 @echo
123
124listaddonpromodules:
125 @echo
126
127listaddonentmodules:
128 @echo
129
130
131REQUIRES=
132
133####### Sub-libraries
134
135
136###### Combined headers
137
138
139
140####### Compile
141
142qimpenchar.o: qimpenchar.cpp \
143 qimpencombining.h \
144 qimpenchar.h \
145 qimpenstroke.h
146
147qimpenprofile.o: qimpenprofile.cpp \
148 qimpencombining.h \
149 qimpenchar.h \
150 qimpenstroke.h \
151 qimpenprofile.h
152
153qimpencombining.o: qimpencombining.cpp \
154 qimpencombining.h \
155 qimpenchar.h \
156 qimpenstroke.h
157
158qimpenhelp.o: qimpenhelp.cpp \
159 qimpenwidget.h \
160 qimpenchar.h \
161 qimpenstroke.h \
162 qimpencombining.h \
163 qimpenmatch.h \
164 qimpenhelp.h \
165 qimpenprofile.h
166
167qimpeninput.o: qimpeninput.cpp \
168 qimpenwidget.h \
169 qimpenchar.h \
170 qimpenstroke.h \
171 qimpensetup.h \
172 qimpenprofile.h \
173 qimpeninput.h \
174 qimpencombining.h \
175 qimpenwordpick.h \
176 qimpenmatch.h \
177 qimpenhelp.h
178
179qimpenmatch.o: qimpenmatch.cpp \
180 qimpenmatch.h \
181 qimpenchar.h \
182 qimpenstroke.h
183
184qimpensetup.o: qimpensetup.cpp \
185 qimpenwidget.h \
186 qimpenchar.h \
187 qimpenstroke.h \
188 qimpenprefbase.h \
189 qimpensetup.h \
190 qimpenprofile.h
191
192qimpenstroke.o: qimpenstroke.cpp \
193 qimpenstroke.h
194
195qimpenwidget.o: qimpenwidget.cpp \
196 qimpenchar.h \
197 qimpenstroke.h \
198 qimpenwidget.h
199
200qimpenwordpick.o: qimpenwordpick.cpp \
201 qimpenwordpick.h \
202 qimpenmatch.h \
203 qimpenchar.h \
204 qimpenstroke.h
205
206handwritingimpl.o: handwritingimpl.cpp \
207 qimpeninput.h \
208 qimpenprofile.h \
209 qimpenchar.h \
210 qimpenstroke.h \
211 handwritingimpl.h
212
213qimpenprefbase.h: qimpenprefbase.ui
214 $(UIC) qimpenprefbase.ui -o $(INTERFACE_DECL_PATH)/qimpenprefbase.h
215
216qimpenprefbase.cpp: qimpenprefbase.ui
217 $(UIC) qimpenprefbase.ui -i qimpenprefbase.h -o qimpenprefbase.cpp
218
219qimpenprefbase.o: qimpenprefbase.cpp \
220 qimpenprefbase.h \
221 qimpenprefbase.ui
222
223moc_qimpenhelp.o: moc_qimpenhelp.cpp \
224 qimpenhelp.h \
225 qimpenchar.h \
226 qimpenstroke.h \
227 qimpenprofile.h
228
229moc_qimpeninput.o: moc_qimpeninput.cpp \
230 qimpeninput.h \
231 qimpenprofile.h \
232 qimpenchar.h \
233 qimpenstroke.h
234
235moc_qimpenmatch.o: moc_qimpenmatch.cpp \
236 qimpenmatch.h \
237 qimpenchar.h \
238 qimpenstroke.h
239
240moc_qimpensetup.o: moc_qimpensetup.cpp \
241 qimpensetup.h \
242 qimpenprofile.h \
243 qimpenchar.h \
244 qimpenstroke.h
245
246moc_qimpenwidget.o: moc_qimpenwidget.cpp \
247 qimpenwidget.h \
248 qimpenchar.h \
249 qimpenstroke.h
250
251moc_qimpenwordpick.o: moc_qimpenwordpick.cpp \
252 qimpenwordpick.h \
253 qimpenmatch.h \
254 qimpenchar.h \
255 qimpenstroke.h
256
257moc_qimpenprefbase.o: moc_qimpenprefbase.cpp \
258 qimpenprefbase.h
259
260moc_qimpenhelp.cpp: qimpenhelp.h
261 $(MOC) qimpenhelp.h -o moc_qimpenhelp.cpp
262
263moc_qimpeninput.cpp: qimpeninput.h
264 $(MOC) qimpeninput.h -o moc_qimpeninput.cpp
265
266moc_qimpenmatch.cpp: qimpenmatch.h
267 $(MOC) qimpenmatch.h -o moc_qimpenmatch.cpp
268
269moc_qimpensetup.cpp: qimpensetup.h
270 $(MOC) qimpensetup.h -o moc_qimpensetup.cpp
271
272moc_qimpenwidget.cpp: qimpenwidget.h
273 $(MOC) qimpenwidget.h -o moc_qimpenwidget.cpp
274
275moc_qimpenwordpick.cpp: qimpenwordpick.h
276 $(MOC) qimpenwordpick.h -o moc_qimpenwordpick.cpp
277
278moc_qimpenprefbase.cpp: qimpenprefbase.h
279 $(MOC) qimpenprefbase.h -o moc_qimpenprefbase.cpp
280
281
diff --git a/inputmethods/handwriting/handwriting.pro b/inputmethods/handwriting/handwriting.pro
new file mode 100644
index 0000000..999552b
--- a/dev/null
+++ b/inputmethods/handwriting/handwriting.pro
@@ -0,0 +1,33 @@
1 TEMPLATE= lib
2 CONFIG += qt warn_on release
3 HEADERS= qimpenchar.h \
4 qimpenprofile.h \
5 qimpencombining.h \
6 qimpenhelp.h \
7 qimpeninput.h \
8 qimpenmatch.h \
9 qimpensetup.h \
10 qimpenstroke.h \
11 qimpenwidget.h \
12 qimpenwordpick.h \
13 handwritingimpl.h
14 SOURCES= qimpenchar.cpp \
15 qimpenprofile.cpp \
16 qimpencombining.cpp \
17 qimpenhelp.cpp \
18 qimpeninput.cpp \
19 qimpenmatch.cpp \
20 qimpensetup.cpp \
21 qimpenstroke.cpp \
22 qimpenwidget.cpp \
23 qimpenwordpick.cpp \
24 handwritingimpl.cpp
25INTERFACES = qimpenprefbase.ui
26 TARGET = qhandwriting
27 DESTDIR = ../../plugins/inputmethods
28INCLUDEPATH += $(QPEDIR)/include
29DEPENDPATH += ../$(QPEDIR)/include ../../taskbar
30LIBS += -lqpe
31 VERSION = 1.0.0
32
33TRANSLATIONS += ../../i18n/de/libqhandwriting.ts
diff --git a/inputmethods/handwriting/handwritingimpl.cpp b/inputmethods/handwriting/handwritingimpl.cpp
new file mode 100644
index 0000000..c39e1aa
--- a/dev/null
+++ b/inputmethods/handwriting/handwritingimpl.cpp
@@ -0,0 +1,113 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include <qapplication.h>
22#include <qwidget.h>
23#include <qpixmap.h>
24#include "qimpeninput.h"
25#include "handwritingimpl.h"
26
27/* XPM */
28static const char * pen_xpm[] = {
29"28 13 9 1",
30" c None",
31". c #000000",
32"+ c #FFE993",
33"@ c #8292FF",
34"# c #F7C500",
35"$ c #C69F00",
36"% c #0022FF",
37"& c #000F72",
38"* c #A3732C",
39" . ",
40" .+. ",
41" .@#$. ",
42" .@%&. ",
43" .@%&. ",
44" . .@%&. ",
45" . .@%&. ",
46" . .@%&. ",
47" ... ... .. .@%&. ",
48" . . . . . .*.&. ",
49" . . . . . .**. ",
50" ... ... .. ... ",
51" "};
52
53HandwritingImpl::HandwritingImpl()
54 : input(0), icn(0), ref(0)
55{
56}
57
58HandwritingImpl::~HandwritingImpl()
59{
60 delete input;
61 delete icn;
62}
63
64QWidget *HandwritingImpl::inputMethod( QWidget *parent, Qt::WFlags f )
65{
66 if ( !input )
67 input = new QIMPenInput( parent, "Handwriting", f );
68 return input;
69}
70
71void HandwritingImpl::resetState()
72{
73 if ( input )
74 input->resetState();
75}
76
77QPixmap *HandwritingImpl::icon()
78{
79 if ( !icn )
80 icn = new QPixmap( (const char **)pen_xpm );
81 return icn;
82}
83
84QString HandwritingImpl::name()
85{
86 return qApp->translate( "InputMethods", "Handwriting" );
87}
88
89void HandwritingImpl::onKeyPress( QObject *receiver, const char *slot )
90{
91 if ( input )
92 QObject::connect( input, SIGNAL(key(ushort,ushort,ushort,bool,bool)), receiver, slot );
93}
94
95#ifndef QT_NO_COMPONENT
96QRESULT HandwritingImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface )
97{
98 *iface = 0;
99 if ( uuid == IID_QUnknown )
100 *iface = this;
101 else if ( uuid == IID_InputMethod )
102 *iface = this;
103
104 if ( *iface )
105 (*iface)->addRef();
106 return QS_OK;
107}
108
109Q_EXPORT_INTERFACE()
110{
111 Q_CREATE_INSTANCE( HandwritingImpl )
112}
113#endif
diff --git a/inputmethods/handwriting/handwritingimpl.h b/inputmethods/handwriting/handwritingimpl.h
new file mode 100644
index 0000000..1215853
--- a/dev/null
+++ b/inputmethods/handwriting/handwritingimpl.h
@@ -0,0 +1,51 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#ifndef HANDWRITINGIMPL_H
21#define HANDWRITINGIMPL_H
22
23#include <qpe/inputmethodinterface.h>
24
25class QIMPenInput;
26class QPixmap;
27
28class HandwritingImpl : public InputMethodInterface
29{
30public:
31 HandwritingImpl();
32 virtual ~HandwritingImpl();
33
34#ifndef QT_NO_COMPONENT
35 QRESULT queryInterface( const QUuid&, QUnknownInterface** );
36 Q_REFCOUNT
37#endif
38
39 virtual QWidget *inputMethod( QWidget *parent, Qt::WFlags f );
40 virtual void resetState();
41 virtual QPixmap *icon();
42 virtual QString name();
43 virtual void onKeyPress( QObject *receiver, const char *slot );
44
45private:
46 QIMPenInput *input;
47 QPixmap *icn;
48 ulong ref;
49};
50
51#endif
diff --git a/inputmethods/handwriting/qimpenchar.cpp b/inputmethods/handwriting/qimpenchar.cpp
new file mode 100644
index 0000000..9c38ec9
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenchar.cpp
@@ -0,0 +1,505 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include <qfile.h>
22#include <qtl.h>
23#include <math.h>
24#include <limits.h>
25#include <errno.h>
26#include <qdatastream.h>
27#include "qimpencombining.h"
28#include "qimpenchar.h"
29
30 #define QIMPEN_MATCH_THRESHOLD 200000
31
32const QIMPenSpecialKeys qimpen_specialKeys[] = {
33 { Qt::Key_Escape, "[Esc]" },
34 { Qt::Key_Tab, "[Tab]" },
35 { Qt::Key_Backspace,"[BackSpace]" },
36 { Qt::Key_Return, "[Return]" },
37 { QIMPenChar::Caps, "[Uppercase]" },
38 { QIMPenChar::CapsLock,"[Caps Lock]" },
39 { QIMPenChar::Shortcut,"[Shortcut]" },
40 { QIMPenChar::Punctuation, "[Punctuation]" },
41 { QIMPenChar::Symbol,"[Symbol]" },
42 { QIMPenChar::Extended,"[Extended]" },
43 { Qt::Key_unknown, 0 } };
44
45
46/*!
47 \class QIMPenChar qimpenchar.h
48
49 Handles a single character. Can calculate closeness of match to
50 another character.
51*/
52
53QIMPenChar::QIMPenChar()
54{
55 flags = 0;
56 strokes.setAutoDelete( TRUE );
57}
58
59QIMPenChar::QIMPenChar( const QIMPenChar &chr )
60{
61 strokes.setAutoDelete( TRUE );
62 ch = chr.ch;
63 flags = chr.flags;
64 d = chr.d;
65 QIMPenStrokeIterator it( chr.strokes );
66 while ( it.current() ) {
67 strokes.append( new QIMPenStroke( *it.current() ) );
68 ++it;
69 }
70}
71
72QIMPenChar &QIMPenChar::operator=( const QIMPenChar &chr )
73{
74 strokes.clear();
75 ch = chr.ch;
76 flags = chr.flags;
77 d = chr.d;
78 QIMPenStrokeIterator it( chr.strokes );
79 while ( it.current() ) {
80 strokes.append( new QIMPenStroke( *it.current() ) );
81 ++it;
82 }
83
84 return *this;
85}
86
87QString QIMPenChar::name() const
88{
89 QString n;
90
91 if ( (ch & 0x0000FFFF) == 0 ) {
92 int code = ch >> 16;
93 for ( int i = 0; qimpen_specialKeys[i].code != Qt::Key_unknown; i++ ) {
94 if ( qimpen_specialKeys[i].code == code ) {
95 n = qimpen_specialKeys[i].name;
96 break;
97 }
98 }
99 } else {
100 n = QChar( ch & 0x0000FFFF );
101 }
102
103 return n;
104}
105
106void QIMPenChar::clear()
107{
108 ch = 0;
109 flags = 0;
110 d = QString::null;
111 strokes.clear();
112}
113
114unsigned int QIMPenChar::strokeLength( int s ) const
115{
116 QIMPenStrokeIterator it( strokes );
117 while ( it.current() && s ) {
118 ++it;
119 --s;
120 }
121
122 if ( it.current() )
123 return it.current()->length();
124
125 return 0;
126}
127
128/*!
129 Add a stroke to the character
130*/
131void QIMPenChar::addStroke( QIMPenStroke *st )
132{
133 QIMPenStroke *stroke = new QIMPenStroke( *st );
134 strokes.append( stroke );
135}
136
137/*!
138 Return an indicator of the closeness of this character to \a pen.
139 Lower value is better.
140*/
141int QIMPenChar::match( QIMPenChar *pen )
142{
143/*
144 if ( strokes.count() > pen->strokes.count() )
145 return INT_MAX;
146*/
147 int err = 0;
148 int maxErr = 0;
149 int diff = 0;
150 QIMPenStrokeIterator it1( strokes );
151 QIMPenStrokeIterator it2( pen->strokes );
152 err = it1.current()->match( it2.current() );
153 if ( err > maxErr )
154 maxErr = err;
155 ++it1;
156 ++it2;
157 while ( err < 400000 && it1.current() && it2.current() ) {
158 QPoint p1 = it1.current()->boundingRect().center() -
159 strokes.getFirst()->boundingRect().center();
160 QPoint p2 = it2.current()->boundingRect().center() -
161 pen->strokes.getFirst()->boundingRect().center();
162 int xdiff = QABS( p1.x() - p2.x() ) - 6;
163 int ydiff = QABS( p1.y() - p2.y() ) - 5;
164 if ( xdiff < 0 )
165 xdiff = 0;
166 if ( ydiff < 0 )
167 ydiff = 0;
168 if ( xdiff > 10 || ydiff > 10 ) { // not a chance
169#ifdef DEBUG_QIMPEN
170 qDebug( "char %c, stroke starting pt diff excessive", pen->ch );
171#endif
172 return INT_MAX;
173 }
174 diff += xdiff*xdiff + ydiff*ydiff;
175 err = it1.current()->match( it2.current() );
176 if ( err > maxErr )
177 maxErr = err;
178 ++it1;
179 ++it2;
180 }
181
182 maxErr += diff * diff * 6; // magic weighting :)
183
184#ifdef DEBUG_QIMPEN
185 qDebug( "char: %c, maxErr %d, diff %d, (%d)", pen->ch, maxErr, diff, strokes.count() );
186#endif
187 return maxErr;
188}
189
190/*!
191 Return the bounding rect of this character. It may have sides with
192 negative coords since its origin is where the user started drawing
193 the character.
194*/
195QRect QIMPenChar::boundingRect()
196{
197 QRect br;
198 QIMPenStroke *st = strokes.first();
199 while ( st ) {
200 br |= st->boundingRect();
201 st = strokes.next();
202 }
203
204 return br;
205}
206
207
208/*!
209 Write the character's data to the stream.
210*/
211QDataStream &operator<< (QDataStream &s, const QIMPenChar &ws)
212{
213 s << ws.ch;
214 s << ws.flags;
215 if ( ws.flags & QIMPenChar::Data )
216 s << ws.d;
217 s << ws.strokes.count();
218 QIMPenStrokeIterator it( ws.strokes );
219 while ( it.current() ) {
220 s << *it.current();
221 ++it;
222 }
223
224 return s;
225}
226
227/*!
228 Read the character's data from the stream.
229*/
230QDataStream &operator>> (QDataStream &s, QIMPenChar &ws)
231{
232 s >> ws.ch;
233 s >> ws.flags;
234 if ( ws.flags & QIMPenChar::Data )
235 s >> ws.d;
236 unsigned size;
237 s >> size;
238 for ( unsigned i = 0; i < size; i++ ) {
239 QIMPenStroke *st = new QIMPenStroke();
240 s >> *st;
241 ws.strokes.append( st );
242 }
243
244 return s;
245}
246
247//===========================================================================
248
249bool QIMPenCharMatch::operator>( const QIMPenCharMatch &m )
250{
251 return error > m.error;
252}
253
254bool QIMPenCharMatch::operator<( const QIMPenCharMatch &m )
255{
256 return error < m.error;
257}
258
259bool QIMPenCharMatch::operator<=( const QIMPenCharMatch &m )
260{
261 return error <= m.error;
262}
263
264//===========================================================================
265
266/*!
267 \class QIMPenCharSet qimpenchar.h
268
269 Maintains a set of related characters.
270*/
271
272QIMPenCharSet::QIMPenCharSet()
273{
274 chars.setAutoDelete( TRUE );
275 desc = "Unnamed";
276 csTitle = "abc";
277 csType = Unknown;
278 maxStrokes = 0;
279}
280
281/*!
282 Construct and load a characters set from file \a fn.
283*/
284QIMPenCharSet::QIMPenCharSet( const QString &fn )
285{
286 chars.setAutoDelete( TRUE );
287 desc = "Unnamed";
288 csTitle = "abc";
289 csType = Unknown;
290 maxStrokes = 0;
291 load( fn, System );
292}
293
294const QString &QIMPenCharSet::filename( Domain d ) const
295{
296 if ( d == System )
297 return sysFilename;
298 else
299 return userFilename;
300}
301
302void QIMPenCharSet::setFilename( const QString &fn, Domain d )
303{
304 if ( d == System )
305 sysFilename = fn;
306 else if ( d == User )
307 userFilename = fn;
308}
309
310/*!
311 Load a character set from file \a fn.
312*/
313bool QIMPenCharSet::load( const QString &fn, Domain d )
314{
315 setFilename( fn, d );
316
317 bool ok = FALSE;
318 QFile file( fn );
319 if ( file.open( IO_ReadOnly ) ) {
320 QDataStream ds( &file );
321 QString version;
322 ds >> version;
323 ds >> csTitle;
324 ds >> desc;
325 int major = version.mid( 4, 1 ).toInt();
326 int minor = version.mid( 6 ).toInt();
327 if ( major >= 1 && minor > 0 ) {
328 ds >> (Q_INT8 &)csType;
329 } else {
330 if ( csTitle == "abc" )
331 csType = Lower;
332 else if ( csTitle == "ABC" )
333 csType = Upper;
334 else if ( csTitle == "123" )
335 csType = Numeric;
336 else if ( fn == "Combining" )
337 csType = Combining;
338 }
339 while ( !ds.atEnd() ) {
340 QIMPenChar *pc = new QIMPenChar;
341 ds >> *pc;
342 if ( d == User )
343 markDeleted( pc->character() ); // override system
344 addChar( pc );
345 }
346 if ( file.status() == IO_Ok )
347 ok = TRUE;
348 }
349
350 return ok;
351}
352
353/*!
354 Save this character set.
355*/
356bool QIMPenCharSet::save( Domain d )
357{
358 if ( filename( d ).isEmpty() )
359 return FALSE;
360
361 bool ok = FALSE;
362
363 QString fn = filename( d );
364 QString tmpFn = fn + ".new";
365 QFile file( tmpFn );
366 if ( file.open( IO_WriteOnly|IO_Raw ) ) {
367 QDataStream ds( &file );
368 ds << QString( "QPT 1.1" );
369 ds << csTitle;
370 ds << desc;
371 ds << (Q_INT8)csType;
372 QIMPenCharIterator ci( chars );
373 for ( ; ci.current(); ++ci ) {
374 QIMPenChar *pc = ci.current();
375 if ( ( (d == System) && pc->testFlag( QIMPenChar::System ) ) ||
376 ( (d == User) && !pc->testFlag( QIMPenChar::System ) ) ) {
377 ds << *pc;
378 }
379 if ( file.status() != IO_Ok )
380 break;
381 }
382 if ( file.status() == IO_Ok )
383 ok = TRUE;
384 }
385
386 if ( ok ) {
387 if ( ::rename( tmpFn.latin1(), fn.latin1() ) < 0 ) {
388 qWarning( "problem renaming file %s to %s, errno: %d",
389 tmpFn.latin1(), fn.latin1(), errno );
390 // remove the tmp file, otherwise, it will just lay around...
391 QFile::remove( tmpFn.latin1() );
392 ok = FALSE;
393 }
394 }
395
396 return ok;
397}
398
399QIMPenChar *QIMPenCharSet::at( int i )
400{
401 return chars.at(i);
402}
403
404void QIMPenCharSet::markDeleted( uint ch )
405{
406 QIMPenCharIterator ci( chars );
407 for ( ; ci.current(); ++ci ) {
408 QIMPenChar *pc = ci.current();
409 if ( pc->character() == ch && pc->testFlag( QIMPenChar::System ) )
410 pc->setFlag( QIMPenChar::Deleted );
411 }
412}
413
414/*!
415 Find the best matches for \a ch in this character set.
416*/
417QIMPenCharMatchList QIMPenCharSet::match( QIMPenChar *ch )
418{
419 QIMPenCharMatchList matches;
420
421 QIMPenCharIterator ci( chars );
422 for ( ; ci.current(); ++ci ) {
423 QIMPenChar *tmplChar = ci.current();
424 if ( tmplChar->testFlag( QIMPenChar::Deleted ) ) {
425 continue;
426 }
427 int err;
428 if ( ch->penStrokes().count() <= tmplChar->penStrokes().count() ) {
429 err = ch->match( tmplChar );
430 if ( err <= QIMPEN_MATCH_THRESHOLD ) {
431 if (tmplChar->penStrokes().count() != ch->penStrokes().count())
432 err = QIMPEN_MATCH_THRESHOLD;
433 QIMPenCharMatchList::Iterator it;
434 for ( it = matches.begin(); it != matches.end(); ++it ) {
435 if ( (*it).penChar->character() == tmplChar->character() &&
436 (*it).penChar->penStrokes().count() == tmplChar->penStrokes().count() ) {
437 if ( (*it).error > err )
438 (*it).error = err;
439 break;
440 }
441 }
442 if ( it == matches.end() ) {
443 QIMPenCharMatch m;
444 m.error = err;
445 m.penChar = tmplChar;
446 matches.append( m );
447 }
448 }
449 }
450 }
451 qHeapSort( matches );
452/*
453 QIMPenCharMatchList::Iterator it;
454 for ( it = matches.begin(); it != matches.end(); ++it ) {
455 qDebug( "Match: \'%c\', error %d, strokes %d", (*it).penChar->character(),
456 (*it).error, (*it).penChar->penStrokes().count() );
457 }
458*/
459 return matches;
460}
461
462/*!
463 Add a character \a ch to this set.
464 QIMPenCharSet will delete this character when it is no longer needed.
465*/
466void QIMPenCharSet::addChar( QIMPenChar *ch )
467{
468 if ( ch->penStrokes().count() > maxStrokes )
469 maxStrokes = ch->penStrokes().count();
470 chars.append( ch );
471}
472
473/*!
474 Remove a character by reference \a ch from this set.
475 QIMPenCharSet will delete this character.
476*/
477void QIMPenCharSet::removeChar( QIMPenChar *ch )
478{
479 chars.remove( ch );
480}
481
482/*!
483 Move the character up the list of characters.
484*/
485void QIMPenCharSet::up( QIMPenChar *ch )
486{
487 int idx = chars.findRef( ch );
488 if ( idx > 0 ) {
489 chars.take();
490 chars.insert( idx - 1, ch );
491 }
492}
493
494/*!
495 Move the character down the list of characters.
496*/
497void QIMPenCharSet::down( QIMPenChar *ch )
498{
499 int idx = chars.findRef( ch );
500 if ( idx >= 0 && idx < (int)chars.count() - 1 ) {
501 chars.take();
502 chars.insert( idx + 1, ch );
503 }
504}
505
diff --git a/inputmethods/handwriting/qimpenchar.h b/inputmethods/handwriting/qimpenchar.h
new file mode 100644
index 0000000..9a5f687
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenchar.h
@@ -0,0 +1,157 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#ifndef QIMPENCHAR_H_
22#define QIMPENCHAR_H_
23
24#include <qlist.h>
25#include <qvaluelist.h>
26#include <qcstring.h>
27#include "qimpenstroke.h"
28
29struct QIMPenSpecialKeys {
30 int code;
31 char *name;
32};
33
34extern const QIMPenSpecialKeys qimpen_specialKeys[];
35
36
37class QIMPenChar
38{
39public:
40 QIMPenChar();
41 QIMPenChar( const QIMPenChar & );
42
43 unsigned int character() const { return ch; }
44 void setCharacter( unsigned int c ) { ch = c; }
45
46 const QString &data() const { return d; }
47 void setData( const QString &ba ) { d = ba; }
48
49 QString name() const;
50 bool isEmpty() const { return strokes.isEmpty(); }
51 unsigned int strokeCount() const { return strokes.count(); }
52 unsigned int strokeLength( int s ) const;
53 void clear();
54 int match( QIMPenChar *ch );
55 const QIMPenStrokeList &penStrokes() { return strokes; }
56 QPoint startingPoint() const { return strokes.getFirst()->startingPoint(); }
57 QRect boundingRect();
58
59 void setFlag( int f ) { flags |= f; }
60 void clearFlag( int f ) { flags &= ~f; }
61 bool testFlag( int f ) { return flags & f; }
62
63 enum Flags { System=0x01, Deleted=0x02, CombineRight=0x04, Data=0x08 };
64 // Correspond to codes in template files. Do not change values.
65 enum Mode { ModeBase=0x4000, Caps=0x4001, Shortcut=0x4002, CapsLock=0x4003,
66 Punctuation=0x4004, Symbol=0x4005, Extended=0x4006 };
67
68 QIMPenChar &operator=( const QIMPenChar &s );
69
70 void addStroke( QIMPenStroke * );
71
72protected:
73 unsigned int ch;
74 QString d;
75 Q_UINT8 flags;
76 QIMPenStrokeList strokes;
77
78 friend QDataStream &operator<< (QDataStream &, const QIMPenChar &);
79 friend QDataStream &operator>> (QDataStream &, QIMPenChar &);
80};
81
82typedef QList<QIMPenChar> QIMPenCharList;
83typedef QListIterator<QIMPenChar> QIMPenCharIterator;
84
85QDataStream & operator<< (QDataStream & s, const QIMPenChar &ws);
86QDataStream & operator>> (QDataStream & s, QIMPenChar &ws);
87
88struct QIMPenCharMatch
89{
90 int error;
91 QIMPenChar *penChar;
92
93 bool operator>( const QIMPenCharMatch &m );
94 bool operator<( const QIMPenCharMatch &m );
95 bool operator<=( const QIMPenCharMatch &m );
96};
97
98typedef QValueList<QIMPenCharMatch> QIMPenCharMatchList;
99
100
101class QIMPenCharSet
102{
103public:
104 QIMPenCharSet();
105 QIMPenCharSet( const QString &fn );
106
107 bool isEmpty() const { return chars.isEmpty(); }
108 unsigned int count() const { return chars.count(); }
109 void clear() { chars.clear(); }
110
111 void setDescription( const QString &d ) { desc = d; }
112 QString description() const { return desc; }
113 void setTitle( const QString &t ) { csTitle = t; }
114 QString title() const { return csTitle; }
115
116 QIMPenCharMatchList match( QIMPenChar *ch );
117 void addChar( QIMPenChar *ch );
118 void removeChar( QIMPenChar *ch );
119 QIMPenChar *at( int i );
120
121 unsigned maximumStrokes() const { return maxStrokes; }
122
123 void up( QIMPenChar *ch );
124 void down( QIMPenChar *ch );
125
126 enum Domain { System, User };
127 enum Type { Unknown=0x00, Lower=0x01, Upper=0x02, Combining=0x04,
128 Numeric=0x08, Punctuation=0x10, Symbol=0x20, Shortcut=0x40 };
129
130 const QIMPenCharList &characters() const { return chars; }
131
132 void setType( Type t ) { csType = t; }
133 Type type() const { return csType; }
134
135 const QString &filename( Domain d ) const;
136 void setFilename( const QString &fn, Domain d=System );
137 bool load( const QString &fn, Domain d=System );
138 bool save( Domain d=System );
139
140protected:
141 void markDeleted( uint ch );
142
143protected:
144 QString csTitle;
145 QString desc;
146 QString sysFilename;
147 QString userFilename;
148 Type csType;
149 unsigned maxStrokes;
150 QIMPenCharList chars;
151 QIMPenCharMatchList matches;
152};
153
154typedef QList<QIMPenCharSet> QIMPenCharSetList;
155typedef QListIterator<QIMPenCharSet> QIMPenCharSetIterator;
156
157#endif
diff --git a/inputmethods/handwriting/qimpencombining.cpp b/inputmethods/handwriting/qimpencombining.cpp
new file mode 100644
index 0000000..30459e7
--- a/dev/null
+++ b/inputmethods/handwriting/qimpencombining.cpp
@@ -0,0 +1,141 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include <qfile.h>
22#include <qtl.h>
23#include <math.h>
24#include <limits.h>
25#include <qdatastream.h>
26#include "qimpencombining.h"
27
28static unsigned int combiningSymbols[] = { '\\', '/', '^', '~', '\"', 'o' };
29static unsigned int combiningChars[][7] = {
30 // \ / ^ ~ "
31 { 'A', 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5 },
32 { 'O', 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0000 },
33 { 'U', 0x00D9, 0x00DA, 0x00DB, 0x0000, 0x00DC, 0x0000 },
34 { 'E', 0x00C8, 0x00C9, 0x00CA, 0x0000, 0x00CB, 0x0000 },
35 { 'I', 0x00CC, 0x00CD, 0x00CE, 0x0000, 0x00CF, 0x0000 },
36 { 'a', 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5 },
37 { 'e', 0x00E8, 0x00E9, 0x00EA, 0x0000, 0x00EB, 0x0000 },
38 { 'i', 0x00EC, 0x00ED, 0x00EE, 0x0000, 0x00EF, 0x0000 },
39 { 'n', 0x0000, 0x0000, 0x0000, 0x00F1, 0x0000, 0x0000 },
40 { 'o', 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0000 },
41 { 'u', 0x00F9, 0x00FA, 0x00FB, 0x0000, 0x00FC, 0x0000 },
42 { 'y', 0x0000, 0x00FD, 0x0000, 0x0000, 0x00FF, 0x0000 },
43 { 0, 0, 0, 0, 0, 0, 0 }
44};
45
46
47QIMPenCombining::QIMPenCombining()
48{
49}
50
51QIMPenCombining::QIMPenCombining( const QString &fn )
52 : QIMPenCharSet( fn )
53{
54}
55
56void QIMPenCombining::addCombined( QIMPenCharSet *cs )
57{
58 unsigned int count = cs->count();
59 QIMPenCharIterator it( cs->characters() );
60 for ( ; it.current() && count; ++it, --count ) {
61 QIMPenChar *pc = it.current();
62 if ( pc->testFlag( QIMPenChar::Deleted ) )
63 continue;
64 int charIdx = findCombining( pc->character() );
65 if ( charIdx < 0 )
66 continue;
67 for ( int i = 0; i < 6; i++ ) {
68 if ( combiningChars[charIdx][i+1] ) {
69 QIMPenCharIterator cit( chars );
70 for ( ; cit.current(); ++cit ) {
71 QIMPenChar *accentPc = cit.current();
72 if ( accentPc->character() == combiningSymbols[i] ) {
73 QIMPenChar *combined = combine( pc, accentPc );
74 combined->setCharacter( combiningChars[charIdx][i+1] );
75 cs->addChar( combined );
76 }
77 }
78 }
79 }
80 }
81}
82
83int QIMPenCombining::findCombining( unsigned int ch ) const
84{
85 int i = 0;
86 while ( combiningChars[i][0] ) {
87 if ( combiningChars[i][0] == ch )
88 return i;
89 i++;
90 }
91
92 return -1;
93}
94
95QIMPenChar *QIMPenCombining::combine( QIMPenChar *base, QIMPenChar *accent )
96{
97 QRect brect = base->boundingRect();
98 QRect arect = accent->boundingRect();
99 int offset;
100 if ( accent->testFlag( QIMPenChar::CombineRight ) )
101 offset = brect.left() - arect.left() + brect.width() + 2;
102 else
103 offset = brect.left() - arect.left() + (brect.width() - arect.width())/2;
104 QIMPenChar *combined = 0;
105 if ( base->character() == 'i' ) {
106 // Hack to remove the dot from i's when combining.
107 if ( base->penStrokes().count() > 1 ) {
108 combined = new QIMPenChar;
109 QIMPenStrokeIterator it( base->penStrokes() );
110 for ( unsigned int i = 0; i < base->penStrokes().count()-1; ++it, i++ ) {
111 QIMPenStroke *st = new QIMPenStroke( *(it.current()) );
112 combined->addStroke( st );
113 }
114 combined->setFlag( QIMPenChar::System );
115 }
116 }
117 if ( !combined )
118 combined = new QIMPenChar( *base );
119 QIMPenStrokeIterator it( accent->penStrokes() );
120 for ( ; it.current(); ++it ) {
121 QIMPenStroke *st = new QIMPenStroke( *(it.current()) );
122 st->setStartingPoint( st->startingPoint() + QPoint(offset, 0 ));
123 combined->addStroke( st );
124 delete st;
125 }
126
127 return combined;
128}
129
130QIMPenChar *QIMPenCombining::penChar( int type )
131{
132 QIMPenCharIterator it( chars );
133 for ( ; it.current(); ++it ) {
134 QIMPenChar *pc = it.current();
135 if ( pc->character() == combiningSymbols[type] )
136 return pc;
137 }
138
139 return 0;
140}
141
diff --git a/inputmethods/handwriting/qimpencombining.h b/inputmethods/handwriting/qimpencombining.h
new file mode 100644
index 0000000..778cb8f
--- a/dev/null
+++ b/inputmethods/handwriting/qimpencombining.h
@@ -0,0 +1,41 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#ifndef QIMPENCOMBINING_H_
22#define QIMPENCOMBINING_H_
23
24#include <qlist.h>
25#include "qimpenchar.h"
26
27class QIMPenCombining : public QIMPenCharSet
28{
29public:
30 QIMPenCombining();
31 QIMPenCombining( const QString &fn );
32
33 void addCombined( QIMPenCharSet * );
34
35protected:
36 int findCombining( unsigned int ch ) const;
37 QIMPenChar *combine( QIMPenChar *base, QIMPenChar *accent );
38 QIMPenChar *penChar( int type );
39};
40
41#endif
diff --git a/inputmethods/handwriting/qimpenhelp.cpp b/inputmethods/handwriting/qimpenhelp.cpp
new file mode 100644
index 0000000..5ee46a2
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenhelp.cpp
@@ -0,0 +1,410 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "qimpenwidget.h"
22#include "qimpencombining.h"
23#include "qimpenmatch.h"
24#include "qimpenhelp.h"
25
26#include <qpe/qpeapplication.h>
27#include <qpe/global.h>
28#include <qpe/config.h>
29#include <qpe/stringutil.h>
30
31#include <qtextview.h>
32#include <qlabel.h>
33#include <qlistbox.h>
34#include <qcombobox.h>
35#include <qpushbutton.h>
36#include <qlayout.h>
37#include <qtimer.h>
38#include <qtextstream.h>
39
40/* XPM */
41static const char * const left_xpm[] = {
42"16 16 2 1",
43" c None",
44". c #000000",
45" ",
46" ",
47" ",
48" . ",
49" .. ",
50" ... ",
51" .... ",
52" ..... ",
53" ...... ",
54" ..... ",
55" .... ",
56" ... ",
57" .. ",
58" . ",
59" ",
60" "};
61
62
63/* XPM */
64static const char * const right_xpm[] = {
65"16 16 2 1",
66" c None",
67". c #000000",
68" ",
69" ",
70" ",
71" . ",
72" .. ",
73" ... ",
74" .... ",
75" ..... ",
76" ...... ",
77" ..... ",
78" .... ",
79" ... ",
80" .. ",
81" . ",
82" ",
83" "};
84
85class CharListItem : public QListBoxText
86{
87public:
88 CharListItem( const QString &text, uint c )
89 : QListBoxText( text )
90 {
91 _code = c;
92 }
93
94 uint code() const { return _code; }
95
96protected:
97 uint _code;
98};
99
100HandwritingHelp::HandwritingHelp( QIMPenProfile *p, QWidget *parent, const char *name, WFlags f )
101 : QTabWidget( parent, name, f )
102{
103 setCaption( tr("Handwriting Help") );
104 QTextView *help = new QTextView( this );
105 help->setFrameStyle( QFrame::NoFrame );
106 help->setText(
107 tr( "<ul><li>When you start to use the handwriting recogniser "
108 "write slowly, accurately and firmly."
109 "<li>Use the guide lines when drawing your characters."
110 "<li>When drawing a character with multiple strokes, each "
111 "successive stroke must be drawn before the grayed strokes are erased."
112 "<li>Practice your handwriting using the handwriting trainer."
113 "<li>When adding your own character templates make sure they "
114 "are sufficiently different from other characters' templates."
115 "</ul>") );
116
117 addTab( help, tr("Tips") );
118
119 HandwritingTrainer *trainer = new HandwritingTrainer( p, this );
120 addTab( trainer, tr("Trainer") );
121}
122
123void HandwritingHelp::showEvent( QShowEvent * )
124{
125 Global::hideInputMethod();
126}
127
128void HandwritingHelp::hideEvent( QHideEvent * )
129{
130 Global::showInputMethod();
131}
132
133//---------------------------------------------------------------------------
134
135HandwritingTrainer::HandwritingTrainer( QIMPenProfile *p, QWidget *parent, const char *name )
136 : QWidget( parent, name ), profile(p)
137{
138 QGridLayout *gl = new QGridLayout( this, 5, 2, 0, 4 );
139 gl->setRowStretch( 1, 1 );
140 gl->setRowStretch( 2, 1 );
141 gl->setColStretch( 1, 1 );
142
143 charSetCombo = new QComboBox( this );
144 gl->addMultiCellWidget( charSetCombo, 0, 0, 0, 1 );
145 connect( charSetCombo, SIGNAL(activated(int)), SLOT(selectCharSet(int)));
146 QIMPenCharSetIterator it( profile->charSets() );
147 for ( ; it.current(); ++it ) {
148 charSetCombo->insertItem( it.current()->description() );
149 }
150
151 charList = new QListBox( this );
152 charList->setHScrollBarMode( QListBox::AlwaysOff );
153 charList->setFixedWidth( 80 );
154 connect( charList, SIGNAL(highlighted(int)), this, SLOT(selectChar(int)) );
155 gl->addMultiCellWidget( charList, 1, 2, 0, 0 );
156
157 QLabel *help = new QLabel( this );
158 help->setAlignment( AlignLeft | AlignVCenter | WordBreak );
159 gl->addWidget( help, 1, 1 );
160 help->setText(
161 tr( "Select a character from the list. The writing area on the left "
162 "shows the reference character. Practice writing in the area on "
163 "the right.") );
164
165 result = new QLabel( this );
166 gl->addMultiCellWidget( result, 2, 3, 1, 1 );
167
168 matcher = new QIMPenMatch( this );
169 matcher->setCharSet( currentSet );
170 connect( matcher, SIGNAL(noMatch()), this, SLOT(noMatch()) );
171 connect( matcher, SIGNAL(matchedCharacters(const QIMPenCharMatchList &)),
172 this, SLOT(matched(const QIMPenCharMatchList &)) );
173
174 QHBoxLayout *hb = new QHBoxLayout();
175 gl->addLayout( hb, 3, 0 );
176 prevBtn = new QPushButton( this );
177 prevBtn->setPixmap( QPixmap( (const char **)left_xpm ) );
178 connect( prevBtn, SIGNAL(clicked()), SLOT(prevChar()));
179 hb->addWidget( prevBtn );
180
181 nextBtn = new QPushButton( this );
182 nextBtn->setPixmap( QPixmap( (const char **)right_xpm ) );
183 connect( nextBtn, SIGNAL(clicked()), SLOT(nextChar()));
184 hb->addWidget( nextBtn );
185
186 refPw = new QIMPenWidget( this );
187 refPw->setReadOnly( TRUE );
188 gl->addWidget( refPw, 4, 0 );
189
190 pracPw = new QIMPenWidget( this );
191 connect( matcher, SIGNAL(removeStroke()), pracPw, SLOT(removeStroke()) );
192 connect( pracPw, SIGNAL(beginStroke()),
193 this, SLOT(beginStroke()) );
194 connect( pracPw, SIGNAL(stroke( QIMPenStroke * )),
195 this, SLOT(strokeEntered( QIMPenStroke * )) );
196 connect( pracPw, SIGNAL(beginStroke()),
197 matcher, SLOT(beginStroke()) );
198 connect( pracPw, SIGNAL(stroke( QIMPenStroke * )),
199 matcher, SLOT(strokeEntered( QIMPenStroke * )) );
200 gl->addWidget( pracPw, 4, 1 );
201
202 redrawTimer = new QTimer( this );
203 connect( redrawTimer, SIGNAL(timeout()), this, SLOT(redrawChar()) );
204 redrawTimer->start( 5000 );
205
206 currentSet = 0;
207 charSetCombo->setCurrentItem( 1 );
208 selectCharSet( 1 );
209}
210
211HandwritingTrainer::~HandwritingTrainer()
212{
213}
214
215void HandwritingTrainer::showEvent( QShowEvent * )
216{
217 redrawChar();
218 redrawTimer->start( 5000 );
219}
220
221void HandwritingTrainer::setCurrentChar( QIMPenChar *c )
222{
223 currentChar = c;
224 refPw->showCharacter( currentChar );
225 pracPw->clear();
226 if ( currentChar ) {
227 prevBtn->setEnabled( findPrev() != 0 );
228 nextBtn->setEnabled( findNext() != 0 );
229 }
230 result->setText( "" );
231 redrawTimer->start( 5000 );
232}
233
234void HandwritingTrainer::selectChar( int i )
235{
236 currentChar = 0;
237 currentCode = ((CharListItem *)charList->item(i))->code();
238 QIMPenCharIterator it(currentSet->characters() );
239 for ( ; it.current(); ++it ) {
240 if ( it.current()->character() == currentCode &&
241 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
242 setCurrentChar( it.current() );
243 break;
244 }
245 }
246 if ( !it.current() )
247 setCurrentChar( 0 );
248}
249
250void HandwritingTrainer::selectCharSet( int i )
251{
252 if ( currentSet ) {
253 refPw->removeCharSet( 0 );
254 pracPw->removeCharSet( 0 );
255 }
256 currentSet = profile->charSets().at( i );
257 fillCharList();
258 refPw->insertCharSet( currentSet );
259 pracPw->insertCharSet( currentSet );
260 matcher->setCharSet( currentSet );
261 if ( charList->count() ) {
262 charList->setSelected( 0, TRUE );
263 selectChar(0);
264 }
265}
266
267void HandwritingTrainer::noMatch()
268{
269 result->setText( "No match" );
270}
271
272void HandwritingTrainer::matched( const QIMPenCharMatchList &ml )
273{
274 int maxErr = 20000 + (*ml.begin()).penChar->strokeLength(0) * 1000;
275 int baseErr = (*ml.begin()).penChar->strokeLength(0) * 250;
276 unsigned int numStrokes = (*ml.begin()).penChar->strokeCount();
277 QIMPenCharMatchList::ConstIterator it;
278 /*
279 for ( it = ml.begin(); it != ml.end(); ++it ) {
280 if ( (*it).penChar->strokeCount() == numStrokes ) {
281 if ( (*it).error > maxErr )
282 maxErr = (*it).error;
283 }
284 }
285 */
286 int i;
287 QString res;
288 QTextStream ts(&res, IO_WriteOnly);
289 ts << "<qt>" << tr("Matched: ");
290 for ( i = 0, it = ml.begin(); it != ml.end() && i < 4; ++it, i++ ) {
291 if ( (*it).penChar->strokeCount() == numStrokes ) {
292 int rate = 100 - ( ((*it).error - baseErr) * 100 ) / maxErr;
293 if ( it != ml.begin() ) {
294 if ( rate < -10 )
295 continue;
296 ts << "<br>";
297 ts << tr("Similar to: ");
298 }
299 ts << "<big>";
300 if ( (*it).penChar->character() == currentChar->character() )
301 ts << "<b>";
302 ts << Qtopia::escapeString((*it).penChar->name());
303 ts << " (" << rateString(rate) << ")";
304 if ( (*it).penChar->character() == currentChar->character() )
305 ts << "</b>";
306 ts << "</big>";
307 }
308 }
309 ts << "</qt>";
310 result->setText( res );
311}
312
313QString HandwritingTrainer::rateString( int rate ) const
314{
315 if ( rate < 1 )
316 rate = 1;
317 if ( rate > 100 )
318 rate = 100;
319 return tr("%1%").arg(rate);
320}
321
322void HandwritingTrainer::prevChar()
323{
324 QIMPenChar *pc = findPrev();
325 if ( pc )
326 setCurrentChar( pc );
327}
328
329void HandwritingTrainer::nextChar()
330{
331 QIMPenChar *pc = findNext();
332 if ( pc )
333 setCurrentChar( pc );
334}
335
336void HandwritingTrainer::redrawChar()
337{
338 if ( currentChar )
339 refPw->showCharacter( currentChar );
340}
341
342void HandwritingTrainer::beginStroke()
343{
344 redrawTimer->start( 5000 );
345}
346
347void HandwritingTrainer::strokeEntered( QIMPenStroke * )
348{
349 pracPw->greyStroke();
350}
351
352QIMPenChar *HandwritingTrainer::findPrev()
353{
354 if ( !currentChar )
355 return 0;
356 QIMPenCharIterator it( currentSet->characters() );
357 bool found = FALSE;
358 for ( it.toLast(); it.current(); --it ) {
359 if ( !found && it.current() == currentChar )
360 found = TRUE;
361 else if ( found && it.current()->character() == currentCode &&
362 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
363 return it.current();
364 }
365 }
366
367 return 0;
368}
369
370QIMPenChar *HandwritingTrainer::findNext()
371{
372 if ( !currentChar )
373 return 0;
374 QIMPenCharIterator it( currentSet->characters() );
375 bool found = FALSE;
376 for ( ; it.current(); ++it ) {
377 if ( !found && it.current() == currentChar )
378 found = TRUE;
379 else if ( found && it.current()->character() == currentCode &&
380 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
381 return it.current();
382 }
383 }
384
385 return 0;
386}
387
388void HandwritingTrainer::fillCharList()
389{
390 charList->clear();
391 QIMPenCharIterator it( currentSet->characters() );
392 CharListItem *li = 0;
393 for ( ; it.current(); ++it ) {
394 uint ch = it.current()->character();
395 QString n = it.current()->name();
396 if ( !n.isEmpty() )
397 li = new CharListItem( n, ch );
398 if ( li ) {
399 CharListItem *i = (CharListItem *)charList->findItem( li->text() );
400 if ( !i || i->code() != ch ) {
401 charList->insertItem( li );
402 } else {
403 delete li;
404 li = 0;
405 }
406 }
407 }
408 currentChar = 0;
409}
410
diff --git a/inputmethods/handwriting/qimpenhelp.h b/inputmethods/handwriting/qimpenhelp.h
new file mode 100644
index 0000000..07cb035
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenhelp.h
@@ -0,0 +1,85 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#include <qtabwidget.h>
21#include <qlist.h>
22#include "qimpenchar.h"
23#include "qimpenprofile.h"
24
25class QListBox;
26class QLabel;
27class QComboBox;
28class QPushButton;
29class QTimer;
30class QIMPenWidget;
31class QIMPenMatch;
32
33class HandwritingHelp : public QTabWidget
34{
35 Q_OBJECT
36public:
37 HandwritingHelp( QIMPenProfile *p, QWidget *parent=0, const char *name=0, WFlags f=0 );
38
39protected:
40 virtual void showEvent( QShowEvent * );
41 virtual void hideEvent( QHideEvent * );
42};
43
44class HandwritingTrainer : public QWidget
45{
46 Q_OBJECT
47public:
48 HandwritingTrainer( QIMPenProfile *p, QWidget *parent=0, const char *name=0 );
49 ~HandwritingTrainer();
50
51private slots:
52 void selectChar( int );
53 void selectCharSet( int );
54 void noMatch();
55 void matched( const QIMPenCharMatchList &ml );
56 void prevChar();
57 void nextChar();
58 void redrawChar();
59 void beginStroke();
60 void strokeEntered( QIMPenStroke * );
61
62private:
63 virtual void showEvent( QShowEvent * );
64 QString rateString( int rate ) const;
65 void setCurrentChar( QIMPenChar *c );
66 void fillCharList();
67 QIMPenChar *findPrev();
68 QIMPenChar *findNext();
69
70private:
71 QIMPenMatch *matcher;
72 QIMPenCharSet *currentSet;
73 QIMPenChar *currentChar;
74 QIMPenProfile *profile;
75 uint currentCode;
76 QIMPenWidget *refPw;
77 QIMPenWidget *pracPw;
78 QComboBox *charSetCombo;
79 QListBox *charList;
80 QLabel *result;
81 QPushButton *prevBtn;
82 QPushButton *nextBtn;
83 QTimer *redrawTimer;
84};
85
diff --git a/inputmethods/handwriting/qimpeninput.cpp b/inputmethods/handwriting/qimpeninput.cpp
new file mode 100644
index 0000000..6718b26
--- a/dev/null
+++ b/inputmethods/handwriting/qimpeninput.cpp
@@ -0,0 +1,515 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "qimpenwidget.h"
22#include "qimpensetup.h"
23#include "qimpeninput.h"
24#include "qimpencombining.h"
25#include "qimpenwordpick.h"
26#include "qimpenmatch.h"
27#include "qimpenhelp.h"
28
29#include <qpe/qpeapplication.h>
30#include <qpe/qdawg.h>
31#include <qpe/config.h>
32#include <qpe/global.h>
33
34#include <qlayout.h>
35#include <qpushbutton.h>
36#include <qlabel.h>
37#include <qtimer.h>
38#include <qdir.h>
39
40#include <limits.h>
41
42// We'll use little pixmaps for the buttons to save screen space.
43
44/* XPM */
45static const char * const pen_xpm[] = {
46"12 12 4 1",
47 " c None",
48 ".c #000000",
49 "+c #FFFFFF",
50 "@c #808080",
51" . ",
52" .+. ",
53" ..@@.",
54" .+@.. ",
55" .+@@. ",
56" .+@@. ",
57" .+@@. ",
58" .@.@. ",
59" .@@. ",
60" .... ",
61" .. ",
62" "};
63
64
65/* XPM */
66static char * bs_xpm[] = {
67"12 12 5 1",
68 " c None",
69 ".c #333333",
70 "+c #000000",
71 "@c #FFFFFF",
72 "#c #666666",
73" ",
74" ",
75" ",
76" . ",
77" ++ ",
78" +@#+++++. ",
79" +@@@@@@@@+ ",
80" +@#+++++. ",
81" ++ ",
82" . ",
83" ",
84" "};
85
86
87/* XPM */
88static char * enter_xpm[] = {
89"12 12 5 1",
90 " c None",
91 ".c #333333",
92 "+c #000000",
93 "@c #FFFFFF",
94 "#c #666666",
95" ",
96" .+. ",
97" +@+ ",
98" . +@+ ",
99" ++ +@+ ",
100" +@#++++@+ ",
101" +@@@@@@@@+ ",
102" +@#+++++. ",
103" ++ ",
104" . ",
105" ",
106" "};
107
108
109
110/* XPM */
111static char * help_xpm[] = {
112"12 12 5 1",
113 " c None",
114 ".c #000000",
115 "+c #FFFFFF",
116 "@c #666666",
117 "#c #333333",
118" ",
119" ... ",
120" .+++. ",
121" .+..@+. ",
122" #.# .+. ",
123" .+. ",
124" .+. ",
125" .+. ",
126" .+. ",
127" #.# ",
128" .+. ",
129" #.# "};
130
131
132/*!
133 \class QIMPenInput qimpeninput.h
134
135 Pen input widget.
136*/
137QIMPenInput::QIMPenInput( QWidget *parent, const char *name, WFlags f )
138 : QFrame( parent, name, f ), helpDlg(0), profile(0)
139{
140 setFrameStyle( Box | Plain );
141
142 profileList.setAutoDelete( true );
143
144 matcher = new QIMPenMatch( this );
145 connect( matcher, SIGNAL(keypress(uint)), this, SLOT(keypress(uint)) );
146 connect( matcher, SIGNAL(erase()), this, SLOT(erase()) );
147
148 QGridLayout *gl = new QGridLayout( this, 5, 2, 1, 0 );
149 gl->setColStretch( 0, 1 );
150
151 wordPicker = new QIMPenWordPick( this );
152 connect( wordPicker, SIGNAL(wordClicked(const QString &)),
153 this, SLOT(wordPicked(const QString &)) );
154 connect( matcher, SIGNAL(matchedCharacters(const QIMPenCharMatchList &)),
155 this, SLOT(matchedCharacters(const QIMPenCharMatchList &)) );
156 connect( matcher, SIGNAL(matchedWords(const QIMPenMatch::MatchWordList&)),
157 wordPicker, SLOT(setWords(const QIMPenMatch::MatchWordList&)) );
158 QFont f("smallsmooth",9);
159 QFontInfo fi( f );
160 wordPicker->setFont( f );
161 wordPicker->setBackgroundColor( white );
162 gl->addMultiCellWidget( wordPicker, 0, 0, 0, 1 );
163 if ( !Global::fixedDawg().root() || !matcher->isWordMatchingEnabled() )
164 wordPicker->hide();
165
166 pw = new QIMPenWidget( this );
167 gl->addMultiCellWidget( pw, 1, 4, 0, 0 );
168
169 int bh = pw->sizeHint().height()/4;
170
171 QPushButton *b = new QPushButton( this );
172 b->setFocusPolicy( NoFocus );
173 b->setPixmap( QPixmap( (const char **)bs_xpm ) );
174 b->setFixedHeight(pw->sizeHint().height()-3*bh); // left-over space goes here
175 b->setAutoRepeat( TRUE );
176 gl->addWidget( b, 1, 1 );
177 connect( b, SIGNAL(clicked()), SLOT(backspace()));
178
179 b = new QPushButton( this );
180 b->setFocusPolicy( NoFocus );
181 b->setPixmap( QPixmap( (const char **)enter_xpm ) );
182 b->setFixedHeight(bh);
183 b->setAutoRepeat( TRUE );
184 gl->addWidget( b, 2, 1 );
185 connect( b, SIGNAL(clicked()), SLOT(enter()));
186
187 helpBtn = new QPushButton( this );
188 helpBtn->setFocusPolicy( NoFocus );
189 helpBtn->setPixmap( QPixmap( (const char **)help_xpm ) );
190 helpBtn->setFixedHeight(bh);
191 gl->addWidget( helpBtn, 3, 1 );
192 connect( helpBtn, SIGNAL(clicked()), SLOT(help()));
193
194 QPixmap pm( (const char **)pen_xpm );
195 setupBtn = new QPushButton( this );
196 setupBtn->setFocusPolicy( NoFocus );
197 setupBtn->setPixmap( pm );
198 setupBtn->setFixedHeight(bh);
199 gl->addWidget( setupBtn, 4, 1 );
200 connect( setupBtn, SIGNAL(clicked()), SLOT(setup()));
201
202 connect( matcher, SIGNAL(removeStroke()), pw, SLOT(removeStroke()) );
203 connect( pw, SIGNAL(changeCharSet( QIMPenCharSet * )),
204 matcher, SLOT(setCharSet( QIMPenCharSet * )) );
205 connect( pw, SIGNAL(changeCharSet( int )),
206 this, SLOT(selectCharSet( int )) );
207 connect( pw, SIGNAL(beginStroke()),
208 matcher, SLOT(beginStroke()) );
209 connect( pw, SIGNAL(stroke( QIMPenStroke * )),
210 this, SLOT(strokeEntered( QIMPenStroke * )) );
211 connect( pw, SIGNAL(stroke( QIMPenStroke * )),
212 matcher, SLOT(strokeEntered( QIMPenStroke * )) );
213
214 shortcutCharSet = 0;
215 currCharSet = 0;
216 setupDlg = 0;
217 profile = 0;
218 mode = Normal;
219
220 loadProfiles();
221}
222
223QIMPenInput::~QIMPenInput()
224{
225 delete (HandwritingHelp*) helpDlg;
226}
227
228QSize QIMPenInput::sizeHint() const
229{
230 int fw = frameWidth();
231 int ps = wordPicker->isHidden() ? 0 : wordPicker->sizeHint().height();
232 return pw->sizeHint() + QSize( fw*2, fw*2+ps );
233}
234
235void QIMPenInput::loadProfiles()
236{
237 profileList.clear();
238 profile = 0;
239 delete shortcutCharSet;
240 shortcutCharSet = new QIMPenCharSet();
241 shortcutCharSet->setTitle( "Shortcut" );
242 QString path = QPEApplication::qpeDir() + "etc/qimpen";
243 QDir dir( path, "*.conf" );
244 QStringList list = dir.entryList();
245 QStringList::Iterator it;
246 for ( it = list.begin(); it != list.end(); ++it ) {
247 QIMPenProfile *p = new QIMPenProfile( path + "/" + *it );
248 profileList.append( p );
249 if ( p->shortcut() ) {
250 QIMPenCharIterator it( p->shortcut()->characters() );
251 for ( ; it.current(); ++it ) {
252 shortcutCharSet->addChar( new QIMPenChar(*it.current()) );
253 }
254 }
255 }
256
257 Config config( "handwriting" );
258 config.setGroup( "Settings" );
259 QString prof = config.readEntry( "Profile", "Default" );
260 selectProfile( prof );
261}
262
263void QIMPenInput::selectProfile( const QString &name )
264{
265 QListIterator<QIMPenProfile> it( profileList );
266 for ( ; it.current(); ++it ) {
267 if ( it.current()->name() == name ) {
268 profile = it.current();
269 break;
270 }
271 }
272
273 if ( !it.current() )
274 return;
275
276 pw->clearCharSets();
277 baseSets.clear();
278
279 matcher->setMultiStrokeTimeout( profile->multiStrokeTimeout() );
280 matcher->setWordMatchingEnabled( profile->matchWords() );
281
282 if ( !Global::fixedDawg().root() || !matcher->isWordMatchingEnabled() )
283 wordPicker->hide();
284 else
285 wordPicker->show();
286
287 if ( profile->uppercase() && profile->style() == QIMPenProfile::BothCases ) {
288 baseSets.append( profile->uppercase() );
289 pw->insertCharSet( profile->uppercase() );
290 }
291
292 if ( profile->lowercase() ) {
293 baseSets.append( profile->lowercase() );
294 pw->insertCharSet( profile->lowercase(), profile->style() == QIMPenProfile::BothCases ? 1 : 2 );
295 }
296
297 if ( profile->numeric() ) {
298 baseSets.append( profile->numeric() );
299 pw->insertCharSet( profile->numeric() );
300 }
301
302 if ( helpDlg )
303 delete (HandwritingHelp*) helpDlg;
304}
305
306void QIMPenInput::wordPicked( const QString &w )
307{
308 int bs = matcher->word().length();
309 for ( int i = 0; i < bs; i++ )
310 keypress( Qt::Key_Backspace << 16 );
311
312 for ( unsigned int i = 0; i < w.length(); i++ )
313 keypress( w[i].unicode() );
314
315 matcher->resetState();
316 wordPicker->clear();
317}
318
319void QIMPenInput::selectCharSet( int idx )
320{
321 if ( mode == Switch ) {
322 //qDebug( "Switch back to normal" );
323 pw->changeCharSet( baseSets.at(currCharSet), currCharSet );
324 mode = Normal;
325 }
326 currCharSet = idx;
327}
328
329void QIMPenInput::beginStroke()
330{
331}
332
333void QIMPenInput::strokeEntered( QIMPenStroke * )
334{
335 pw->greyStroke();
336}
337
338void QIMPenInput::erase()
339{
340 keypress( Qt::Key_Backspace << 16 );
341}
342
343void QIMPenInput::matchedCharacters( const QIMPenCharMatchList &cl )
344{
345 const QIMPenChar *ch = cl.first().penChar;
346 int scan = ch->character() >> 16;
347
348 if ( scan < QIMPenChar::ModeBase )
349 return;
350
351 // We matched a special character...
352
353 switch ( scan ) {
354 case QIMPenChar::Caps:
355 if ( profile->style() == QIMPenProfile::ToggleCases ) {
356 // qDebug( "Caps" );
357 if ( mode == SwitchLock ) {
358 // qDebug( "Switch to normal" );
359 pw->changeCharSet( profile->lowercase(), currCharSet );
360 mode = Switch;
361 } else {
362 // qDebug( "Switch to upper" );
363 pw->changeCharSet( profile->uppercase(), currCharSet );
364 mode = Switch;
365 }
366 }
367 break;
368 case QIMPenChar::CapsLock:
369 if ( profile->style() == QIMPenProfile::ToggleCases ) {
370 // qDebug( "CapsLock" );
371 if ( mode == Switch &&
372 baseSets.at(currCharSet) == profile->uppercase() ) {
373 // qDebug( "Switch to normal" );
374 pw->changeCharSet( profile->lowercase(), currCharSet );
375 // change our base set back to lower.
376 baseSets.remove( currCharSet );
377 baseSets.insert( currCharSet, profile->lowercase() );
378 mode = Normal;
379 } else {
380 // qDebug( "Switch to caps lock" );
381 pw->changeCharSet( profile->uppercase(), currCharSet );
382 // change our base set to upper.
383 baseSets.remove( currCharSet );
384 baseSets.insert( currCharSet, profile->uppercase() );
385 mode = SwitchLock;
386 }
387 }
388 break;
389 case QIMPenChar::Punctuation:
390 if ( profile->punctuation() ) {
391 //qDebug( "Switch to punctuation" );
392 pw->changeCharSet( profile->punctuation(), currCharSet );
393 mode = Switch;
394 }
395 break;
396 case QIMPenChar::Symbol:
397 if ( profile->symbol() ) {
398 //qDebug( "Switch to symbol" );
399 pw->changeCharSet( profile->symbol(), currCharSet );
400 mode = Switch;
401 }
402 break;
403 case QIMPenChar::Shortcut:
404 if ( shortcutCharSet ) {
405 pw->changeCharSet( shortcutCharSet, currCharSet );
406 mode = Switch;
407 }
408 break;
409 case QIMPenChar::Extended:
410 handleExtended( ch->data() );
411 break;
412 }
413}
414
415void QIMPenInput::keypress( uint scan_uni )
416{
417 int scan = scan_uni >> 16;
418 if ( !scan ) {
419 if ( scan_uni >= 'a' && scan_uni <= 'z' ) {
420 scan = Qt::Key_A + scan_uni - 'a';
421 } else if ( scan_uni >= 'A' && scan_uni <= 'Z' ) {
422 scan = Qt::Key_A + scan_uni - 'A';
423 } else if ( scan_uni == ' ' ) {
424 scan = Qt::Key_Space;
425 }
426 }
427
428 switch ( scan ) {
429 case Key_Tab:
430 scan_uni = 9;
431 break;
432 case Key_Return:
433 scan_uni = 13;
434 break;
435 case Key_Backspace:
436 scan_uni = 8;
437 break;
438 case Key_Escape:
439 scan_uni = 27;
440 break;
441 default:
442 break;
443 }
444
445 if ( mode == Switch ) {
446 //qDebug( "Switch back to normal" );
447 pw->changeCharSet( baseSets.at(currCharSet), currCharSet );
448 if ( baseSets.at(currCharSet) == profile->uppercase() )
449 mode = SwitchLock;
450 else
451 mode = Normal;
452 }
453
454 emit key( scan_uni&0xffff, scan, 0, true, false );
455 emit key( scan_uni&0xffff, scan, 0, false, false );
456}
457
458void QIMPenInput::handleExtended( const QString &ex )
459{
460 if ( ex.find( "Select" ) == 0 ) {
461 QString set = ex.mid( 7 );
462 qDebug( "Select new profile: %s", set.latin1() );
463 selectProfile( set );
464 }
465}
466
467void QIMPenInput::help()
468{
469 if ( helpDlg )
470 delete (HandwritingHelp*) helpDlg;
471 helpDlg = new HandwritingHelp( profile, 0, 0, WDestructiveClose );
472 helpDlg->showMaximized();
473 helpDlg->show();
474 helpDlg->raise();
475}
476
477/*!
478 Open the setup dialog
479*/
480void QIMPenInput::setup()
481{
482 if ( !setupDlg ) {
483 // We are working with our copy of the char sets here.
484 setupDlg = new QIMPenSetup( profile, 0, 0, TRUE );
485 setupDlg->editor()->selectCharSet( profile->charSets().at(1) );// lower case? This is crap.
486 if ( qApp->desktop()->width() < 640 )
487 setupDlg->showMaximized();
488 Global::hideInputMethod();
489 setupDlg->exec();
490 loadProfiles();
491 delete setupDlg;
492 setupDlg = 0;
493 Global::showInputMethod();
494 } else {
495 setupDlg->raise();
496 }
497}
498
499void QIMPenInput::backspace()
500{
501 keypress( Qt::Key_Backspace << 16 );
502 matcher->backspace();
503}
504
505void QIMPenInput::enter()
506{
507 keypress( Qt::Key_Return << 16 );
508 matcher->resetState();
509}
510
511
512void QIMPenInput::resetState()
513{
514 matcher->resetState();
515}
diff --git a/inputmethods/handwriting/qimpeninput.h b/inputmethods/handwriting/qimpeninput.h
new file mode 100644
index 0000000..b4e4006
--- a/dev/null
+++ b/inputmethods/handwriting/qimpeninput.h
@@ -0,0 +1,94 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#ifndef _QIMPENINPUT_H_
22#define _QIMPENINPUT_H_
23
24#include "qimpenprofile.h"
25
26#include <qpe/qdawg.h>
27
28#include <qframe.h>
29#include <qlist.h>
30#include <qguardedptr.h>
31
32class QPushButton;
33class QTimer;
34class QIMPenWidget;
35class QIMPenSetup;
36class QIMPenWordPick;
37class QIMPenMatch;
38class HandwritingHelp;
39
40class QIMPenInput : public QFrame
41{
42 Q_OBJECT
43public:
44 QIMPenInput( QWidget *parent = 0, const char *name = 0, WFlags f = 0 );
45 virtual ~QIMPenInput();
46
47 void resetState();
48
49 QSize sizeHint() const;
50
51signals:
52 void key( ushort, ushort, ushort, bool, bool );
53
54private slots:
55 void wordPicked( const QString & );
56 void selectCharSet( int );
57 void beginStroke();
58 void strokeEntered( QIMPenStroke *st );
59 void matchedCharacters( const QIMPenCharMatchList &cl );
60 void keypress( uint scan_uni );
61 void erase();
62 void help();
63 void setup();
64 void backspace();
65 void enter();
66
67private:
68 void loadProfiles();
69 void selectProfile( const QString &name );
70 void handleExtended( const QString & );
71 void updateWordMatch( QIMPenCharMatchList &ml );
72 void matchWords();
73 void scanDict( const QDawg::Node* n, int ipos, const QString& str, int error );
74
75 enum Mode { Normal, Switch, SwitchLock };
76
77private:
78 Mode mode;
79 QRect prefRect;
80 QIMPenWidget *pw;
81 QPushButton *helpBtn;
82 QPushButton *setupBtn;
83 QIMPenSetup *setupDlg;
84 QIMPenMatch *matcher;
85 QGuardedPtr<HandwritingHelp> helpDlg;
86 QIMPenProfile *profile;
87 QList<QIMPenProfile> profileList;
88 QIMPenCharSet *shortcutCharSet;
89 QIMPenCharSetList baseSets;
90 int currCharSet;
91 QIMPenWordPick *wordPicker;
92};
93
94#endif // _QIMPENINPUT_H_
diff --git a/inputmethods/handwriting/qimpenmatch.cpp b/inputmethods/handwriting/qimpenmatch.cpp
new file mode 100644
index 0000000..0d3e25a
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenmatch.cpp
@@ -0,0 +1,365 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "qimpenmatch.h"
22
23#include <qpe/qdawg.h>
24#include <qpe/global.h>
25
26#include <qapplication.h>
27#include <qtimer.h>
28
29#include <limits.h>
30
31 #define ERROR_THRESHOLD 200000
32 #define LOOKAHEAD_ERROR 2500
33//#define DEBUG_QIMPEN
34
35QIMPenMatch::QIMPenMatch( QObject *parent, const char *name )
36 : QObject( parent, name )
37{
38 strokes.setAutoDelete( TRUE );
39 wordChars.setAutoDelete( TRUE );
40 wordMatches.setAutoDelete( TRUE );
41
42 multiTimer = new QTimer( this );
43 connect( multiTimer, SIGNAL(timeout()), this, SLOT(endMulti()) );
44
45 prevMatchChar = 0;
46 prevMatchError = INT_MAX;
47 charSet = 0;
48 multiCharSet = 0;
49 multiTimeout = 500;
50 canErase = FALSE;
51 doWordMatching = true;
52}
53
54QIMPenMatch::~QIMPenMatch()
55{
56}
57
58void QIMPenMatch::setCharSet( QIMPenCharSet *cs )
59{
60 charSet = cs;
61}
62
63void QIMPenMatch::beginStroke()
64{
65 multiTimer->stop();
66}
67
68void QIMPenMatch::strokeEntered( QIMPenStroke *st )
69{
70#ifdef DEBUG_QIMPEN
71 qDebug( "---------- new stroke -------------" );
72#endif
73 strokes.append( new QIMPenStroke( *st ) );
74
75 QIMPenChar testChar;
76 QIMPenStrokeIterator it(strokes);
77 for ( ; it.current(); ++it ) {
78 testChar.addStroke( it.current() );
79 }
80
81 QIMPenCharMatchList ml;
82 if ( strokes.count() > 1 && multiCharSet ) {
83#ifdef DEBUG_QIMPEN
84 qDebug( "Matching against multi set" );
85#endif
86 ml = multiCharSet->match( &testChar );
87 } else {
88#ifdef DEBUG_QIMPEN
89 qDebug( "Matching against single set" );
90#endif
91 ml = charSet->match( &testChar );
92 }
93
94 processMatches( ml );
95}
96
97void QIMPenMatch::processMatches( QIMPenCharMatchList &ml )
98{
99#ifdef DEBUG_QIMPEN
100 qDebug( "Entering strokes.count() = %d", strokes.count() );
101#endif
102 QIMPenCharMatch candidate1 = { INT_MAX, 0 };
103 QIMPenCharMatch candidate2 = { INT_MAX, 0 };
104 QIMPenCharMatchList ml2;
105
106 if ( ml.count() ) {//&&
107 // ml.first().penChar->penStrokes().count() == strokes.count() ) {
108 candidate1 = ml.first();
109#ifdef DEBUG_QIMPEN
110 qDebug( QString("Candidate1 = %1").arg(QChar(candidate1.penChar->character())) );
111#endif
112 }
113
114 if ( strokes.count() > 1 ) {
115 // See if the last stroke can match a new character
116 QIMPenChar testChar;
117 QIMPenStroke *st = strokes.at(strokes.count()-1);
118 testChar.addStroke( st );
119 ml2 = charSet->match( &testChar );
120 if ( ml2.count() ) {
121 candidate2 = ml2.first();
122#ifdef DEBUG_QIMPEN
123 qDebug( QString("Candidate2 = %1").arg(QChar(candidate2.penChar->character())) );
124#endif
125 }
126 }
127
128 bool eraseLast = FALSE;
129 bool output = TRUE;
130
131 if ( candidate1.penChar && candidate2.penChar ) {
132 // Hmmm, a multi-stroke or a new character are both possible.
133 // Bias the multi-stroke case.
134 if ( QMAX(candidate2.error, prevMatchError)*3 < candidate1.error ) {
135 int i = strokes.count()-1;
136 while ( i-- ) {
137 strokes.removeFirst();
138 emit removeStroke();
139 }
140 prevMatchChar = candidate2.penChar;
141 prevMatchError = candidate2.error;
142 multiCharSet = charSet;
143 ml = ml2;
144#ifdef DEBUG_QIMPEN
145 qDebug( "** Using Candidate2" );
146#endif
147 } else {
148 if ( (prevMatchChar->character() >> 16) != Qt::Key_Backspace &&
149 (prevMatchChar->character() >> 16) < QIMPenChar::ModeBase )
150 eraseLast = TRUE;
151 prevMatchChar = candidate1.penChar;
152 prevMatchError = candidate1.error;
153#ifdef DEBUG_QIMPEN
154 qDebug( "** Using Candidate1, with erase" );
155#endif
156 }
157 } else if ( candidate1.penChar ) {
158 if ( strokes.count() != 1 )
159 eraseLast = TRUE;
160 else
161 multiCharSet = charSet;
162 prevMatchChar = candidate1.penChar;
163 prevMatchError = candidate1.error;
164#ifdef DEBUG_QIMPEN
165 qDebug( "** Using Candidate1" );
166#endif
167 } else if ( candidate2.penChar ) {
168 int i = strokes.count()-1;
169 while ( i-- ) {
170 strokes.removeFirst();
171 emit removeStroke();
172 }
173 prevMatchChar = candidate2.penChar;
174 prevMatchError = candidate2.error;
175 multiCharSet = charSet;
176 ml = ml2;
177#ifdef DEBUG_QIMPEN
178 qDebug( "** Using Candidate2" );
179#endif
180 } else {
181 if ( !ml.count() ) {
182#ifdef DEBUG_QIMPEN
183 qDebug( "** Failed" );
184#endif
185 canErase = FALSE;
186 } else {
187#ifdef DEBUG_QIMPEN
188 qDebug( "Need more strokes" );
189#endif
190 if ( strokes.count() == 1 )
191 canErase = FALSE;
192 multiCharSet = charSet;
193 }
194 output = FALSE;
195 emit noMatch();
196 }
197
198 if ( eraseLast && canErase ) {
199#ifdef DEBUG_QIMPEN
200 qDebug( "deleting last" );
201#endif
202 emit erase();
203 wordChars.removeLast();
204 wordEntered.truncate( wordEntered.length() - 1 );
205 }
206
207 if ( output ) {
208 emit matchedCharacters( ml );
209 uint code = prevMatchChar->character() >> 16;
210 if ( code < QIMPenChar::ModeBase ) {
211 updateWordMatch( ml );
212 emit keypress( prevMatchChar->character() );
213 }
214 canErase = TRUE;
215 }
216
217 if ( strokes.count() )
218 multiTimer->start( multiTimeout, TRUE );
219}
220
221void QIMPenMatch::updateWordMatch( QIMPenCharMatchList &ml )
222{
223 if ( !ml.count() || !doWordMatching )
224 return;
225 int ch = ml.first().penChar->character();
226 QChar qch( ch );
227 int code = ch >> 16;
228 if ( qch.isPunct() || qch.isSpace() ||
229 code == Qt::Key_Enter || code == Qt::Key_Return ||
230 code == Qt::Key_Tab || code == Qt::Key_Escape ) {
231 //qDebug( "Word Matching: Clearing word" );
232 wordChars.clear();
233 wordMatches.clear();
234 wordEntered = QString();
235 } else if ( code == Qt::Key_Backspace ) {
236 //qDebug( "Word Matching: Handle backspace" );
237 wordChars.removeLast();
238 wordEntered.truncate( wordEntered.length() - 1 );
239 matchWords();
240 } else {
241 QIMPenChar *matchCh;
242
243 wordChars.append( new QIMPenCharMatchList() );
244 wordEntered += ml.first().penChar->character();
245
246 QIMPenCharMatchList::Iterator it;
247 for ( it = ml.begin(); it != ml.end(); ++it ) {
248 matchCh = (*it).penChar;
249
250 if ( matchCh->penStrokes().count() == strokes.count() ) {
251 QChar ch(matchCh->character());
252 if ( !ch.isPunct() && !ch.isSpace() ) {
253 wordChars.last()->append( QIMPenCharMatch( (*it) ) );
254 }
255 }
256 }
257 matchWords();
258 }
259 if ( !wordMatches.count() || wordMatches.getFirst()->word != wordEntered )
260 wordMatches.prepend( new MatchWord( wordEntered, 0 ) );
261 emit matchedWords( wordMatches );
262}
263
264void QIMPenMatch::matchWords()
265{
266 if ( wordEntered.length() > 0 ) {
267 // more leaniency if we don't have many matches
268 if ( badMatches < 200 )
269 errorThreshold += (200 - badMatches) * 100;
270 } else
271 errorThreshold = ERROR_THRESHOLD;
272 wordMatches.clear();
273 goodMatches = 0;
274 badMatches = 0;
275 if ( wordChars.count() > 0 ) {
276 maxGuess = (int)wordChars.count() * 2;
277 if ( maxGuess < 3 )
278 maxGuess = 3;
279 QString str;
280 scanDict( Global::fixedDawg().root(), 0, str, 0 );
281/*
282 QListIterator<MatchWord> it( wordMatches);
283 for ( ; it.current(); ++it ) {
284 qDebug( QString("Match word: %1").arg(it.current()->word) );
285 }
286*/
287 }
288 //qDebug( "Possibles: Good %d, total %d", goodMatches, wordMatches.count() );
289 wordMatches.sort();
290}
291
292void QIMPenMatch::scanDict( const QDawg::Node* n, int ipos, const QString& str, int error )
293{
294 if ( !n )
295 return;
296 if ( error / (ipos+1) > errorThreshold )
297 return;
298
299 while (n) {
300 if ( goodMatches > 20 )
301 break;
302 if ( ipos < (int)wordChars.count() ) {
303 int i;
304 QChar testCh = QChar(n->letter());
305 QIMPenCharMatchList::Iterator it;
306 for ( i = 0, it = wordChars.at(ipos)->begin();
307 it != wordChars.at(ipos)->end() && i < 8; ++it, i++ ) {
308 QChar ch( (*it).penChar->character() );
309 if ( ch == testCh || ( !ipos && ch.lower() == testCh.lower() ) ) {
310 int newerr = error + (*it).error;
311 if ( testCh.category() == QChar::Letter_Uppercase )
312 ch = testCh;
313 QString newstr( str + ch );
314 if ( n->isWord() && ipos == (int)wordChars.count() - 1 ) {
315 wordMatches.append( new MatchWord( newstr, newerr ) );
316 goodMatches++;
317 }
318 scanDict( n->jump(), ipos+1, newstr, newerr );
319 }
320 }
321 } else if ( badMatches < 200 && ipos < maxGuess ) {
322 int d = ipos - wordChars.count();
323 int newerr = error + ERROR_THRESHOLD + LOOKAHEAD_ERROR*d;
324 QString newstr( str + n->letter() );
325 if ( n->isWord() ) {
326 wordMatches.append( new MatchWord( newstr, newerr ) );
327 badMatches++;
328 }
329 scanDict( n->jump(), ipos+1, newstr, newerr );
330 }
331 n = n->next();
332 }
333}
334
335void QIMPenMatch::backspace()
336{
337 wordChars.removeLast();
338 wordEntered.truncate( wordEntered.length() - 1 );
339 matchWords();
340 if ( !wordMatches.count() || wordMatches.getFirst()->word != wordEntered )
341 wordMatches.prepend( new MatchWord( wordEntered, 0 ) );
342 emit matchedWords( wordMatches );
343 if ( wordEntered.length() )
344 canErase = TRUE;
345}
346
347void QIMPenMatch::endMulti()
348{
349 int i = strokes.count();
350 while ( i-- )
351 emit removeStroke();
352 strokes.clear();
353 multiCharSet = 0;
354}
355
356void QIMPenMatch::resetState()
357{
358 if ( !wordEntered.isEmpty() ) {
359 wordChars.clear();
360 wordMatches.clear();
361 wordEntered = QString();
362 emit matchedWords( wordMatches );
363 canErase = FALSE;
364 }
365}
diff --git a/inputmethods/handwriting/qimpenmatch.h b/inputmethods/handwriting/qimpenmatch.h
new file mode 100644
index 0000000..d4a730e
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenmatch.h
@@ -0,0 +1,107 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#ifndef _QIMPENMATCH_H_
22#define _QIMPENMATCH_H_
23
24#include "qimpenchar.h"
25
26#include <qpe/qdawg.h>
27
28#include <qlist.h>
29
30class QTimer;
31class QIMPenWidget;
32class QIMPenSetup;
33class QIMPenWordPick;
34
35class QIMPenMatch : public QObject
36{
37 Q_OBJECT
38public:
39 QIMPenMatch( QObject *parent=0, const char *name=0 );
40 virtual ~QIMPenMatch();
41
42 void resetState();
43 void backspace();
44 void setMultiStrokeTimeout( int t ) { multiTimeout = t; }
45
46 const QString &word() const { return wordEntered; }
47
48 void setWordMatchingEnabled( bool e ) { doWordMatching = e; }
49 bool isWordMatchingEnabled() const { return doWordMatching; }
50
51 struct MatchWord {
52 MatchWord( const QString &w, int e ) { word = w; error = e; }
53 QString word;
54 int error;
55 };
56
57 class MatchWordList : public QList<MatchWord>
58 {
59 public:
60 int compareItems( QCollection::Item item1, QCollection::Item item2 ) {
61 MatchWord *m1 = (MatchWord *)item1;
62 MatchWord *m2 = (MatchWord *)item2;
63 return m1->error - m2->error;
64 }
65 };
66
67public slots:
68 void setCharSet( QIMPenCharSet * );
69 void beginStroke();
70 void strokeEntered( QIMPenStroke *st );
71
72signals:
73 void erase();
74 void noMatch();
75 void removeStroke();
76 void keypress( uint ch );
77 void matchedCharacters( const QIMPenCharMatchList & );
78 void matchedWords( const QIMPenMatch::MatchWordList & );
79
80protected slots:
81 void processMatches( QIMPenCharMatchList &ml );
82 void endMulti();
83
84protected:
85 void updateWordMatch( QIMPenCharMatchList &ml );
86 void matchWords();
87 void scanDict( const QDawg::Node* n, int ipos, const QString& str, int error );
88
89 QList<QIMPenStroke> strokes;
90 QIMPenChar *prevMatchChar;
91 int prevMatchError;
92 QIMPenCharSet *charSet;
93 QIMPenCharSet *multiCharSet;
94 QList<QIMPenCharMatchList> wordChars;
95 MatchWordList wordMatches;
96 QString wordEntered;
97 bool doWordMatching;
98 bool canErase;
99 int errorThreshold;
100 int goodMatches;
101 int badMatches;
102 int maxGuess;
103 QTimer *multiTimer;
104 int multiTimeout;
105};
106
107#endif // _QIMPENINPUT_H_
diff --git a/inputmethods/handwriting/qimpenprefbase.ui b/inputmethods/handwriting/qimpenprefbase.ui
new file mode 100644
index 0000000..1639d1a
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenprefbase.ui
@@ -0,0 +1,185 @@
1<!DOCTYPE UI><UI>
2<class>QIMPenPrefBase</class>
3<widget>
4 <class>QWidget</class>
5 <property stdset="1">
6 <name>name</name>
7 <cstring>QIMPenPrefBase</cstring>
8 </property>
9 <property stdset="1">
10 <name>geometry</name>
11 <rect>
12 <x>0</x>
13 <y>0</y>
14 <width>247</width>
15 <height>280</height>
16 </rect>
17 </property>
18 <property stdset="1">
19 <name>caption</name>
20 <string>Form1</string>
21 </property>
22 <vbox>
23 <property stdset="1">
24 <name>margin</name>
25 <number>11</number>
26 </property>
27 <property stdset="1">
28 <name>spacing</name>
29 <number>6</number>
30 </property>
31 <widget>
32 <class>QLabel</class>
33 <property stdset="1">
34 <name>name</name>
35 <cstring>TextLabel1</cstring>
36 </property>
37 <property stdset="1">
38 <name>text</name>
39 <string>Multi-stroke character timeout:</string>
40 </property>
41 </widget>
42 <widget>
43 <class>QLayoutWidget</class>
44 <property stdset="1">
45 <name>name</name>
46 <cstring>Layout2</cstring>
47 </property>
48 <hbox>
49 <property stdset="1">
50 <name>margin</name>
51 <number>0</number>
52 </property>
53 <property stdset="1">
54 <name>spacing</name>
55 <number>6</number>
56 </property>
57 <widget>
58 <class>QSlider</class>
59 <property stdset="1">
60 <name>name</name>
61 <cstring>multiStrokeSlider</cstring>
62 </property>
63 <property stdset="1">
64 <name>minValue</name>
65 <number>250</number>
66 </property>
67 <property stdset="1">
68 <name>maxValue</name>
69 <number>1000</number>
70 </property>
71 <property stdset="1">
72 <name>lineStep</name>
73 <number>10</number>
74 </property>
75 <property stdset="1">
76 <name>pageStep</name>
77 <number>50</number>
78 </property>
79 <property stdset="1">
80 <name>value</name>
81 <number>500</number>
82 </property>
83 <property stdset="1">
84 <name>orientation</name>
85 <enum>Horizontal</enum>
86 </property>
87 <property stdset="1">
88 <name>tickmarks</name>
89 <enum>Right</enum>
90 </property>
91 </widget>
92 <widget>
93 <class>QLabel</class>
94 <property stdset="1">
95 <name>name</name>
96 <cstring>multiStrokeLabel</cstring>
97 </property>
98 <property stdset="1">
99 <name>minimumSize</name>
100 <size>
101 <width>45</width>
102 <height>0</height>
103 </size>
104 </property>
105 <property stdset="1">
106 <name>text</name>
107 <string>ms</string>
108 </property>
109 <property stdset="1">
110 <name>alignment</name>
111 <set>AlignVCenter|AlignRight</set>
112 </property>
113 <property>
114 <name>hAlign</name>
115 </property>
116 </widget>
117 </hbox>
118 </widget>
119 <widget>
120 <class>QButtonGroup</class>
121 <property stdset="1">
122 <name>name</name>
123 <cstring>inputStyle</cstring>
124 </property>
125 <property stdset="1">
126 <name>title</name>
127 <string>Input areas displayed</string>
128 </property>
129 <vbox>
130 <property stdset="1">
131 <name>margin</name>
132 <number>11</number>
133 </property>
134 <property stdset="1">
135 <name>spacing</name>
136 <number>6</number>
137 </property>
138 <widget>
139 <class>QRadioButton</class>
140 <property stdset="1">
141 <name>name</name>
142 <cstring>bothCasesRadio</cstring>
143 </property>
144 <property stdset="1">
145 <name>text</name>
146 <string>Upper and lower case areas</string>
147 </property>
148 </widget>
149 <widget>
150 <class>QRadioButton</class>
151 <property stdset="1">
152 <name>name</name>
153 <cstring>toggleCaseRadio</cstring>
154 </property>
155 <property stdset="1">
156 <name>text</name>
157 <string>Lower case (toggle Upper case)</string>
158 </property>
159 </widget>
160 </vbox>
161 </widget>
162 <spacer>
163 <property>
164 <name>name</name>
165 <cstring>Spacer2</cstring>
166 </property>
167 <property stdset="1">
168 <name>orientation</name>
169 <enum>Vertical</enum>
170 </property>
171 <property stdset="1">
172 <name>sizeType</name>
173 <enum>Expanding</enum>
174 </property>
175 <property>
176 <name>sizeHint</name>
177 <size>
178 <width>20</width>
179 <height>20</height>
180 </size>
181 </property>
182 </spacer>
183 </vbox>
184</widget>
185</UI>
diff --git a/inputmethods/handwriting/qimpenprofile.cpp b/inputmethods/handwriting/qimpenprofile.cpp
new file mode 100644
index 0000000..4b5bb83
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenprofile.cpp
@@ -0,0 +1,245 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "qimpencombining.h"
22#include "qimpenprofile.h"
23
24#include <qpe/qpeapplication.h>
25#include <qpe/config.h>
26#include <qpe/global.h>
27
28
29QIMPenProfile::QIMPenProfile( const QString &fn )
30 : filename( fn )
31{
32 sets.setAutoDelete( true );
33
34 Config config( filename, Config::File );
35 config.setGroup( "Handwriting" );
36
37 pname = config.readEntry( "Name" );
38 pdesc = config.readEntry( "Description" );
39
40 tstyle = config.readBoolEntry( "CanSelectStyle", false );
41
42 wordMatch = config.readBoolEntry( "MatchWords", true );
43
44 config.setGroup( "Settings" );
45
46 pstyle = BothCases;
47 QString s = config.readEntry( "Style", "BothCases" );
48 if ( s == "ToggleCases" )
49 pstyle = ToggleCases;
50
51 msTimeout = config.readNumEntry( "MultiTimeout", 500 );
52
53 // Read user configuration
54 Config usrConfig( userConfig() );
55 usrConfig.setGroup( "Settings" );
56 msTimeout = usrConfig.readNumEntry( "MultiTimeout", msTimeout );
57
58 if ( tstyle && usrConfig.hasKey( "Style" ) ) {
59 pstyle = BothCases;
60 QString s = usrConfig.readEntry( "Style", "BothCases" );
61 if ( s == "ToggleCases" )
62 pstyle = ToggleCases;
63 }
64}
65
66void QIMPenProfile::setStyle( Style s )
67{
68 if ( tstyle && s != pstyle ) {
69 pstyle = s;
70 Config config( userConfig() );
71 config.setGroup( "Settings" );
72 QString s = pstyle == ToggleCases ? "ToggleCases" : "BothCases";
73 config.writeEntry( "Style", s );
74 }
75}
76
77void QIMPenProfile::setMultiStrokeTimeout( int t )
78{
79 if ( t != msTimeout ) {
80 msTimeout = t;
81 Config config( userConfig() );
82 config.setGroup( "Settings" );
83 config.writeEntry( "MultiTimeout", msTimeout );
84 }
85}
86
87QString QIMPenProfile::userConfig()
88{
89 QString un = filename;
90 int pos = un.findRev( '/' );
91 if ( pos >= 0 )
92 un = un.mid( pos + 1 );
93 pos = un.find( '.' );
94 if ( pos > 0 )
95 un.truncate( pos );
96
97 un = "handwriting-" + un;
98
99 return un;
100}
101
102void QIMPenProfile::loadData()
103{
104 Config config( filename, Config::File );
105 config.setGroup( "CharSets" );
106
107 QString baseDir = QPEApplication::qpeDir();
108 baseDir += "/etc/";
109 // accents
110 QIMPenCombining *combining = 0;
111 QString s = config.readEntry( "Combining" );
112 if ( !s.isEmpty() ) {
113 combining = new QIMPenCombining( baseDir + "qimpen/" + s );
114 if ( combining->isEmpty() ) {
115 delete combining;
116 combining = 0;
117 }
118 }
119 // uppercase latin1
120 QIMPenCharSet *cs = 0;
121 s = config.readEntry( "Uppercase" );
122 if ( !s.isEmpty() ) {
123 cs = new QIMPenCharSet( baseDir + "qimpen/" + s );
124 cs->load( Global::applicationFileName("qimpen",s), QIMPenCharSet::User );
125 if ( !cs->isEmpty() ) {
126 if ( combining )
127 combining->addCombined( cs );
128 sets.append( cs );
129 } else {
130 delete cs;
131 }
132 }
133 // lowercase latin1
134 s = config.readEntry( "Lowercase" );
135 if ( !s.isEmpty() ) {
136 cs = new QIMPenCharSet( baseDir + "qimpen/" + s );
137 cs->load( Global::applicationFileName("qimpen",s), QIMPenCharSet::User );
138 if ( !cs->isEmpty() ) {
139 if ( combining )
140 combining->addCombined( cs );
141 sets.append( cs );
142 } else {
143 delete cs;
144 }
145 }
146 // numeric (may comtain punctuation and symbols)
147 s = config.readEntry( "Numeric" );
148 if ( !s.isEmpty() ) {
149 cs = new QIMPenCharSet( baseDir + "qimpen/" + s );
150 cs->load( Global::applicationFileName("qimpen",s), QIMPenCharSet::User );
151 if ( !cs->isEmpty() ) {
152 sets.append( cs );
153 } else {
154 delete cs;
155 }
156 }
157 // punctuation
158 s = config.readEntry( "Punctuation" );
159 if ( !s.isEmpty() ) {
160 cs = new QIMPenCharSet( baseDir + "qimpen/" + s );
161 cs->load( Global::applicationFileName("qimpen",s), QIMPenCharSet::User );
162 if ( !cs->isEmpty() ) {
163 sets.append( cs );
164 } else {
165 delete cs;
166 }
167 }
168 // symbol
169 s = config.readEntry( "Symbol" );
170 if ( !s.isEmpty() ) {
171 cs = new QIMPenCharSet( baseDir + "qimpen/" + s );
172 cs->load( Global::applicationFileName("qimpen",s), QIMPenCharSet::User );
173 if ( !cs->isEmpty() ) {
174 sets.append( cs );
175 } else {
176 delete cs;
177 }
178 }
179 // shortcut
180 s = config.readEntry( "Shortcut" );
181 if ( !s.isEmpty() ) {
182 cs = new QIMPenCharSet( baseDir + "qimpen/" + s );
183 cs->load( Global::applicationFileName("qimpen",s), QIMPenCharSet::User );
184 if ( !cs->isEmpty() ) {
185 sets.append( cs );
186 } else {
187 delete cs;
188 }
189 }
190
191 if ( combining )
192 delete combining;
193}
194
195QIMPenCharSet *QIMPenProfile::uppercase()
196{
197 return find( QIMPenCharSet::Upper );
198}
199
200QIMPenCharSet *QIMPenProfile::lowercase()
201{
202 return find( QIMPenCharSet::Lower );
203}
204
205QIMPenCharSet *QIMPenProfile::numeric()
206{
207 return find( QIMPenCharSet::Numeric );
208}
209
210QIMPenCharSet *QIMPenProfile::punctuation()
211{
212 return find( QIMPenCharSet::Punctuation );
213}
214
215QIMPenCharSet *QIMPenProfile::symbol()
216{
217 return find( QIMPenCharSet::Symbol );
218}
219
220QIMPenCharSet *QIMPenProfile::shortcut()
221{
222 return find( QIMPenCharSet::Shortcut );
223}
224
225QIMPenCharSetList &QIMPenProfile::charSets()
226{
227 if ( sets.isEmpty() )
228 loadData();
229 return sets;
230}
231
232QIMPenCharSet *QIMPenProfile::find( QIMPenCharSet::Type t )
233{
234 if ( sets.isEmpty() )
235 loadData();
236 QIMPenCharSetIterator it( sets );
237 for ( ; it.current(); ++it ) {
238 if ( it.current()->type() == t )
239 return it.current();
240 }
241
242 return 0;
243}
244
245
diff --git a/inputmethods/handwriting/qimpenprofile.h b/inputmethods/handwriting/qimpenprofile.h
new file mode 100644
index 0000000..4ce4367
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenprofile.h
@@ -0,0 +1,70 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#ifndef QIMPENPROFILE_H_
22#define QIMPENPROFILE_H_
23
24#include "qimpenchar.h"
25
26class QIMPenProfile
27{
28public:
29 QIMPenProfile( const QString &fn );
30
31 const QString &name() const { return pname; }
32 const QString &description() const { return pdesc; }
33
34 enum Style { ToggleCases, BothCases };
35 Style style() const { return pstyle; }
36 void setStyle( Style s );
37
38 bool canSelectStyle() const { return tstyle; }
39
40 int multiStrokeTimeout() const { return msTimeout; }
41 void setMultiStrokeTimeout( int t );
42
43 bool matchWords() const { return wordMatch; }
44
45 QIMPenCharSet *uppercase();
46 QIMPenCharSet *lowercase();
47 QIMPenCharSet *numeric();
48 QIMPenCharSet *punctuation();
49 QIMPenCharSet *symbol();
50 QIMPenCharSet *shortcut();
51 QIMPenCharSet *find( QIMPenCharSet::Type t );
52
53 QIMPenCharSetList &charSets();
54
55private:
56 QString userConfig();
57 void loadData();
58
59private:
60 QIMPenCharSetList sets;
61 QString filename;
62 QString pname;
63 QString pdesc;
64 Style pstyle;
65 bool tstyle;
66 int msTimeout;
67 bool wordMatch;
68};
69
70#endif
diff --git a/inputmethods/handwriting/qimpensetup.cpp b/inputmethods/handwriting/qimpensetup.cpp
new file mode 100644
index 0000000..a6ae3a8
--- a/dev/null
+++ b/inputmethods/handwriting/qimpensetup.cpp
@@ -0,0 +1,656 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "qimpenwidget.h"
22#include "qimpenprefbase.h"
23#include "qimpensetup.h"
24
25#include <qpe/qpeapplication.h>
26#include <qpe/config.h>
27
28#include <qcombobox.h>
29#include <qlistbox.h>
30#include <qlabel.h>
31#include <qpushbutton.h>
32#include <qlayout.h>
33#include <qpixmap.h>
34#include <qbuttongroup.h>
35#include <qslider.h>
36#include <qtabwidget.h>
37#include <qdir.h>
38#include <qmessagebox.h>
39
40
41/* XPM */
42static const char * const left_xpm[] = {
43"16 16 2 1",
44 " c None",
45 ".c #000000",
46" ",
47" ",
48" ",
49" . ",
50" .. ",
51" ... ",
52" .... ",
53" ..... ",
54" ...... ",
55" ..... ",
56" .... ",
57" ... ",
58" .. ",
59" . ",
60" ",
61" "};
62
63
64/* XPM */
65static const char * const right_xpm[] = {
66"16 16 2 1",
67 " c None",
68 ".c #000000",
69" ",
70" ",
71" ",
72" . ",
73" .. ",
74" ... ",
75" .... ",
76" ..... ",
77" ...... ",
78" ..... ",
79" .... ",
80" ... ",
81" .. ",
82" . ",
83" ",
84" "};
85
86
87
88QIMPenSetup::QIMPenSetup( QIMPenProfile *p, QWidget *parent,
89 const char *name, bool modal, int WFlags )
90 : QDialog( parent, name, modal, WFlags ), profileCombo(0), profile(p)
91{
92 setCaption( tr("Setup Handwriting Input") );
93
94 QVBoxLayout *vb = new QVBoxLayout( this );
95
96#if 0
97 profileList.setAutoDelete( true );
98 QHBoxLayout *hb = new QHBoxLayout( vb );
99 hb->setMargin( 6 );
100 QLabel *l = new QLabel( tr("Character Profile:"), this );
101 hb->addWidget( l );
102 profileCombo = new QComboBox( this );
103 connect( profileCombo, SIGNAL(activated(const QString &)),
104 this, SLOT(selectProfile(const QString &)) );
105 hb->addWidget( profileCombo );
106 loadProfiles();
107#else
108 profileList.append( profile );
109#endif
110
111 QTabWidget *tw = new QTabWidget( this );
112 vb->addWidget( tw );
113
114 pref = new QIMPenPrefBase( this );
115 tw->addTab( pref, tr("Preferences") );
116
117 pref->inputStyle->setExclusive( TRUE );
118
119 style = profile->style() == QIMPenProfile::ToggleCases ? 1 : 0;
120 pref->inputStyle->setButton( style );
121 connect( pref->inputStyle, SIGNAL(clicked(int)),
122 this, SLOT(styleClicked(int)) );
123 pref->inputStyle->setEnabled( profile->canSelectStyle() );
124
125 multiTimeout = profile->multiStrokeTimeout();
126 pref->multiStrokeSlider->setValue( multiTimeout );
127 multiTimeoutChanged( multiTimeout );
128 connect( pref->multiStrokeSlider, SIGNAL(valueChanged(int)),
129 this, SLOT(multiTimeoutChanged(int)) );
130
131 edit = new QIMPenEdit( p, tw );
132 tw->addTab( edit, tr("Customize") );
133}
134
135void QIMPenSetup::loadProfiles()
136{
137 QString path = QPEApplication::qpeDir() + "etc/qimpen";
138 QDir dir( path, "*.conf" );
139 QStringList list = dir.entryList();
140 QStringList::Iterator it;
141 for ( it = list.begin(); it != list.end(); ++it ) {
142 QIMPenProfile *p = new QIMPenProfile( path + "/" + *it );
143 profileList.append( p );
144 profileCombo->insertItem( p->name() );
145 if ( p->name() == profile->name() ) {
146 profileCombo->setCurrentItem( profileCombo->count()-1 );
147 profile = p;
148 }
149 }
150}
151
152void QIMPenSetup::styleClicked( int id )
153{
154 style = id;
155}
156
157void QIMPenSetup::multiTimeoutChanged( int v )
158{
159 multiTimeout = v;
160 pref->multiStrokeLabel->setText( tr("%1 ms").arg(v) );
161}
162
163void QIMPenSetup::selectProfile( const QString &p )
164{
165 if ( p == profile->name() )
166 return;
167
168 profile->setStyle( style ? QIMPenProfile::ToggleCases : QIMPenProfile::BothCases );
169 profile->setMultiStrokeTimeout( multiTimeout );
170
171 for ( int i = 0; i < (int)profileList.count(); i++ ) {
172 if ( profileList.at(i)->name() == p ) {
173 profile = profileList.at(i);
174 style = profile->style() == QIMPenProfile::ToggleCases ? 1 : 0;
175 pref->inputStyle->setButton( style );
176 pref->inputStyle->setEnabled( profile->canSelectStyle() );
177 multiTimeout = profile->multiStrokeTimeout();
178 pref->multiStrokeSlider->setValue( multiTimeout );
179 multiTimeoutChanged( multiTimeout );
180 edit->setProfile( profile );
181 break;
182 }
183 }
184}
185
186void QIMPenSetup::accept()
187{
188 profile->setStyle( style ? QIMPenProfile::ToggleCases : QIMPenProfile::BothCases );
189 profile->setMultiStrokeTimeout( multiTimeout );
190 // Save current profile
191 if ( profileCombo ) {
192 Config config( "handwriting" );
193 config.setGroup( "Settings" );
194 config.writeEntry( "Profile", profileCombo->currentText() );
195 }
196 // Save charsets
197 bool ok = TRUE;
198 for ( int i = 0; i < (int)profileList.count(); i++ ) {
199 QIMPenProfile *prof = profileList.at(i);
200 QIMPenCharSetIterator it(prof->charSets());
201 for ( ; it.current(); ++it ) {
202 if ( !(it.current()->save( QIMPenCharSet::User )) ) {
203 ok = FALSE;
204 break;
205 }
206 }
207 }
208 if ( !ok ) {
209 if ( QMessageBox::critical( 0, tr( "Out of space" ),
210 tr("Unable to save information.\n"
211 "Free up some space\n"
212 "and try again.\n"
213 "\nQuit anyway?"),
214 QMessageBox::Yes|QMessageBox::Escape,
215 QMessageBox::No|QMessageBox::Default )
216 != QMessageBox::No ) {
217 QDialog::accept();
218 }
219 } else {
220 QDialog::accept();
221 }
222}
223
224//---------------------------------------------------------------------------
225
226QIMPenInputCharDlg::QIMPenInputCharDlg( QWidget *parent, const char *name,
227 bool modal, int WFlags)
228 : QDialog( parent, name, modal, WFlags )
229{
230 setCaption( tr("Enter new character") );
231 uni = 0;
232
233 QVBoxLayout *vb = new QVBoxLayout( this, 10 );
234
235 QHBoxLayout *hb = new QHBoxLayout();
236 vb->addLayout( hb );
237
238 QLabel *label = new QLabel( "Character:", this );
239 hb->addWidget( label );
240
241 QComboBox *cb = new QComboBox( TRUE, this );
242 connect( cb, SIGNAL(activated(int)), SLOT(setSpecial(int)) );
243 connect( cb, SIGNAL(textChanged(const QString &)),
244 SLOT(setCharacter(const QString &)) );
245 addSpecial( cb );
246 cb->setEditText( "" );
247 hb->addWidget( cb );
248
249 hb = new QHBoxLayout();
250 vb->addLayout( hb );
251
252 QPushButton *pb = new QPushButton( "OK", this );
253 connect( pb, SIGNAL(clicked()), SLOT(accept()));
254 hb->addWidget( pb );
255 pb = new QPushButton( "Cancel", this );
256 connect( pb, SIGNAL(clicked()), SLOT(reject()));
257 hb->addWidget( pb );
258
259 cb->setFocus();
260}
261
262void QIMPenInputCharDlg::addSpecial( QComboBox *cb )
263{
264 int i = 0;
265 while ( qimpen_specialKeys[i].code != Key_unknown ) {
266 cb->insertItem( qimpen_specialKeys[i].name );
267 i++;
268 }
269}
270
271void QIMPenInputCharDlg::setSpecial( int sp )
272{
273 uni = qimpen_specialKeys[sp].code << 16;
274}
275
276void QIMPenInputCharDlg::setCharacter( const QString &string )
277{
278 uni = string[0].unicode();
279}
280
281//---------------------------------------------------------------------------
282
283class CharListItem : public QListBoxText
284{
285public:
286 CharListItem( const QString &text, uint c )
287 : QListBoxText( text )
288 {
289 _code = c;
290 }
291
292 uint code() const { return _code; }
293
294protected:
295 uint _code;
296};
297
298/*!
299 \class QIMPenEdit qimpensetup.h
300
301 Class to allow users to input totally useless character definitions
302 which could match any number of the default set.
303*/
304
305QIMPenEdit::QIMPenEdit( QIMPenProfile *p, QWidget *parent,
306 const char *name )
307 : QWidget( parent, name ), profile(p)
308{
309 currentChar = 0;
310 currentCode = 0;
311 inputChar = new QIMPenChar();
312
313 QVBoxLayout *tvb = new QVBoxLayout( this, 5 );
314
315 QGridLayout *gl = new QGridLayout( tvb, 4, 2 );
316 gl->setRowStretch( 1, 1 );
317 gl->addRowSpacing( 2, 35 );
318 gl->addRowSpacing( 3, 35 );
319
320 charSetCombo = new QComboBox( this );
321 gl->addMultiCellWidget( charSetCombo, 0, 0, 0, 1 );
322 connect( charSetCombo, SIGNAL(activated(int)), SLOT(selectCharSet(int)));
323 QIMPenCharSetIterator it( profile->charSets() );
324 for ( ; it.current(); ++it ) {
325 charSetCombo->insertItem( it.current()->description() );
326 }
327
328 charList = new QListBox( this );
329 charList->setMinimumHeight( charList->sizeHint().height() );
330 connect( charList, SIGNAL(highlighted(int)), SLOT(selectChar(int)) );
331 gl->addWidget( charList, 1, 0 );
332
333 pw = new QIMPenWidget( this );
334 pw->setFixedHeight( 75 );
335 gl->addMultiCellWidget( pw, 2, 3, 0, 0 );
336 connect( pw, SIGNAL(stroke(QIMPenStroke *)),
337 SLOT(newStroke(QIMPenStroke *)) );
338
339 QVBoxLayout *vb = new QVBoxLayout();
340 gl->addLayout( vb, 1, 1 );
341 newBtn = new QPushButton( tr("New..."), this );
342 connect( newBtn, SIGNAL(clicked()), SLOT(addNewChar()) );
343 vb->addWidget( newBtn );
344
345 addBtn = new QPushButton( tr("Add"), this );
346 connect( addBtn, SIGNAL(clicked()), SLOT(addChar()) );
347 vb->addWidget( addBtn );
348
349 removeBtn = new QPushButton( tr("Remove"), this );
350 connect( removeBtn, SIGNAL(clicked()), SLOT(removeChar()) );
351 vb->addWidget( removeBtn );
352
353 QPushButton *pb = new QPushButton( tr("Default"), this );
354 connect( pb, SIGNAL(clicked()), SLOT(defaultChars()) );
355 vb->addWidget( pb );
356
357 QHBoxLayout *hb = new QHBoxLayout();
358 gl->addLayout( hb, 2, 1 );
359 prevBtn = new QPushButton( this );
360 prevBtn->setPixmap( QPixmap( (const char **)left_xpm ) );
361 connect( prevBtn, SIGNAL(clicked()), SLOT(prevChar()));
362 hb->addWidget( prevBtn );
363
364 nextBtn = new QPushButton( this );
365 nextBtn->setPixmap( QPixmap( (const char **)right_xpm ) );
366 connect( nextBtn, SIGNAL(clicked()), SLOT(nextChar()));
367 hb->addWidget( nextBtn );
368
369 pb = new QPushButton( tr("Clear"), this );
370 connect( pb, SIGNAL(clicked()), SLOT(clearChar()) );
371 gl->addWidget( pb, 3, 1 );
372
373 //--
374#if !defined(Q_WS_QWS)
375 hb = new QHBoxLayout( tvb );
376 pb = new QPushButton( "OK", this );
377 connect( pb, SIGNAL(clicked()), SLOT(accept()) );
378 hb->addWidget( pb );
379
380 pb = new QPushButton( "Cancel", this );
381 connect( pb, SIGNAL(clicked()), SLOT(reject()) );
382 hb->addWidget( pb );
383#endif
384 selectCharSet( 0 );
385 charList->setFocus();
386
387 resize( minimumSize() );
388 enableButtons();
389}
390
391void QIMPenEdit::setProfile( QIMPenProfile *p )
392{
393 profile = p;
394 charSetCombo->clear();
395 QIMPenCharSetIterator it( profile->charSets() );
396 for ( ; it.current(); ++it ) {
397 charSetCombo->insertItem( it.current()->description() );
398 }
399 selectCharSet( 0 );
400 charList->setFocus();
401 enableButtons();
402}
403
404void QIMPenEdit::selectCharSet( QIMPenCharSet *c )
405{
406 int i = 0;
407 QIMPenCharSetIterator it( profile->charSets() );
408 for ( ; it.current(); ++it, i++ ) {
409 if ( it.current() == c ) {
410 charSetCombo->setCurrentItem( i );
411 selectCharSet( i );
412 }
413 }
414}
415
416
417/*!
418 Fill the character list box with the characters. Duplicates are not
419 inserted.
420*/
421void QIMPenEdit::fillCharList()
422{
423 charList->clear();
424 QIMPenCharIterator it( currentSet->characters() );
425 CharListItem *li = 0;
426 for ( ; it.current(); ++it ) {
427 uint ch = it.current()->character();
428 QString n = it.current()->name();
429 if ( !n.isEmpty() )
430 li = new CharListItem( n, ch );
431 if ( li ) {
432 CharListItem *i = (CharListItem *)charList->findItem( li->text() );
433 if ( !i || i->code() != ch ) {
434 charList->insertItem( li );
435 } else {
436 delete li;
437 li = 0;
438 }
439 }
440 }
441 currentChar = 0;
442}
443
444void QIMPenEdit::enableButtons()
445{
446 bool add = !inputChar->isEmpty();
447 newBtn->setEnabled( add );
448 addBtn->setEnabled( add );
449 removeBtn->setEnabled( currentChar );
450}
451
452/*!
453 Find the previous character with the same code as the current one.
454 returns 0 if there is no previous character.
455*/
456QIMPenChar *QIMPenEdit::findPrev()
457{
458 if ( !currentChar )
459 return 0;
460 QIMPenCharIterator it( currentSet->characters() );
461 bool found = FALSE;
462 for ( it.toLast(); it.current(); --it ) {
463 if ( !found && it.current() == currentChar )
464 found = TRUE;
465 else if ( found && it.current()->character() == currentCode &&
466 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
467 return it.current();
468 }
469 }
470
471 return 0;
472}
473
474/*!
475 Find the next character with the same code as the current one.
476 returns 0 if there is no next character.
477*/
478QIMPenChar *QIMPenEdit::findNext()
479{
480 if ( !currentChar )
481 return 0;
482 QIMPenCharIterator it( currentSet->characters() );
483 bool found = FALSE;
484 for ( ; it.current(); ++it ) {
485 if ( !found && it.current() == currentChar )
486 found = TRUE;
487 else if ( found && it.current()->character() == currentCode &&
488 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
489 return it.current();
490 }
491 }
492
493 return 0;
494}
495
496void QIMPenEdit::setCurrentChar( QIMPenChar *pc )
497{
498 currentChar = pc;
499 pw->showCharacter( currentChar );
500 if ( currentChar ) {
501 prevBtn->setEnabled( findPrev() != 0 );
502 nextBtn->setEnabled( findNext() != 0 );
503 }
504}
505
506void QIMPenEdit::prevChar()
507{
508 QIMPenChar *pc = findPrev();
509 if ( pc )
510 setCurrentChar( pc );
511}
512
513void QIMPenEdit::nextChar()
514{
515 QIMPenChar *pc = findNext();
516 if ( pc )
517 setCurrentChar( pc );
518}
519
520void QIMPenEdit::clearChar()
521{
522 inputChar->clear();
523 pw->clear();
524 enableButtons();
525}
526
527void QIMPenEdit::selectChar( int i )
528{
529 currentChar = 0;
530 currentCode = ((CharListItem *)charList->item(i))->code();
531 QIMPenCharIterator it(currentSet->characters() );
532 for ( ; it.current(); ++it ) {
533 if ( it.current()->character() == currentCode &&
534 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
535 setCurrentChar( it.current() );
536 break;
537 }
538 }
539 if ( !it.current() )
540 setCurrentChar( 0 );
541 inputChar->clear();
542}
543
544void QIMPenEdit::selectCharSet( int i )
545{
546 if ( currentSet )
547 pw->removeCharSet( 0 );
548 currentSet = profile->charSets().at( i );
549 fillCharList();
550 pw->insertCharSet( currentSet );
551 inputChar->clear();
552 if ( charList->count() ) {
553 charList->setSelected( 0, TRUE );
554 selectChar(0);
555 }
556}
557
558void QIMPenEdit::addChar()
559{
560 if ( !inputChar->isEmpty() ) {
561 QIMPenChar *pc = new QIMPenChar( *inputChar );
562 pc->setCharacter( currentCode );
563
564 // User characters override all matching system characters.
565 // Copy and mark deleted identical system characters.
566 QIMPenCharIterator it(currentSet->characters() );
567 QIMPenChar *sc = 0;
568 while ( (sc = it.current()) != 0 ) {
569 ++it;
570 if ( sc->character() == currentCode &&
571 sc->testFlag( QIMPenChar::System ) &&
572 !sc->testFlag( QIMPenChar::Deleted ) ) {
573 QIMPenChar *cc = new QIMPenChar( *sc );
574 cc->clearFlag( QIMPenChar::System );
575 currentSet->addChar( cc );
576 sc->setFlag( QIMPenChar::Deleted );
577 }
578 }
579
580 currentSet->addChar( pc );
581 setCurrentChar( pc );
582 inputChar->clear();
583 }
584}
585
586void QIMPenEdit::addNewChar()
587{
588 if ( !inputChar->isEmpty() ) {
589 QIMPenInputCharDlg dlg( 0, 0, TRUE );
590 if ( dlg.exec() ) {
591 currentCode = dlg.unicode();
592 addChar();
593 fillCharList();
594 for ( unsigned int i = 0; i < charList->count(); i++ ) {
595 CharListItem *li = (CharListItem *)charList->item(i);
596 if ( li->code() == dlg.unicode() ) {
597 charList->setSelected( i, TRUE );
598 break;
599 }
600 }
601 }
602 }
603}
604
605void QIMPenEdit::removeChar()
606{
607 if ( currentChar ) {
608 QIMPenChar *pc = findPrev();
609 if ( !pc ) pc = findNext();
610 if ( currentChar->testFlag( QIMPenChar::System ) )
611 currentChar->setFlag( QIMPenChar::Deleted );
612 else
613 currentSet->removeChar( currentChar );
614 setCurrentChar( pc );
615 }
616}
617
618void QIMPenEdit::defaultChars()
619{
620 if ( currentCode ) {
621 currentChar = 0;
622 bool haveSystem = FALSE;
623 QIMPenCharIterator it(currentSet->characters() );
624 for ( ; it.current(); ++it ) {
625 if ( it.current()->character() == currentCode &&
626 it.current()->testFlag( QIMPenChar::System ) ) {
627 haveSystem = TRUE;
628 break;
629 }
630 }
631 if ( haveSystem ) {
632 it.toFirst();
633 while ( it.current() ) {
634 QIMPenChar *pc = it.current();
635 ++it;
636 if ( pc->character() == currentCode ) {
637 if ( pc->testFlag( QIMPenChar::System ) ) {
638 pc->clearFlag( QIMPenChar::Deleted );
639 if ( !currentChar )
640 currentChar = pc;
641 } else {
642 currentSet->removeChar( pc );
643 }
644 }
645 }
646 setCurrentChar( currentChar );
647 }
648 }
649}
650
651void QIMPenEdit::newStroke( QIMPenStroke *st )
652{
653 inputChar->addStroke( st );
654 enableButtons();
655}
656
diff --git a/inputmethods/handwriting/qimpensetup.h b/inputmethods/handwriting/qimpensetup.h
new file mode 100644
index 0000000..5d3064b
--- a/dev/null
+++ b/inputmethods/handwriting/qimpensetup.h
@@ -0,0 +1,124 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include <qdialog.h>
22#include <qlist.h>
23#include "qimpenprofile.h"
24
25class QListBox;
26class QPushButton;
27class QComboBox;
28class QIMPenWidget;
29class QIMPenEdit;
30class QIMPenPrefBase;
31
32class QIMPenSetup : public QDialog
33{
34 Q_OBJECT
35public:
36 QIMPenSetup( QIMPenProfile *p, QWidget *parent=0,
37 const char *name=0, bool modal=FALSE, int WFlags=0 );
38
39 QIMPenEdit *editor() { return edit; }
40
41protected:
42 void loadProfiles();
43 virtual void accept();
44
45private slots:
46 void styleClicked( int );
47 void multiTimeoutChanged( int );
48 void selectProfile( const QString &p );
49
50private:
51 QComboBox *profileCombo;
52 QIMPenEdit *edit;
53 QIMPenPrefBase *pref;
54 int style;
55 int multiTimeout;
56 QIMPenProfile *profile;
57 QList<QIMPenProfile> profileList;
58};
59
60class QIMPenInputCharDlg : public QDialog
61{
62 Q_OBJECT
63public:
64 QIMPenInputCharDlg( QWidget *parent = 0, const char *name = 0,
65 bool modal = FALSE, int WFlags = 0 );
66
67 unsigned int unicode() const { return uni; }
68
69protected:
70 void addSpecial( QComboBox *cb );
71
72protected slots:
73 void setSpecial( int sp );
74 void setCharacter( const QString &string );
75
76protected:
77 uint uni;
78};
79
80class QIMPenEdit : public QWidget
81{
82 Q_OBJECT
83public:
84 QIMPenEdit( QIMPenProfile *p, QWidget *parent=0,
85 const char *name=0 );
86
87 void setProfile( QIMPenProfile *p );
88 void selectCharSet( QIMPenCharSet *c );
89
90protected:
91 void fillCharList();
92 void enableButtons();
93 QIMPenChar *findPrev();
94 QIMPenChar *findNext();
95 void setCurrentChar( QIMPenChar * );
96
97protected slots:
98 void prevChar();
99 void nextChar();
100 void clearChar();
101 void selectChar( int );
102 void selectCharSet( int );
103 void addChar();
104 void addNewChar();
105 void removeChar();
106 void defaultChars();
107 void newStroke( QIMPenStroke * );
108
109protected:
110 QIMPenWidget *pw;
111 QComboBox *charSetCombo;
112 QListBox *charList;
113 QPushButton *newBtn;
114 QPushButton *addBtn;
115 QPushButton *removeBtn;
116 QPushButton *prevBtn;
117 QPushButton *nextBtn;
118 uint currentCode;
119 QIMPenChar *currentChar;
120 QIMPenChar *inputChar;
121 QIMPenCharSet *currentSet;
122 QIMPenProfile *profile;
123};
124
diff --git a/inputmethods/handwriting/qimpenstroke.cpp b/inputmethods/handwriting/qimpenstroke.cpp
new file mode 100644
index 0000000..3567d6d
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenstroke.cpp
@@ -0,0 +1,646 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include <qfile.h>
22#include <qtl.h>
23#include <math.h>
24#include <limits.h>
25#include <qdatastream.h>
26#include "qimpenstroke.h"
27
28#define QIMPEN_CORRELATION_POINTS 25
29//#define DEBUG_QIMPEN
30
31/*!
32 \class QIMPenStroke qimpenstroke.h
33
34 Handles a single stroke. Can calculate closeness of match to
35 another stroke.
36*/
37
38QIMPenStroke::QIMPenStroke()
39{
40}
41
42QIMPenStroke::QIMPenStroke( const QIMPenStroke &st )
43{
44 startPoint = st.startPoint;
45 lastPoint = st.lastPoint;
46 links = st.links.copy();
47}
48
49QIMPenStroke &QIMPenStroke::operator=( const QIMPenStroke &s )
50{
51 clear();
52 //qDebug( "copy strokes %d", s.links.count() );
53 startPoint = s.startPoint;
54 lastPoint = s.lastPoint;
55 links = s.links.copy();
56
57 return *this;
58}
59
60void QIMPenStroke::clear()
61{
62 startPoint = QPoint(0,0);
63 lastPoint = QPoint( 0, 0 );
64 links.resize( 0 );
65 tsig.resize( 0 );
66 dsig.resize( 0 );
67 asig.resize( 0 );
68}
69
70/*!
71 Begin inputting a new stroke.
72*/
73void QIMPenStroke::beginInput( QPoint p )
74{
75 clear();
76 startPoint = p;
77 bounding = QRect();
78 internalAddPoint( p );
79}
80
81/*!
82 Add a point to the stroke's shape.
83 Returns TRUE if the point was successfully added.
84*/
85bool QIMPenStroke::addPoint( QPoint p )
86{
87 if ( links.count() > 500 ) // sanity check (that the user is sane).
88 return FALSE;
89
90 int dx = p.x() - lastPoint.x();
91 int dy = p.y() - lastPoint.y();
92 if ( QABS( dx ) > 1 || QABS( dy ) > 1 ) {
93 // The point is not adjacent to the previous point, so we fill
94 // in with a straight line. Some kind of non-linear
95 // interpolation might be better.
96 int x = lastPoint.x();
97 int y = lastPoint.y();
98 int ix = 1;
99 int iy = 1;
100 if ( dx < 0 ) {
101 ix = -1;
102 dx = -dx;
103 }
104 if ( dy < 0 ) {
105 iy = -1;
106 dy = -dy;
107 }
108 int d = 0;
109 if ( dx < dy ) {
110 d = dx;
111 do {
112 y += iy;
113 d += dx;
114 if ( d > dy ) {
115 x += ix;
116 d -= dy;
117 }
118 internalAddPoint( QPoint( x, y ) );
119 } while ( y != p.y() );
120 } else {
121 d = dy;
122 do {
123 x += ix;
124 d += dy;
125 if ( d > dx ) {
126 y += iy;
127 d -= dx;
128 }
129 internalAddPoint( QPoint( x, y ) );
130 } while ( x != p.x() );
131 }
132 } else {
133 internalAddPoint( p );
134 }
135
136 return TRUE;
137}
138
139/*!
140 Finish inputting a stroke.
141*/
142void QIMPenStroke::endInput()
143{
144 if ( links.count() < 3 ) {
145 QIMPenGlyphLink gl;
146 links.resize(1);
147 gl.dx = 1;
148 gl.dy = 0;
149 links[0] = gl;
150 }
151
152 //qDebug("Points: %d", links.count() );
153}
154
155/*!
156 Return an indicator of the closeness of this stroke to \a pen.
157 Lower value is better.
158*/
159unsigned int QIMPenStroke::match( QIMPenStroke *pen )
160{
161 double lratio;
162
163 if ( links.count() > pen->links.count() )
164 lratio = (links.count()+2) / (pen->links.count()+2);
165 else
166 lratio = (pen->links.count()+2) / (links.count()+2);
167
168 lratio -= 1.0;
169
170 if ( lratio > 2.0 ) {
171#ifdef DEBUG_QIMPEN
172 qDebug( "stroke length too different" );
173#endif
174 return 400000;
175 }
176
177 createSignatures();
178 pen->createSignatures();
179
180 // Starting point offset
181 int vdiff = QABS(startPoint.y() - pen->startPoint.y());
182
183 // Insanely offset?
184 if ( vdiff > 18 ) {
185 return 400000;
186 }
187
188 vdiff -= 4;
189 if ( vdiff < 0 )
190 vdiff = 0;
191
192 // Ending point offset
193 int evdiff = QABS(lastPoint.y() - pen->lastPoint.y());
194 // Insanely offset?
195 if ( evdiff > 20 ) {
196 return 400000;
197 }
198
199 evdiff -= 5;
200 if ( evdiff < 0 )
201 evdiff = 0;
202
203 // do a correlation with the three available signatures.
204 int err1 = INT_MAX;
205 int err2 = INT_MAX;
206 int err3 = INT_MAX;
207
208 // base has extra points at the start and end to enable
209 // correlation of a sliding window with the pen supplied.
210 QArray<int> base = createBase( tsig, 2 );
211 for ( int i = 0; i < 4; i++ ) {
212 int e = calcError( base, pen->tsig, i, TRUE );
213 if ( e < err1 )
214 err1 = e;
215 }
216 if ( err1 > 40 ) { // no need for more matching
217#ifdef DEBUG_QIMPEN
218 qDebug( "tsig too great: %d", err1 );
219#endif
220 return 400000;
221 }
222
223 // maybe a sliding window is worthwhile for these too.
224 err2 = calcError( dsig, pen->dsig, 0, FALSE );
225 if ( err2 > 100 ) {
226#ifdef DEBUG_QIMPEN
227 qDebug( "dsig too great: %d", err2 );
228#endif
229 return 400000;
230 }
231
232 err3 = calcError( asig, pen->asig, 0, TRUE );
233 if ( err3 > 60 ) {
234#ifdef DEBUG_QIMPEN
235 qDebug( "asig too great: %d", err3 );
236#endif
237 return 400000;
238 }
239
240 // Some magic numbers here - the addition reduces the weighting of
241 // the error and compensates for the different error scales. I
242 // consider the tangent signature to be the best indicator, so it
243 // has the most weight. This ain't rocket science.
244 // Basically, these numbers are the tuning factors.
245 unsigned int err = (err1+1) * ( err2 + 60 ) * ( err3 + 20 ) +
246 vdiff * 1000 + evdiff * 500 +
247 (unsigned int)(lratio * 5000.0);
248
249#ifdef DEBUG_QIMPEN
250 qDebug( "err %d ( %d, %d, %d, %d)", err, err1, err2, err3, vdiff );
251#endif
252
253 return err;
254}
255
256/*!
257 Return the bounding rect of this stroke.
258*/
259QRect QIMPenStroke::boundingRect()
260{
261 if ( !bounding.isValid() ) {
262 int x = startPoint.x();
263 int y = startPoint.y();
264 bounding = QRect( x, y, 1, 1 );
265
266 for ( unsigned i = 0; i < links.count(); i++ ) {
267 x += links[i].dx;
268 y += links[i].dy;
269 if ( x < bounding.left() )
270 bounding.setLeft( x );
271 if ( x > bounding.right() )
272 bounding.setRight( x );
273 if ( y < bounding.top() )
274 bounding.setTop( y );
275 if ( y > bounding.bottom() )
276 bounding.setBottom( y );
277 }
278 }
279
280 return bounding;
281}
282
283
284/*!
285 Perform a correlation of the supplied arrays. \a base should have
286 win.count() + 2 * off points to enable sliding \a win over the
287 \a base data. If \a t is TRUE, the comparison takes into account
288 the circular nature of the angular data.
289 Returns the best (lowest error) match.
290*/
291
292int QIMPenStroke::calcError( const QArray<int> &base,
293 const QArray<int> &win, int off, bool t )
294{
295 int err = 0;
296
297 for ( unsigned i = 0; i < win.count(); i++ ) {
298 int d = QABS( base[i+off] - win[i] );
299 if ( t && d > 128 )
300 d -= 256;
301 err += QABS( d );
302 }
303
304 err /= win.count();
305
306 return err;
307}
308
309/*!
310 Creates signatures used in matching if not already created.
311*/
312void QIMPenStroke::createSignatures()
313{
314 if ( tsig.isEmpty() )
315 createTanSignature();
316 if ( asig.isEmpty() )
317 createAngleSignature();
318 if ( dsig.isEmpty() )
319 createDistSignature();
320}
321
322/*!
323 Create a signature of the tangents to the user's stroke.
324*/
325void QIMPenStroke::createTanSignature()
326{
327 int dist = 5; // number of points to include in calculation
328 if ( (int)links.count() <= dist ) {
329 tsig.resize(1);
330 int dx = 0;
331 int dy = 0;
332 for ( unsigned j = 0; j < links.count(); j++ ) {
333 dx += links[j].dx;
334 dy += links[j].dy;
335 }
336 tsig[0] = arcTan( dy, dx );
337 } else {
338 tsig.resize( (links.count()-dist+1) / 2 );
339 int idx = 0;
340 for ( unsigned i = 0; i < links.count() - dist; i += 2 ) {
341 int dx = 0;
342 int dy = 0;
343 for ( int j = 0; j < dist; j++ ) {
344 dx += links[i+j].dx;
345 dy += links[i+j].dy;
346 }
347 tsig[idx++] = arcTan( dy, dx );
348 }
349 }
350
351 tsig = scale( tsig, QIMPEN_CORRELATION_POINTS, TRUE );
352// smooth(tsig);
353}
354
355/*!
356 Create a signature of the change in angle.
357*/
358void QIMPenStroke::createAngleSignature()
359{
360 QPoint c = calcCenter();
361
362 int dist = 3; // number of points to include in calculation
363 if ( (int)links.count() <= dist ) {
364 asig.resize(1);
365 asig[0] = 1;
366 } else {
367 asig.resize( links.count() );
368 QPoint current(0, 0);
369 int idx = 0;
370 for ( unsigned i = 0; i < links.count(); i++ ) {
371 int dx = c.x() - current.x();
372 int dy = c.y() - current.y();
373 int md = QMAX( QABS(dx), QABS(dy) );
374 if ( md > 5 ) {
375 dx = dx * 5 / md;
376 dy = dy * 5 / md;
377 }
378 asig[idx++] = arcTan( dy, dx );
379 current += QPoint( links[i].dx, links[i].dy );
380 }
381 }
382
383 asig = scale( asig, QIMPEN_CORRELATION_POINTS, TRUE );
384
385/*
386 if ( tsig.isEmpty() )
387 createTanSignature();
388
389 if ( tsig.count() < 5 ) {
390 asig.resize( 1 );
391 asig[0] = 0;
392 } else {
393 asig.resize( tsig.count() - 5 );
394
395 for ( unsigned i = 0; i < asig.count(); i++ ) {
396 asig[i] = QABS(tsig[i] - tsig[i+5]);
397 }
398 }
399*/
400}
401
402/*!
403 Create a signature of the distance from the char's center of gravity
404 to its points.
405*/
406void QIMPenStroke::createDistSignature()
407{
408 dsig.resize( (links.count()+1)/2 );
409 QPoint c = calcCenter();
410 QPoint pt( 0, 0 );
411
412 int minval = INT_MAX;
413 int maxval = 0;
414 int idx = 0;
415 for ( unsigned i = 0; i < links.count(); i += 2 ) {
416 int dx = c.x() - pt.x();
417 int dy = c.y() - pt.y();
418 if ( dx == 0 && dy == 0 )
419 dsig[idx] = 0;
420 else
421 dsig[idx] = dx*dx + dy*dy;
422
423 if ( dsig[idx] > maxval )
424 maxval = dsig[idx];
425 if ( dsig[idx] < minval )
426 minval = dsig[idx];
427 pt.rx() += links[i].dx;
428 pt.ry() += links[i].dy;
429 idx++;
430 }
431
432 // normalise 0-255
433 int div = maxval - minval;
434 if ( div == 0 ) div = 1;
435 for ( unsigned i = 0; i < dsig.count(); i++ ) {
436 dsig[i] = (dsig[i] - minval ) * 255 / div;
437 }
438
439 dsig = scale( dsig, QIMPEN_CORRELATION_POINTS );
440}
441
442
443/*!
444 Scale the points in a array to \a count points.
445 This is braindead at the moment (no smooth scaling) and fixing this is
446 probably one of the simpler ways to improve performance.
447*/
448QArray<int> QIMPenStroke::scale( const QArray<int> &s, unsigned count, bool t )
449{
450 QArray<int> d(count);
451
452 unsigned si = 0;
453 if ( s.count() > count ) {
454 unsigned next = 0;
455 for ( unsigned i = 0; i < count; i++ ) {
456 next = (i+1) * s.count() / count;
457 int maxval = 0;
458 if ( t ) {
459 for ( unsigned j = si; j < next; j++ ) {
460 maxval = s[j] > maxval ? s[j] : maxval;
461 }
462 }
463 int sum = 0;
464 for ( unsigned j = si; j < next; j++ ) {
465 if ( t && maxval - s[j] > 128 )
466 sum += 256;
467 sum += s[j];
468 }
469 d[i] = sum / (next-si);
470 if ( t && d[i] > 256 )
471 d[i] %= 256;
472 si = next;
473 }
474 } else {
475 for ( unsigned i = 0; i < count; i++ ) {
476 si = i * s.count() / count;
477 d[i] = s[si];
478 }
479 }
480
481 return d;
482}
483
484/*!
485 Add another point to the stroke's shape.
486*/
487void QIMPenStroke::internalAddPoint( QPoint p )
488{
489 if ( p == lastPoint )
490 return;
491
492 if ( !lastPoint.isNull() ) {
493 QIMPenGlyphLink gl;
494 gl.dx = p.x() - lastPoint.x();
495 gl.dy = p.y() - lastPoint.y();
496 links.resize( links.size() + 1 ); //### resize by 1 is bad
497 links[links.size() - 1] = gl;
498 }
499
500 lastPoint = p;
501 bounding = QRect();
502}
503
504/*!
505 Calculate the center of gravity of the stroke.
506*/
507QPoint QIMPenStroke::calcCenter()
508{
509 QPoint pt( 0, 0 );
510 int ax = 0;
511 int ay = 0;
512
513 for ( unsigned i = 0; i < links.count(); i++ ) {
514 pt.rx() += links[i].dx;
515 pt.ry() += links[i].dy;
516 ax += pt.x();
517 ay += pt.y();
518 }
519
520 ax /= (int)links.count();
521 ay /= (int)links.count();
522
523 return QPoint( ax, ay );
524}
525
526/*!
527 Calculate the arctan of the lengths supplied.
528 The angle returned is in the range 0-255.
529 \a dy and \a dx MUST be in the range 0-5 - I dont even check :-P
530*/
531int QIMPenStroke::arcTan( int dy, int dx )
532{
533 if ( dx == 0 ) {
534 if ( dy >= 0 )
535 return 64;
536 else
537 return 192;
538 }
539
540 if ( dy == 0 ) {
541 if ( dx >= 0 )
542 return 0;
543 else
544 return 128;
545 }
546
547 static int table[5][5] = {
548 { 32, 19, 13, 10, 8 },
549 { 45, 32, 24, 19, 16 },
550 { 51, 40, 32, 26, 22 },
551 { 54, 45, 37, 32, 27 },
552 { 56, 49, 42, 37, 32 } };
553
554 if ( dy > 0 ) {
555 if ( dx > 0 )
556 return table[dy-1][dx-1];
557 else
558 return 128 - table[dy-1][QABS(dx)-1];
559 } else {
560 if ( dx > 0 )
561 return 256 - table[QABS(dy)-1][dx-1];
562 else
563 return 128 + table[QABS(dy)-1][QABS(dx)-1];
564 }
565
566 return 0;
567}
568
569
570/*!
571 Silly name. Create an array that has \a e points extra at the start and
572 end to enable a sliding correlation to be performed.
573*/
574QArray<int> QIMPenStroke::createBase( const QArray<int> a, int e )
575{
576 QArray<int> ra( a.count() + 2*e );
577
578 for ( int i = 0; i < e; i++ ) {
579 ra[i] = a[e - i - 1];
580 ra[a.count() + i] = a[a.count() - i - 1];
581 }
582 for ( unsigned i = 0; i < a.count(); i++ ) {
583 ra[i+e] = a[i];
584 }
585
586 return ra;
587}
588
589
590/*!
591 Smooth the points in an array. Probably a bad idea.
592*/
593void QIMPenStroke::smooth( QArray<int> &sig)
594{
595 QArray<int> nsig = sig.copy();
596
597 int a;
598 for ( unsigned i = 1; i < sig.count()-2; i++ ) {
599 a = 0;
600 for ( int j = -1; j <= 1; j++ ) {
601 a += sig[ i + j ];
602 }
603 nsig[i] = a / 3;
604 }
605
606 sig = nsig;
607}
608
609/*!
610 Write the character's data to the stream.
611*/
612QDataStream &operator<< (QDataStream &s, const QIMPenStroke &ws)
613{
614 s << ws.startPoint;
615 s << ws.links.count();
616 for ( unsigned i = 0; i < ws.links.count(); i++ ) {
617 s << (Q_INT8)ws.links[i].dx;
618 s << (Q_INT8)ws.links[i].dy;
619 }
620
621 return s;
622}
623
624/*!
625 Read the character's data from the stream.
626*/
627QDataStream &operator>> (QDataStream &s, QIMPenStroke &ws)
628{
629 Q_INT8 i8;
630 s >> ws.startPoint;
631 ws.lastPoint = ws.startPoint;
632 unsigned size;
633 s >> size;
634 ws.links.resize( size );
635 for ( unsigned i = 0; i < size; i++ ) {
636 s >> i8;
637 ws.links[i].dx = i8;
638 s >> i8;
639 ws.links[i].dy = i8;
640 ws.lastPoint += QPoint( ws.links[i].dx, ws.links[i].dy );
641 }
642
643 return s;
644}
645
646
diff --git a/inputmethods/handwriting/qimpenstroke.h b/inputmethods/handwriting/qimpenstroke.h
new file mode 100644
index 0000000..bd5ee0e
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenstroke.h
@@ -0,0 +1,91 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#ifndef QIMPENSTROKE_H_
22#define QIMPENSTROKE_H_
23
24#include <qobject.h>
25#include <qarray.h>
26#include <qlist.h>
27
28struct Q_PACKED QIMPenGlyphLink
29{
30 signed char dx;
31 signed char dy;
32};
33
34class QIMPenStroke
35{
36public:
37 QIMPenStroke();
38 QIMPenStroke( const QIMPenStroke & );
39
40 void clear();
41 bool isEmpty() const { return links.isEmpty(); }
42 unsigned int length() const { return links.count(); }
43 unsigned int match( QIMPenStroke *st );
44 const QArray<QIMPenGlyphLink> &chain() const { return links; }
45 QPoint startingPoint() const { return startPoint; }
46 void setStartingPoint( const QPoint &p ) { startPoint = p; }
47 QRect boundingRect();
48
49 QIMPenStroke &operator=( const QIMPenStroke &s );
50
51 void beginInput( QPoint p );
52 bool addPoint( QPoint p );
53 void endInput();
54
55 QArray<int> sig() { createTanSignature(); return tsig; } // for debugging
56
57protected:
58 void createSignatures();
59 void createTanSignature();
60 void createAngleSignature();
61 void createDistSignature();
62 int calcError( const QArray<int> &base, const QArray<int> &win,
63 int off, bool t );
64 QArray<int> scale( const QArray<int> &s, unsigned count, bool t = FALSE );
65 void internalAddPoint( QPoint p );
66 QPoint calcCenter();
67 int arcTan( int dy, int dx );
68 QArray<int> createBase( const QArray<int> a, int e );
69 void smooth( QArray<int> &);
70
71protected:
72 QPoint startPoint;
73 QPoint lastPoint;
74 QArray<QIMPenGlyphLink> links;
75 QArray<int> tsig;
76 QArray<int> asig;
77 QArray<int> dsig;
78 QRect bounding;
79
80 friend QDataStream &operator<< (QDataStream &, const QIMPenStroke &);
81 friend QDataStream &operator>> (QDataStream &, QIMPenStroke &);
82};
83
84typedef QList<QIMPenStroke> QIMPenStrokeList;
85typedef QListIterator<QIMPenStroke> QIMPenStrokeIterator;
86
87QDataStream & operator<< (QDataStream & s, const QIMPenStroke &ws);
88QDataStream & operator>> (QDataStream & s, const QIMPenStroke &ws);
89
90#endif
91
diff --git a/inputmethods/handwriting/qimpenwidget.cpp b/inputmethods/handwriting/qimpenwidget.cpp
new file mode 100644
index 0000000..8f8f582
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenwidget.cpp
@@ -0,0 +1,446 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include <qapplication.h>
22#include <qinputdialog.h>
23#include <qpainter.h>
24#include <qfile.h>
25#include <qdatastream.h>
26#include <qtimer.h>
27#include "qimpenchar.h"
28#include "qimpenwidget.h"
29
30 #define TITLE_WIDTH30 // ### magic
31
32/*!
33 \class QIMPenWidget qimpenwidget.h
34
35 Draws characters and allows input of characters.
36*/
37
38QIMPenWidget::QIMPenWidget( QWidget *parent )
39 : QWidget( parent )
40{
41 charSets.setAutoDelete( TRUE );
42 inputStroke = 0;
43 outputChar = 0;
44 outputStroke = 0;
45 mode = Waiting;
46 currCharSet = 0;
47 readOnly = FALSE;
48 strokes.setAutoDelete( TRUE );
49
50 timer = new QTimer(this);
51 connect( timer, SIGNAL(timeout()), SLOT(timeout()));
52
53 setBackgroundColor( qApp->palette().color( QPalette::Active,
54 QColorGroup::Base ) );
55 strokeColor = black;
56 setFixedHeight( 75 );
57}
58
59void QIMPenWidget::clear()
60{
61 timer->stop();
62 mode = Waiting;
63 QRect r( dirtyRect );
64 QIMPenStrokeIterator it( strokes );
65 while ( it.current() ) {
66 r |= it.current()->boundingRect();
67 ++it;
68 }
69 outputChar = 0;
70 outputStroke = 0;
71 strokes.clear();
72 if ( !r.isNull() ) {
73 r.moveBy( -2, -2 );
74 r.setSize( r.size() + QSize( 4, 4 ) );
75 repaint( r );
76 } else {
77 repaint();
78 }
79}
80
81void QIMPenWidget::removeStroke()
82{
83 QRect r( dirtyRect );
84 QIMPenStroke *st = strokes.getFirst();
85 QRect strokeRect;
86 if ( st )
87 strokeRect = st->boundingRect();
88 r |= strokeRect;
89 strokes.removeFirst();
90 if ( !r.isNull() ) {
91 r.moveBy( -2, -2 );
92 r.setSize( r.size() + QSize( 4, 4 ) );
93 repaint( r );
94 }
95}
96
97void QIMPenWidget::greyStroke()
98{
99 QRect r( dirtyRect );
100 QIMPenStroke *st = strokes.getLast();
101 QRect strokeRect;
102 if ( st )
103 strokeRect = st->boundingRect();
104 r |= strokeRect;
105 QColor oldCol = strokeColor;
106 strokeColor = gray;
107 if ( !r.isNull() ) {
108 r.moveBy( -2, -2 );
109 r.setSize( r.size() + QSize( 4, 4 ) );
110 repaint( r );
111 }
112 strokeColor = oldCol;
113}
114
115/*!
116 Insert a character set into the list.
117*/
118void QIMPenWidget::insertCharSet( QIMPenCharSet *cs, int stretch, int pos )
119{
120 CharSetEntry *e = new CharSetEntry;
121 e->cs = cs;
122 e->stretch = stretch;
123 if ( pos < 0 )
124 pos = charSets.count();
125 charSets.insert( pos, e );
126 currCharSet = 0;
127 emit changeCharSet( currCharSet );
128 emit changeCharSet( charSets.at(currCharSet)->cs );
129 totalStretch = 0;
130 CharSetEntryIterator it( charSets );
131 for ( ; it.current(); ++it )
132 totalStretch += it.current()->stretch;
133 update();
134}
135
136/*!
137 Remove a character set from the list.
138*/
139void QIMPenWidget::removeCharSet( int pos )
140{
141 if ( pos >= 0 && pos < (int)charSets.count() ) {
142 charSets.remove( pos );
143 currCharSet = 0;
144 if ( charSets.count() ) {
145 emit changeCharSet( currCharSet );
146 emit changeCharSet( charSets.at(currCharSet)->cs );
147 }
148 totalStretch = 0;
149 CharSetEntryIterator it( charSets );
150 for ( ; it.current(); ++it )
151 totalStretch += it.current()->stretch;
152 update();
153 }
154}
155
156void QIMPenWidget::changeCharSet( QIMPenCharSet *cs, int pos )
157{
158 if ( pos >= 0 && pos < (int)charSets.count() ) {
159 CharSetEntry *e = new CharSetEntry;
160 e->cs = cs;
161 e->stretch = charSets.at(pos)->stretch;
162 charSets.remove( pos );
163 charSets.insert( pos, e );
164 if ( pos == currCharSet ) {
165 emit changeCharSet( charSets.at(currCharSet)->cs );
166 }
167 update();
168 }
169}
170
171void QIMPenWidget::clearCharSets()
172{
173 charSets.clear();
174 currCharSet = 0;
175 update();
176}
177
178/*!
179 Display a character. \a speed determines how quickly the character is
180 drawn.
181*/
182void QIMPenWidget::showCharacter( QIMPenChar *ch, int speed )
183{
184 outputChar = 0;
185 outputStroke = 0;
186 strokes.clear();
187 mode = Output;
188 repaint();
189 if ( !ch || ch->isEmpty() ) {
190 mode = Waiting;
191 return;
192 }
193
194 outputChar = ch;
195 outputStroke = outputChar->penStrokes().getFirst();
196 if ( speed < 0 ) speed = 0;
197 if ( speed > 20 ) speed = 20;
198 speed = 50 - speed;
199 pointIndex = 0;
200 strokeIndex = 0;
201 lastPoint = outputStroke->startingPoint();
202 QRect br( outputChar->boundingRect() );
203 lastPoint.setX( (width() - br.width()) / 2 + (lastPoint.x () - br.left()) );
204 QPoint offset = lastPoint - outputStroke->startingPoint();
205 br.moveBy( offset.x(), offset.y() );
206 dirtyRect |= br;
207 timer->start( speed );
208}
209
210/*!
211 Handle drawing/clearing of characters.
212*/
213void QIMPenWidget::timeout()
214{
215 if ( mode == Output ) {
216 const QArray<QIMPenGlyphLink> &chain = outputStroke->chain();
217 if ( pointIndex < chain.count() ) {
218 QPainter paint( this );
219 paint.setBrush( Qt::black );
220 for ( unsigned i = 0; i < 3 && pointIndex < chain.count(); i++ ) {
221 lastPoint.rx() += chain[pointIndex].dx;
222 lastPoint.ry() += chain[pointIndex].dy;
223 pointIndex++;
224 paint.drawRect( lastPoint.x()-1, lastPoint.y()-1, 2, 2 );
225 }
226 }
227 if ( pointIndex >= chain.count() ) {
228 QIMPenStrokeList strokes = outputChar->penStrokes();
229 if ( strokeIndex < (int)strokes.count() - 1 ) {
230 pointIndex = 0;
231 strokeIndex++;
232 outputStroke = strokes.at( strokeIndex );
233 lastPoint = outputChar->startingPoint();
234 QRect br( outputChar->boundingRect() );
235 lastPoint.setX( (width() - br.width()) / 2
236 + (lastPoint.x () - br.left()) );
237 QPoint off = lastPoint - outputChar->startingPoint();
238 lastPoint = outputStroke->startingPoint() + off;
239 } else {
240 timer->stop();
241 mode = Waiting;
242 }
243 }
244 } else if ( mode == Waiting ) {
245 QRect r( dirtyRect );
246 if ( !r.isNull() ) {
247 r.moveBy( -2, -2 );
248 r.setSize( r.size() + QSize( 4, 4 ) );
249 repaint( r );
250 }
251 }
252}
253
254/*!
255 If the point \a p is over one of the character set titles, switch
256 to the set and return TRUE.
257*/
258bool QIMPenWidget::selectSet( QPoint p )
259{
260 if ( charSets.count() ) {
261 CharSetEntryIterator it( charSets );
262 int spos = 0;
263 int idx = 0;
264 for ( ; it.current(); ++it, idx++ ) {
265 int setWidth = width() * it.current()->stretch / totalStretch;
266 spos += setWidth;
267 if ( p.x() < spos ) {
268 if ( idx != currCharSet ) {
269 currCharSet = idx;
270 update( 0, 0, width(), 12 );
271 emit changeCharSet( currCharSet );
272 emit changeCharSet( charSets.at(currCharSet)->cs );
273 }
274 break;
275 }
276 }
277 }
278
279 return FALSE;
280}
281
282/*!
283 Hopefully returns a sensible size.
284*/
285QSize QIMPenWidget::sizeHint()
286{
287 return QSize( TITLE_WIDTH * charSets.count(), 75 );
288}
289
290void QIMPenWidget::mousePressEvent( QMouseEvent *e )
291{
292 if ( !readOnly && e->button() == LeftButton && mode == Waiting ) {
293 // if selectSet returns false the click was not over the
294 // char set selectors.
295 if ( !selectSet( e->pos() ) ) {
296 // start of character input
297 timer->stop();
298 if ( outputChar ) {
299 outputChar = 0;
300 outputStroke = 0;
301 repaint();
302 }
303 mode = Input;
304 lastPoint = e->pos();
305 emit beginStroke();
306 inputStroke = new QIMPenStroke;
307 strokes.append( inputStroke );
308 inputStroke->beginInput( e->pos() );
309 QPainter paint( this );
310 paint.setBrush( Qt::black );
311 paint.drawRect( lastPoint.x()-1, lastPoint.y()-1, 2, 2 );
312 }
313 }
314}
315
316void QIMPenWidget::mouseReleaseEvent( QMouseEvent *e )
317{
318 if ( !readOnly && e->button() == LeftButton && mode == Input ) {
319 mode = Waiting;
320 inputStroke->endInput();
321 if ( charSets.count() )
322 emit stroke( inputStroke );
323 inputStroke = 0;
324 }
325}
326
327void QIMPenWidget::mouseMoveEvent( QMouseEvent *e )
328{
329 if ( !readOnly && mode == Input ) {
330 int dx = QABS( e->pos().x() - lastPoint.x() );
331 int dy = QABS( e->pos().y() - lastPoint.y() );
332 if ( dx + dy > 1 ) {
333 if ( inputStroke->addPoint( e->pos() ) ) {
334 QPainter paint( this );
335 paint.setPen( Qt::black );
336 paint.setBrush( Qt::black );
337 const QArray<QIMPenGlyphLink> &chain = inputStroke->chain();
338 QPoint p( e->pos() );
339 for ( int i = (int)chain.count()-1; i >= 0; i-- ) {
340 paint.drawRect( p.x()-1, p.y()-1, 2, 2 );
341 p.rx() -= chain[i].dx;
342 p.ry() -= chain[i].dy;
343 if ( p == lastPoint )
344 break;
345 }
346
347 /* ### use this when thick lines work properly on all devices
348 paint.setPen( QPen( Qt::black, 2 ) );
349 paint.drawLine( lastPoint, e->pos() );
350 */
351 }
352 lastPoint = e->pos();
353 }
354 }
355}
356
357void QIMPenWidget::paintEvent( QPaintEvent * )
358{
359 QPainter paint( this );
360
361 // draw guidelines
362 paint.setPen( Qt::gray );
363 paint.drawLine( 0, 0, width(), 0 );
364 int y = height() / 3;
365 paint.drawLine( 0, y, width(), y );
366 y *= 2;
367 paint.setPen( blue );
368 paint.drawLine( 0, y, width(), y );
369 paint.setPen( Qt::gray );
370
371 if ( !charSets.count() )
372 return;
373
374 // draw the character set titles
375 QFont selFont( "helvetica", 8, QFont::Bold );
376 QFont font( "helvetica", 8 );
377 CharSetEntryIterator it( charSets );
378 int spos = 0;
379 for ( ; it.current(); ++it ) {
380 int setWidth = width() * it.current()->stretch / totalStretch;
381 spos += setWidth;
382 if ( it.current() != charSets.getLast() ) {
383 paint.drawLine( spos, 0, spos, 5 );
384 paint.drawLine( spos, height()-1, spos, height()-6 );
385 }
386 paint.setFont( font );
387 int w = paint.fontMetrics().width( it.current()->cs->title() );
388 int tpos = spos - setWidth / 2;
389 paint.drawText( tpos - w/2, 0, w, 12, QPainter::AlignCenter,
390 it.current()->cs->title() );
391 }
392
393 // draw any character that should be displayed when repainted.
394 QPoint off;
395 const QIMPenStrokeList *stk = 0;
396 if ( outputChar && mode == Waiting ) {
397 stk = &outputChar->penStrokes();
398 QPoint p( outputChar->startingPoint() );
399 QRect br( outputChar->boundingRect() );
400 p.setX( (width() - br.width()) / 2 + (p.x () - br.left()) );
401 off = p - outputChar->startingPoint();
402 } else if ( mode == Waiting ) {
403 stk = &strokes;
404 strokeColor = gray;
405 }
406
407 if ( stk && !stk->isEmpty() ) {
408 paint.setPen( strokeColor );
409 paint.setBrush( strokeColor );
410 QIMPenStrokeIterator it( *stk );
411 while ( it.current() ) {
412 QPoint p = it.current()->startingPoint() + off;
413 paint.drawRect( p.x()-1, p.y()-1, 2, 2 );
414 const QArray<QIMPenGlyphLink> &chain = it.current()->chain();
415 for ( unsigned i = 0; i < chain.count(); i++ ) {
416 p.rx() += chain[i].dx;
417 p.ry() += chain[i].dy;
418 paint.drawRect( p.x()-1, p.y()-1, 2, 2 );
419 }
420 ++it;
421 if ( it.atLast() && mode == Waiting )
422 strokeColor = black;
423 }
424 }
425
426 dirtyRect = QRect();
427
428 // debug
429/*
430 if ( input ) {
431 QArray<int> sig = input->sig();
432 for ( unsigned i = 0; i < sig.count(); i++ ) {
433 paint.drawPoint( 200 + i, height()/2 - sig[i] / 8 );
434 }
435 }
436*/
437}
438
439void QIMPenWidget::resizeEvent( QResizeEvent *e )
440{
441 if ( mode == Output )
442 showCharacter( outputChar, 0 );
443
444 QWidget::resizeEvent( e );
445}
446
diff --git a/inputmethods/handwriting/qimpenwidget.h b/inputmethods/handwriting/qimpenwidget.h
new file mode 100644
index 0000000..98d7f5c
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenwidget.h
@@ -0,0 +1,88 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include <qwidget.h>
22#include <qlist.h>
23#include "qimpenchar.h"
24
25class QIMPenWidget : public QWidget
26{
27 Q_OBJECT
28public:
29 QIMPenWidget( QWidget *parent );
30
31 void clear();
32 void greyStroke();
33 void setReadOnly( bool r ) { readOnly = r; }
34
35 void insertCharSet( QIMPenCharSet *cs, int stretch=1, int pos=-1 );
36 void removeCharSet( int );
37 void changeCharSet( QIMPenCharSet *cs, int pos );
38 void clearCharSets();
39 void showCharacter( QIMPenChar *, int speed = 10 );
40 virtual QSize sizeHint();
41
42public slots:
43 void removeStroke();
44
45signals:
46 void changeCharSet( QIMPenCharSet *cs );
47 void changeCharSet( int );
48 void beginStroke();
49 void stroke( QIMPenStroke *ch );
50
51protected slots:
52 void timeout();
53
54protected:
55 enum Mode { Waiting, Input, Output };
56 bool selectSet( QPoint );
57 virtual void mousePressEvent( QMouseEvent *e );
58 virtual void mouseReleaseEvent( QMouseEvent *e );
59 virtual void mouseMoveEvent( QMouseEvent *e );
60 virtual void paintEvent( QPaintEvent *e );
61 virtual void resizeEvent( QResizeEvent *e );
62
63 struct CharSetEntry {
64 QIMPenCharSet *cs;
65 int stretch;
66 };
67 typedef QList<CharSetEntry> CharSetEntryList;
68 typedef QListIterator<CharSetEntry> CharSetEntryIterator;
69
70protected:
71 Mode mode;
72 bool autoHide;
73 bool readOnly;
74 QPoint lastPoint;
75 unsigned pointIndex;
76 int strokeIndex;
77 int currCharSet;
78 QTimer *timer;
79 QColor strokeColor;
80 QRect dirtyRect;
81 QIMPenChar *outputChar;
82 QIMPenStroke *outputStroke;
83 QIMPenStroke *inputStroke;
84 QIMPenStrokeList strokes;
85 CharSetEntryList charSets;
86 int totalStretch;
87};
88
diff --git a/inputmethods/handwriting/qimpenwordpick.cpp b/inputmethods/handwriting/qimpenwordpick.cpp
new file mode 100644
index 0000000..8ee103d
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenwordpick.cpp
@@ -0,0 +1,113 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include <qpainter.h>
22#include "qimpenwordpick.h"
23
24QIMPenWordPick::QIMPenWordPick( QWidget *parent, const char *name, WFlags f )
25 : QFrame( parent, name, f )
26{
27 clickWord = -1;
28 setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) );
29}
30
31void QIMPenWordPick::clear()
32{
33 words.clear();
34 repaint();
35}
36
37QSize QIMPenWordPick::sizeHint() const
38{
39 return QSize( -1, font().pixelSize()+2 );
40}
41
42void QIMPenWordPick::setWords( const QIMPenMatch::MatchWordList &w )
43{
44 words.clear();
45 QListIterator<QIMPenMatch::MatchWord> it( w );
46 for ( ; it.current(); ++it ) {
47 words.append( it.current()->word );
48 }
49 repaint();
50}
51
52int QIMPenWordPick::onWord( QPoint p )
53{
54 int x = 2;
55 int idx = 0;
56 for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it ) {
57 QString word = *it;
58 int w = fontMetrics().width( word );
59 if ( x + w > width() )
60 break;
61 if ( p.x() > x-2 && p.x() < x + w + 2 )
62 return idx;
63 x += w + 5;
64 if ( !idx )
65 x += 3;
66 idx++;
67 }
68
69 return -1;
70}
71
72void QIMPenWordPick::paintEvent( QPaintEvent * )
73{
74 QPainter p(this);
75 int x = 2;
76 int h = p.fontMetrics().ascent() + 1;
77 int idx = 0;
78 for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it ) {
79 QString word = *it;
80 int w = p.fontMetrics().width( word );
81 if ( x + w > width() )
82 break;
83 if ( idx == clickWord ) {
84 p.fillRect( x, 0, w, height(), black );
85 p.setPen( white );
86 } else {
87 p.setPen( colorGroup().text() );
88 }
89 p.drawText( x, h, word );
90 x += w + 5;
91 if ( !idx )
92 x += 3;
93 idx++;
94 }
95}
96
97void QIMPenWordPick::mousePressEvent( QMouseEvent *e )
98{
99 clickWord = onWord( e->pos() );
100 repaint();
101}
102
103void QIMPenWordPick::mouseReleaseEvent( QMouseEvent *e )
104{
105 int wordIdx = onWord( e->pos() );
106 if ( wordIdx >= 0 && wordIdx == clickWord ) {
107 //qDebug( "Clicked %s", words[wordIdx].latin1() );
108 emit wordClicked( words[wordIdx] );
109 }
110 clickWord = -1;
111 repaint();
112}
113
diff --git a/inputmethods/handwriting/qimpenwordpick.h b/inputmethods/handwriting/qimpenwordpick.h
new file mode 100644
index 0000000..376288e
--- a/dev/null
+++ b/inputmethods/handwriting/qimpenwordpick.h
@@ -0,0 +1,49 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include <qframe.h>
22#include "qimpenmatch.h"
23
24class QIMPenWordPick : public QFrame
25{
26 Q_OBJECT
27public:
28 QIMPenWordPick( QWidget *parent = 0, const char *name = 0, WFlags f = 0 );
29
30 void clear();
31 virtual QSize sizeHint() const;
32
33public slots:
34 void setWords( const QIMPenMatch::MatchWordList &w );
35
36signals:
37 void wordClicked( const QString & );
38
39protected:
40 int onWord( QPoint p );
41 virtual void paintEvent( QPaintEvent * );
42 virtual void mousePressEvent( QMouseEvent * );
43 virtual void mouseReleaseEvent( QMouseEvent * );
44
45private:
46 QStringList words;
47 int clickWord;
48};
49
diff --git a/inputmethods/handwriting/qpe-handwriting.control b/inputmethods/handwriting/qpe-handwriting.control
new file mode 100644
index 0000000..f1648c6
--- a/dev/null
+++ b/inputmethods/handwriting/qpe-handwriting.control
@@ -0,0 +1,9 @@
1Files: plugins/inputmethods/libqhandwriting.so*
2Priority: optional
3Section: qpe/inputmethods
4Maintainer: Martin Jones <mjones@trolltech.com>
5Architecture: arm
6Version: $QPE_VERSION-3
7Depends: qpe-base ($QPE_VERSION)
8Description: Handwriting input method
9 Handwriting recognition input method for the Qtopia environment.
diff --git a/inputmethods/handwriting/qpe-handwriting.postinst b/inputmethods/handwriting/qpe-handwriting.postinst
new file mode 100755
index 0000000..c254b01
--- a/dev/null
+++ b/inputmethods/handwriting/qpe-handwriting.postinst
@@ -0,0 +1,2 @@
1#!/bin/sh
2/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadInputMethods()"
diff --git a/inputmethods/handwriting/qpe-handwriting.postrm b/inputmethods/handwriting/qpe-handwriting.postrm
new file mode 100755
index 0000000..c254b01
--- a/dev/null
+++ b/inputmethods/handwriting/qpe-handwriting.postrm
@@ -0,0 +1,2 @@
1#!/bin/sh
2/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadInputMethods()"
diff --git a/inputmethods/keyboard/.cvsignore b/inputmethods/keyboard/.cvsignore
new file mode 100644
index 0000000..edfa921
--- a/dev/null
+++ b/inputmethods/keyboard/.cvsignore
@@ -0,0 +1,3 @@
1moc_*
2*.moc
3Makefile
diff --git a/inputmethods/keyboard/Makefile.in b/inputmethods/keyboard/Makefile.in
new file mode 100644
index 0000000..3631807
--- a/dev/null
+++ b/inputmethods/keyboard/Makefile.in
@@ -0,0 +1,151 @@
1#############################################################################
2
3####### Compiler, tools and options
4
5 CXX =$(SYSCONF_CXX) $(QT_CXX_MT)
6 CXXFLAGS=$(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB)
7 CC =$(SYSCONF_CC) $(QT_C_MT)
8 CFLAGS =$(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB)
9 INCPATH =-I$(QPEDIR)/include
10 LFLAGS =$(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
11 LIBS =$(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP)
12 MOC =$(SYSCONF_MOC)
13 UIC =$(SYSCONF_UIC)
14
15####### Target
16
17DESTDIR = ../../plugins/inputmethods/
18VER_MAJ = 1
19VER_MIN = 0
20VER_PATCH = 0
21 TARGET= qkeyboard
22TARGET1 = lib$(TARGET).so.$(VER_MAJ)
23
24####### Files
25
26 HEADERS =keyboard.h \
27 ../pickboard/pickboardcfg.h \
28 ../pickboard/pickboardpicks.h \
29 keyboardimpl.h
30 SOURCES =keyboard.cpp \
31 ../pickboard/pickboardcfg.cpp \
32 ../pickboard/pickboardpicks.cpp \
33 keyboardimpl.cpp
34 OBJECTS =keyboard.o \
35 ../pickboard/pickboardcfg.o \
36 ../pickboard/pickboardpicks.o \
37 keyboardimpl.o
38INTERFACES =
39UICDECLS =
40UICIMPLS =
41 SRCMOC =moc_keyboard.cpp \
42 ../pickboard/moc_pickboardcfg.cpp \
43 ../pickboard/moc_pickboardpicks.cpp
44 OBJMOC =moc_keyboard.o \
45 ../pickboard/moc_pickboardcfg.o \
46 ../pickboard/moc_pickboardpicks.o
47
48
49####### Implicit rules
50
51.SUFFIXES: .cpp .cxx .cc .C .c
52
53.cpp.o:
54 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
55
56.cxx.o:
57 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
58
59.cc.o:
60 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
61
62.C.o:
63 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
64
65.c.o:
66 $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
67
68####### Build rules
69
70
71all: $(DESTDIR)$(SYSCONF_LINK_TARGET)
72
73$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
74 $(SYSCONF_LINK_LIB)
75
76moc: $(SRCMOC)
77
78tmake:
79 tmake keyboard.pro
80
81clean:
82 -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
83 -rm -f *~ core
84 -rm -f allmoc.cpp
85
86####### Extension Modules
87
88listpromodules:
89 @echo
90
91listallmodules:
92 @echo
93
94listaddonpromodules:
95 @echo
96
97listaddonentmodules:
98 @echo
99
100
101REQUIRES=
102
103####### Sub-libraries
104
105
106###### Combined headers
107
108
109
110####### Compile
111
112keyboard.o: keyboard.cpp \
113 keyboard.h \
114 ../pickboard/pickboardcfg.h \
115 ../pickboard/pickboardpicks.h
116
117../pickboard/pickboardcfg.o: ../pickboard/pickboardcfg.cpp \
118 ../pickboard/pickboardcfg.h \
119 ../pickboard/pickboardpicks.h
120
121../pickboard/pickboardpicks.o: ../pickboard/pickboardpicks.cpp \
122 ../pickboard/pickboardpicks.h \
123 ../pickboard/pickboardcfg.h
124
125keyboardimpl.o: keyboardimpl.cpp \
126 keyboard.h \
127 ../pickboard/pickboardcfg.h \
128 ../pickboard/pickboardpicks.h \
129 keyboardimpl.h
130
131moc_keyboard.o: moc_keyboard.cpp \
132 keyboard.h \
133 ../pickboard/pickboardcfg.h \
134 ../pickboard/pickboardpicks.h
135
136../pickboard/moc_pickboardcfg.o: ../pickboard/moc_pickboardcfg.cpp \
137 ../pickboard/pickboardcfg.h
138
139../pickboard/moc_pickboardpicks.o: ../pickboard/moc_pickboardpicks.cpp \
140 ../pickboard/pickboardpicks.h
141
142moc_keyboard.cpp: keyboard.h
143 $(MOC) keyboard.h -o moc_keyboard.cpp
144
145../pickboard/moc_pickboardcfg.cpp: ../pickboard/pickboardcfg.h
146 $(MOC) ../pickboard/pickboardcfg.h -o ../pickboard/moc_pickboardcfg.cpp
147
148../pickboard/moc_pickboardpicks.cpp: ../pickboard/pickboardpicks.h
149 $(MOC) ../pickboard/pickboardpicks.h -o ../pickboard/moc_pickboardpicks.cpp
150
151
diff --git a/inputmethods/keyboard/keyboard.cpp b/inputmethods/keyboard/keyboard.cpp
new file mode 100644
index 0000000..9dd24e4
--- a/dev/null
+++ b/inputmethods/keyboard/keyboard.cpp
@@ -0,0 +1,794 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "keyboard.h"
22
23#include <qpe/global.h>
24
25#include <qwindowsystem_qws.h>
26#include <qpainter.h>
27#include <qfontmetrics.h>
28#include <qtimer.h>
29#include <ctype.h>
30
31
32#define USE_SMALL_BACKSPACE
33
34Keyboard::Keyboard(QWidget* parent, const char* name, WFlags f) :
35 QFrame(parent, name, f), shift(FALSE), lock(FALSE), ctrl(FALSE),
36 alt(FALSE), useLargeKeys(TRUE), useOptiKeys(0), pressedKey(-1),
37 unicode(-1), qkeycode(0), modifiers(0)
38{
39 // setPalette(QPalette(QColor(240,240,230))); // Beige!
40 // setFont( QFont( "Helvetica", 8 ) );
41// setPalette(QPalette(QColor(200,200,200))); // Gray
42 setPalette(QPalette(QColor(220,220,220))); // Gray
43
44 picks = new KeyboardPicks( this );
45 picks->setFont( QFont( "smallsmooth", 9 ) );
46 setFont( QFont( "smallsmooth", 9 ) );
47 picks->initialise();
48 QObject::connect( picks, SIGNAL(key(ushort,ushort,ushort,bool,bool) ),
49 this, SIGNAL(key(ushort,ushort,ushort,bool,bool)) );
50
51 repeatTimer = new QTimer( this );
52 connect( repeatTimer, SIGNAL(timeout()), this, SLOT(repeat()) );
53}
54
55void Keyboard::resizeEvent(QResizeEvent*)
56{
57 int ph = picks->sizeHint().height();
58 picks->setGeometry( 0, 0, width(), ph );
59 keyHeight = (height()-ph)/5;
60 int nk;
61 if ( useOptiKeys ) {
62 nk = 15;
63 } else if ( useLargeKeys ) {
64 nk = 15;
65 } else {
66 nk = 19;
67 }
68 defaultKeyWidth = width()/nk;
69 xoffs = (width()-defaultKeyWidth*nk)/2;
70}
71
72void KeyboardPicks::initialise()
73{
74 setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
75 mode = 0;
76 dc = new KeyboardConfig(this);
77 configs.append(dc);
78}
79
80QSize KeyboardPicks::sizeHint() const
81{
82 return QSize(240,fontMetrics().lineSpacing());
83}
84
85
86void KeyboardConfig::generateText(const QString &s)
87{
88#if defined(Q_WS_QWS) || defined(_WS_QWS_)
89 for (int i=0; i<(int)backspaces; i++) {
90 parent->emitKey( 0, Qt::Key_Backspace, 0, true, false );
91 parent->emitKey( 0, Qt::Key_Backspace, 0, false, false );
92 }
93 for (int i=0; i<(int)s.length(); i++) {
94 parent->emitKey( s[i].unicode(), 0, 0, true, false );
95 parent->emitKey( s[i].unicode(), 0, 0, false, false );
96 }
97 parent->emitKey( 0, Qt::Key_Space, 0, true, false );
98 parent->emitKey( 0, Qt::Key_Space, 0, false, false );
99 backspaces = 0;
100#endif
101}
102
103
104//PC keyboard layout and scancodes
105
106/*
107 Format: length, code, length, code, ..., 0
108
109 length is measured in half the width of a standard key.
110 If code < 0x80 we have length/2 consecutive standard keys,
111 starting with scancode code.
112
113 Special keys are hardcoded, one at a time, with length of key
114 and code >= 0x80, these are NOT standard PC scancodes, but are looked
115 up in specialM[]. (The special keys are not keymappable.)
116
117 */
118
119static const uchar * const keyboard_opti[5] = {
120 (const uchar *const) "\001\223\003\240\002\20\002\41\002\26\002\62\002\56\002\45\002\54\003\200\001\223\002\226\002\235\002\234\002\236",
121 (const uchar *const) "\001\223\003\201\004\207\002\30\002\24\002\43\004\207\003\203\001\223\006\002\002\065",
122 (const uchar *const) "\001\223\003\202\002\60\002\37\002\23\002\22\002\36\002\21\002\55\003\203\001\223\006\005\002\055",
123 (const uchar *const) "\001\223\003\205\004\207\002\27\002\61\002\40\004\207\003\204\001\223\006\010\002\014",
124 (const uchar *const) "\001\223\003\206\002\44\002\31\002\57\002\42\002\46\002\25\002\207\003\204\001\223\002\013\002\064\002\015\002\230"
125};
126
127
128static const uchar * const keyboard_standard[5] = {
129
130#ifdef USE_SMALL_BACKSPACE
131 (const uchar *const)"\002\240\002`\0021\0022\0023\0024\0025\0026\0027\0028\0029\0020\002-\002=\002\200\002\223\002\215\002\216\002\217",
132#else
133 (const uchar *const)"\002\051\0021\0022\0023\0024\0025\0026\0027\0028\0029\0020\002-\002=\004\200\002\223\002\215\002\216\002\217",
134#endif
135 //~ + 123...+ BACKSPACE //+ INSERT + HOME + PGUP
136
137 (const uchar *const)"\003\201\002q\002w\002e\002r\002t\002y\002u\002i\002o\002p\002[\002]\002\\\001\224\002\223\002\221\002\220\002\222",
138 //TAB + qwerty.. + backslash //+ DEL + END + PGDN
139
140 (const uchar *const)"\004\202\002a\002s\002d\002f\002g\002h\002j\002k\002l\002;\002'\004\203",
141 //CAPS + asdf.. + RETURN
142
143 (const uchar *const)"\005\204\002z\002x\002c\002v\002b\002n\002m\002,\002.\002/\005\204\002\223\002\223\002\211",
144 //SHIFT + zxcv... //+ UP
145
146 (const uchar *const)"\003\205\003\206\022\207\003\206\003\205\002\223\002\212\002\213\002\214"
147 //CTRL + ALT + SPACE //+ LEFT + DOWN + RIGHT
148
149};
150
151
152struct ShiftMap {
153 char normal;
154 char shifted;
155};
156
157
158static const ShiftMap shiftMap[] = {
159 { '`', '~' },
160 { '1', '!' },
161 { '2', '@' },
162 { '3', '#' },
163 { '4', '$' },
164 { '5', '%' },
165 { '6', '^' },
166 { '7', '&' },
167 { '8', '*' },
168 { '9', '(' },
169 { '0', ')' },
170 { '-', '_' },
171 { '=', '+' },
172 { '\\', '|' },
173 { '[', '{' },
174 { ']', '}' },
175 { ';', ':' },
176 { '\'', '"' },
177 { ',', '<' },
178 { '.', '>' },
179 { '/', '?' }
180};
181
182
183/* XPM */
184static const char * const uparrow_xpm[]={
185"9 9 2 1",
186"a c #000000",
187". c None",
188".........",
189"....a....",
190"...aaa...",
191"..aaaaa..",
192"....a....",
193"....a....",
194"....a....",
195"....a....",
196"........."};
197/* XPM */
198static const char * const leftarrow_xpm[]={
199"9 9 2 1",
200"a c #000000",
201". c None",
202".........",
203".........",
204"...a.....",
205"..aa.....",
206".aaaaaaa.",
207"..aa.....",
208"...a.....",
209".........",
210"........."};
211/* XPM */
212static const char * const downarrow_xpm[]={
213"9 9 2 1",
214"a c #000000",
215". c None",
216".........",
217"....a....",
218"....a....",
219"....a....",
220"....a....",
221"..aaaaa..",
222"...aaa...",
223"....a....",
224"........."};
225/* XPM */
226static const char * const rightarrow_xpm[]={
227"9 9 2 1",
228"a c #000000",
229". c None",
230".........",
231".........",
232".....a...",
233".....aa..",
234".aaaaaaa.",
235".....aa..",
236".....a...",
237".........",
238"........."};
239/* XPM */
240static const char * const insert_xpm[]={
241"9 9 2 1",
242"a c #000000",
243". c None",
244".........",
245"a........",
246"a.aaa.aaa",
247"a.a.a.a..",
248"a.a.a..a.",
249"a.a.a...a",
250"a.a.a.aaa",
251".........",
252"........."};
253/* XPM */
254static const char * const delete_xpm[]={
255"9 9 2 1",
256"a c #000000",
257". c None",
258".........",
259"aa......a",
260"a.a.aaa.a",
261"a.a.a.a.a",
262"a.a.aaa.a.",
263"a.a.a...a",
264"aaa.aaa.a",
265".........",
266"........."};
267/* XPM */
268static const char * const home_xpm[]={
269"9 9 2 1",
270"a c #000000",
271". c None",
272"....a....",
273"...a.a...",
274"..a...a..",
275".a.....a.",
276"aa.aaa.aa",
277".a.a.a.a.",
278".a.a.a.a.",
279".aaaaaaa.",
280"........."};
281/* XPM */
282static const char * const end_xpm[]={
283"10 9 2 1",
284"a c #000000",
285". c None",
286"..........",
287"aa.......a",
288"a..aaa.aaa",
289"aa.a.a.a.a",
290"a..a.a.a.a",
291"a..a.a.a.a",
292"aa.a.a.aaa",
293"..........",
294".........."};
295/* XPM */
296static const char * const pageup_xpm[]={
297"9 9 2 1",
298"a c #000000",
299". c None",
300".aaa.aaa.",
301".a.a.a.a.",
302".aaa..aa.",
303".a...aaa.",
304".........",
305".a.a.aaa.",
306".a.a.a.a.",
307".aaa.aaa.",
308".....a..."};
309/* XPM */
310static const char * const pagedown_xpm[]={
311"9 9 2 1",
312"a c #000000",
313". c None",
314".aaa.aaa.",
315".a.a.a.a.",
316".aaa..aa.",
317".a...aaa.",
318".........",
319"...a.....",
320".aaa.aaa.",
321".a.a.a.a.",
322".aaa.a.a."};
323/* XPM */
324static const char * const expand_xpm[]={
325"4 9 2 1",
326"a c #408040",
327". c None",
328"a...",
329"aa..",
330"aaa.",
331"aaaa",
332"aaaa",
333"aaaa",
334"aaa.",
335"aa..",
336"a..."};
337/* XPM */
338#ifdef USE_SMALL_BACKSPACE
339static const char * const backspace_xpm[]={
340"9 9 2 1",
341"a c #000000",
342". c None",
343".........",
344".........",
345"...a.....",
346"..aa.....",
347".aaaaaaaa",
348"..aa.....",
349"...a.....",
350".........",
351"........."};
352#else
353static const char * const backspace_xpm[]={
354"21 9 2 1",
355"a c #000000",
356". c None",
357".....................",
358".....................",
359".....aaa..a..........",
360".a...a..a.a.a.aaa.aaa",
361"aaaa.aaa..aa..aa..a.a",
362".a...a..a.aaa..aa.a.a",
363".....aaaa.a.a.aaa.aa.",
364"..................a..",
365"....................."};
366#endif
367/* XPM */
368static const char * const escape_xpm[]={
369"9 9 2 1",
370"a c #000000",
371". c None",
372".........",
373".........",
374".aa.aa.aa",
375".a..a..a.",
376".aa.aa.a.",
377".a...a.a.",
378".aa.aa.aa",
379".........",
380"........."};
381
382
383enum { BSCode = 0x80, TabCode, CapsCode, RetCode,
384 ShiftCode, CtrlCode, AltCode, SpaceCode, BackSlash,
385 UpCode, LeftCode, DownCode, RightCode, Blank, Expand,
386 Opti, ResetDict,
387 Divide, Multiply, Add, Subtract, Decimal, Equal,
388 Percent, Sqrt, Inverse, Escape };
389
390typedef struct SpecialMap {
391 int qcode;
392 ushort unicode;
393 const char * label;
394 const char * const * xpm;
395};
396
397
398static const SpecialMap specialM[] = {
399 { Qt::Key_Backspace, 8,"<", backspace_xpm },
400 { Qt::Key_Tab, 9,"Tab", NULL },
401 { Qt::Key_CapsLock, 0,"Caps", NULL },
402 { Qt::Key_Return, 13,"Ret", NULL },
403 { Qt::Key_Shift, 0,"Shift", NULL },
404 { Qt::Key_Control, 0,"Ctrl", NULL },
405 { Qt::Key_Alt, 0,"Alt", NULL },
406 { Qt::Key_Space, ' ',"", NULL },
407 { BackSlash, 43,"\\", NULL },
408
409 // Need images?
410 { Qt::Key_Up, 0,"^", uparrow_xpm },
411 { Qt::Key_Left, 0,"<", leftarrow_xpm },
412 { Qt::Key_Down, 0,"v", downarrow_xpm },
413 { Qt::Key_Right, 0,">", rightarrow_xpm },
414 { Qt::Key_Insert, 0,"I", insert_xpm },
415 { Qt::Key_Home, 0,"H", home_xpm },
416 { Qt::Key_PageUp, 0,"U", pageup_xpm },
417 { Qt::Key_End, 0,"E", end_xpm },
418 { Qt::Key_Delete, 0,"X", delete_xpm },
419 { Qt::Key_PageDown, 0,"D", pagedown_xpm },
420 { Blank, 0," ", NULL },
421 { Expand, 0,"->", expand_xpm },
422 { Opti, 0,"#", NULL },
423 { ResetDict, 0,"R", NULL },
424
425 // number pad stuff
426 { Divide, 0,"/", NULL },
427 { Multiply, 0,"*", NULL },
428 { Add, 0,"+", NULL },
429 { Subtract, 0,"-", NULL },
430 { Decimal, 0,".", NULL },
431 { Equal, 0,"=", NULL },
432 { Percent, 0,"%", NULL },
433 { Sqrt, 0, "^1/2", NULL },
434 { Inverse, 0, "1/x", NULL },
435
436 { Escape, 27, "ESC", escape_xpm }
437};
438
439
440static int keycode( int i2, int j, const uchar **keyboard )
441{
442 if ( j <0 || j >= 5 )
443 return 0;
444
445 const uchar *row = keyboard[j];
446
447 while ( *row && *row <= i2 ) {
448 i2 -= *row;
449 row += 2;
450 }
451
452 if ( !*row ) return 0;
453
454 int k;
455 if ( row[1] >= 0x80 ) {
456 k = row[1];
457 } else {
458 k = row[1]+i2/2;
459 }
460
461 return k;
462}
463
464
465/*
466 return scancode and width of first key in row \a j if \a j >= 0,
467 or next key on current row if \a j < 0.
468
469*/
470
471int Keyboard::getKey( int &w, int j ) {
472 static const uchar *row = 0;
473 static int key_i = 0;
474 static int scancode = 0;
475 static int half = 0;
476
477 if ( j >= 0 && j < 5 ) {
478 if (useOptiKeys)
479 row = keyboard_opti[j];
480 else
481 row = keyboard_standard[j];
482 half=0;
483 }
484
485 if ( !row || !*row ) {
486 return 0;
487 } else if ( row[1] >= 0x80 ) {
488 scancode = row[1];
489 w = (row[0] * w + (half++&1)) / 2;
490 row += 2;
491 return scancode;
492 } else if ( key_i <= 0 ) {
493 key_i = row[0]/2;
494 scancode = row[1];
495 }
496 key_i--;
497 if ( key_i <= 0 )
498 row += 2;
499 return scancode++;
500}
501
502
503void Keyboard::paintEvent(QPaintEvent* e)
504{
505 QPainter painter(this);
506 painter.setClipRect(e->rect());
507 drawKeyboard( painter );
508 picks->dc->draw( &painter );
509}
510
511
512/*
513 Draw the keyboard.
514
515 If key >= 0, only the specified key is drawn.
516*/
517void Keyboard::drawKeyboard( QPainter &p, int key )
518{
519 const bool threeD = FALSE;
520 const QColorGroup& cg = colorGroup();
521 QColor keycolor = // cg.background();
522 QColor(240,240,230); // Beige!
523 QColor keycolor_pressed = cg.mid();
524 QColor keycolor_lo = cg.dark();
525 QColor keycolor_hi = cg.light();
526 QColor textcolor = QColor(0,0,0); // cg.text();
527
528 int margin = threeD ? 1 : 0;
529
530// p.fillRect( 0, , kw-1, keyHeight-2, keycolor_pressed );
531
532 for ( int j = 0; j < 5; j++ ) {
533 int y = j * keyHeight + picks->height() + 1;
534 int x = xoffs;
535 int kw = defaultKeyWidth;
536 int k= getKey( kw, j );
537 while ( k ) {
538 if ( key < 0 || k == key ) {
539 QString s;
540 bool pressed = (k == pressedKey);
541 bool blank = (k == 0223);
542 const char * const * xpm = NULL;
543
544 if ( k >= 0x80 ) {
545 s = specialM[k - 0x80].label;
546
547 xpm = specialM[k - 0x80].xpm;
548
549 if ( k == ShiftCode ) {
550 pressed = shift;
551 } else if ( k == CapsCode ) {
552 pressed = lock;
553 } else if ( k == CtrlCode ) {
554 pressed = ctrl;
555 } else if ( k == AltCode ) {
556 pressed = alt;
557 }
558 } else {
559#if defined(Q_WS_QWS) || defined(_WS_QWS_)
560/*
561 s = QChar( shift^lock ? QWSServer::keyMap()[k].shift_unicode :
562 QWSServer::keyMap()[k].unicode);
563*/
564 // ### Fixme, bad code, needs improving, whole thing needs to
565 // be re-coded to get rid of the way it did things with scancodes etc
566 char shifted = k;
567 if ( !isalpha( k ) ) {
568 for ( unsigned i = 0; i < sizeof(shiftMap)/sizeof(ShiftMap); i++ )
569 if ( shiftMap[i].normal == k )
570 shifted = shiftMap[i].shifted;
571 } else {
572 shifted = toupper( k );
573 }
574 s = QChar( shift^lock ? shifted : k );
575#endif
576 }
577
578 if (!blank) {
579 if ( pressed )
580 p.fillRect( x+margin, y+margin, kw-margin, keyHeight-margin-1, keycolor_pressed );
581 else
582 p.fillRect( x+margin, y+margin, kw-margin, keyHeight-margin-1, keycolor );
583
584 if ( threeD ) {
585 p.setPen(pressed ? keycolor_lo : keycolor_hi);
586 p.drawLine( x, y+1, x, y+keyHeight-2 );
587 p.drawLine( x+1, y+1, x+1, y+keyHeight-3 );
588 p.drawLine( x+1, y+1, x+1+kw-2, y+1 );
589 } else if ( j == 0 ) {
590 p.setPen(pressed ? keycolor_hi : keycolor_lo);
591 p.drawLine( x, y, x+kw, y );
592 }
593
594 // right
595 p.setPen(pressed ? keycolor_hi : keycolor_lo);
596 p.drawLine( x+kw-1, y, x+kw-1, y+keyHeight-2 );
597
598 if ( threeD ) {
599 p.setPen(keycolor_lo.light());
600 p.drawLine( x+kw-2, y+keyHeight-2, x+kw-2, y+1 );
601 p.drawLine( x+kw-2, y+keyHeight-2, x+1, y+keyHeight-2 );
602 }
603
604 if (xpm) {
605 p.drawPixmap( x + 1, y + 2, QPixmap((const char**)xpm) );
606 } else {
607 p.setPen(textcolor);
608 p.drawText( x - 1, y, kw, keyHeight-2, AlignCenter, s );
609 }
610
611 if ( threeD ) {
612 p.setPen(keycolor_hi);
613 p.drawLine( x, y, x+kw-1, y );
614 }
615
616 // bottom
617 p.setPen(keycolor_lo);
618 p.drawLine( x, y+keyHeight-1, x+kw-1, y+keyHeight-1 );
619
620 } else {
621 p.fillRect( x, y, kw, keyHeight, cg.background() );
622 }
623 }
624
625 x += kw;
626 kw = defaultKeyWidth;
627 k = getKey( kw );
628 }
629 }
630}
631
632
633void Keyboard::mousePressEvent(QMouseEvent *e)
634{
635 clearHighlight(); // typing fast?
636
637 int i2 = ((e->x() - xoffs) * 2) / defaultKeyWidth;
638 int j = (e->y() - picks->height()) / keyHeight;
639
640 int k = keycode( i2, j, (const uchar **)((useOptiKeys) ? keyboard_opti : keyboard_standard) );
641 bool need_repaint = FALSE;
642 unicode = -1;
643 qkeycode = 0;
644 if ( k >= 0x80 ) {
645 if ( k == ShiftCode ) {
646 shift = !shift;
647 need_repaint = TRUE;
648 } else if ( k == AltCode ){
649 alt = !alt;
650 need_repaint = TRUE;
651 } else if ( k == CapsCode ) {
652 lock = !lock;
653 need_repaint = TRUE;
654 } else if ( k == CtrlCode ) {
655 ctrl = !ctrl;
656 need_repaint = TRUE;
657 } else if ( k == 0224 /* Expand */ ) {
658 useLargeKeys = !useLargeKeys;
659 resizeEvent(0);
660 repaint( TRUE ); // need it to clear first
661 } else if ( k == 0225 /* Opti/Toggle */ ) {
662 useOptiKeys = !useOptiKeys;
663 resizeEvent(0);
664 repaint( TRUE ); // need it to clear first
665 } else {
666 qkeycode = specialM[ k - 0x80 ].qcode;
667 unicode = specialM[ k - 0x80 ].unicode;
668 }
669 } else {
670#if defined(Q_WS_QWS) || defined(_WS_QWS_)
671/*
672 qk = QWSServer::keyMap()[k].key_code;
673 if ( qk != Key_unknown ) {
674 if ( ctrl )
675 u = QWSServer::keyMap()[k].ctrl_unicode;
676 else if ( shift^lock )
677 u = QWSServer::keyMap()[k].shift_unicode;
678 else
679 u = QWSServer::keyMap()[k].unicode;
680 }
681*/
682 char shifted = k;
683 if ( !isalpha( k ) ) {
684 // ### Fixme, bad code, needs improving, whole thing needs to
685 // be re-coded to get rid of the way it did things with scancodes etc
686 for ( unsigned i = 0; i < sizeof(shiftMap)/sizeof(ShiftMap); i++ )
687 if ( shiftMap[i].normal == k )
688 shifted = shiftMap[i].shifted;
689 } else {
690 shifted = toupper( k );
691 }
692 QChar tempChar( shift^lock ? shifted : k );
693 unicode = tempChar.unicode();
694#endif
695 }
696 if ( unicode != -1 ) {
697 modifiers = (shift ? Qt::ShiftButton : 0) | (ctrl ? Qt::ControlButton : 0) |
698 (alt ? Qt::AltButton : 0);
699#if defined(Q_WS_QWS) || defined(_WS_QWS_)
700 emit key( unicode, qkeycode, modifiers, true, false );
701 repeatTimer->start( 500 );
702#endif
703 need_repaint = shift || alt || ctrl;
704 shift = alt = ctrl = FALSE;
705 //qDebug( "pressed %d -> %04x ('%c')", k, u, u&0xffff < 256 ? u&0xff : 0 );
706
707 KeyboardConfig *dc = picks->dc;
708
709 if (dc) {
710 if (qkeycode == Qt::Key_Backspace) {
711 dc->input.remove(dc->input.last()); // remove last input
712 dc->decBackspaces();
713 } else if ( k == 0226 || qkeycode == Qt::Key_Return ||
714 qkeycode == Qt::Key_Space ||
715 QChar(unicode).isPunct() ) {
716 dc->input.clear();
717 dc->resetBackspaces();
718 } else {
719 dc->add(QString(QChar(unicode)));
720 dc->incBackspaces();
721 }
722 }
723
724 picks->repaint();
725
726 }
727 pressedKey = k;
728 if ( need_repaint ) {
729 repaint( FALSE );
730 } else {
731 QPainter p(this);
732 drawKeyboard( p, pressedKey );
733 }
734 pressTid = startTimer(80);
735 pressed = TRUE;
736}
737
738
739void Keyboard::mouseReleaseEvent(QMouseEvent*)
740{
741 if ( pressTid == 0 )
742 clearHighlight();
743#if defined(Q_WS_QWS) || defined(_WS_QWS_)
744 if ( unicode != -1 ) {
745 emit key( unicode, qkeycode, modifiers, false, false );
746 repeatTimer->stop();
747 }
748#endif
749 pressed = FALSE;
750}
751
752void Keyboard::timerEvent(QTimerEvent* e)
753{
754 if ( e->timerId() == pressTid ) {
755 killTimer(pressTid);
756 pressTid = 0;
757 if ( !pressed )
758 clearHighlight();
759 }
760}
761
762void Keyboard::repeat()
763{
764 repeatTimer->start( 150 );
765 emit key( unicode, qkeycode, modifiers, true, true );
766}
767
768void Keyboard::clearHighlight()
769{
770 if ( pressedKey >= 0 ) {
771 int tmp = pressedKey;
772 pressedKey = -1;
773 QPainter p(this);
774 drawKeyboard( p, tmp );
775 }
776}
777
778
779QSize Keyboard::sizeHint() const
780{
781 QFontMetrics fm=fontMetrics();
782 int keyHeight = fm.lineSpacing()+2;
783
784 if (useOptiKeys)
785 keyHeight += 1;
786
787 return QSize( 320, keyHeight * 5 + picks->sizeHint().height() + 1 );
788}
789
790
791void Keyboard::resetState()
792{
793 picks->resetState();
794}
diff --git a/inputmethods/keyboard/keyboard.h b/inputmethods/keyboard/keyboard.h
new file mode 100644
index 0000000..38ae338
--- a/dev/null
+++ b/inputmethods/keyboard/keyboard.h
@@ -0,0 +1,103 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#include <qframe.h>
21#include "../pickboard/pickboardcfg.h"
22#include "../pickboard/pickboardpicks.h"
23
24class QTimer;
25
26class KeyboardConfig : public DictFilterConfig
27{
28public:
29 KeyboardConfig(PickboardPicks* p) : DictFilterConfig(p), backspaces(0) { nrows = 1; }
30 virtual void generateText(const QString &s);
31 void decBackspaces() { if (backspaces) backspaces--; }
32 void incBackspaces() { backspaces++; }
33 void resetBackspaces() { backspaces = 0; }
34private:
35 int backspaces;
36};
37
38
39class KeyboardPicks : public PickboardPicks
40{
41 Q_OBJECT
42public:
43 KeyboardPicks(QWidget* parent=0, const char* name=0, WFlags f=0)
44 : PickboardPicks(parent, name, f) { }
45 void initialise();
46 virtual QSize sizeHint() const;
47 KeyboardConfig *dc;
48};
49
50class Keyboard : public QFrame
51{
52 Q_OBJECT
53public:
54 Keyboard( QWidget* parent=0, const char* name=0, WFlags f=0 );
55
56 void resetState();
57
58 void mousePressEvent(QMouseEvent*);
59 void mouseReleaseEvent(QMouseEvent*);
60 void resizeEvent(QResizeEvent*);
61 void paintEvent(QPaintEvent* e);
62 void timerEvent(QTimerEvent* e);
63 void drawKeyboard( QPainter &p, int key = -1 );
64
65 void setMode(int mode) { useOptiKeys = mode; }
66
67 QSize sizeHint() const;
68
69signals:
70 void key( ushort scancode, ushort unicode, ushort modifiers, bool, bool );
71
72private slots:
73 void repeat();
74
75private:
76 int getKey( int &w, int j = -1 );
77 void clearHighlight();
78
79 uint shift:1;
80 uint lock:1;
81 uint ctrl:1;
82 uint alt:1;
83 uint useLargeKeys:1;
84 uint useOptiKeys:1;
85
86 int pressedKey;
87
88 KeyboardPicks *picks;
89
90 int keyHeight;
91 int defaultKeyWidth;
92 int xoffs;
93
94 int unicode;
95 int qkeycode;
96 int modifiers;
97
98 int pressTid;
99 bool pressed;
100
101 QTimer *repeatTimer;
102};
103
diff --git a/inputmethods/keyboard/keyboard.pro b/inputmethods/keyboard/keyboard.pro
new file mode 100644
index 0000000..87c838e
--- a/dev/null
+++ b/inputmethods/keyboard/keyboard.pro
@@ -0,0 +1,18 @@
1 TEMPLATE= lib
2 CONFIG += qt warn_on release
3 HEADERS= keyboard.h \
4 ../pickboard/pickboardcfg.h \
5 ../pickboard/pickboardpicks.h \
6 keyboardimpl.h
7 SOURCES= keyboard.cpp \
8 ../pickboard/pickboardcfg.cpp \
9 ../pickboard/pickboardpicks.cpp \
10 keyboardimpl.cpp
11 TARGET = qkeyboard
12 DESTDIR = ../../plugins/inputmethods
13INCLUDEPATH += $(QPEDIR)/include
14DEPENDPATH += ../$(QPEDIR)/include ../../taskbar
15LIBS += -lqpe
16 VERSION = 1.0.0
17
18TRANSLATIONS += ../../i18n/de/libqkeyboard.ts
diff --git a/inputmethods/keyboard/keyboardimpl.cpp b/inputmethods/keyboard/keyboardimpl.cpp
new file mode 100644
index 0000000..ea61272
--- a/dev/null
+++ b/inputmethods/keyboard/keyboardimpl.cpp
@@ -0,0 +1,131 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#include <qapplication.h>
21#include <qpixmap.h>
22#include "keyboard.h"
23#include "keyboardimpl.h"
24
25/* XPM */
26static const char * kb_xpm[] = {
27"28 13 4 1",
28" c None",
29". c #4C4C4C",
30"+ c #FFF7DD",
31"@ c #D6CFBA",
32" .......................... ",
33" .+++.+++.+++.+++.+++.++++. ",
34" .+@@.+@@.+@@.+@@.+@@.+@@@. ",
35" .......................... ",
36" .+++++.+++.+++.+++.++++++. ",
37" .+@@@@.+@@.+@@.+@@.+@@@@@. ",
38" .......................... ",
39" .++++++.+++.+++.+++.+++++. ",
40" .+@@@@@.+@@.+@@.+@@.+@@@@. ",
41" .......................... ",
42" .++++.++++++++++++++.++++. ",
43" .+@@@.+@@@@@@@@@@@@@.+@@@. ",
44" .......................... "};
45
46
47/* XPM */
48static char * opti_xpm[] = {
49"28 13 4 1",
50" c None",
51". c #4C4C4C",
52"+ c #FFF7DD",
53"@ c #D6CFBA",
54" ......................... ",
55" .+++.+++.+++.+++.+++.+++. ",
56" .+@@.+@@.+@@.+@@.+@@.+@@. ",
57" ......................... ",
58" .+++.+++.+++.+++.+++.+++. ",
59" .+@@.+@@.+@@.+@@.+@@.+@@. ",
60" ......................... ",
61" .+++.+++.+++.+++.+++.+++. ",
62" .+@@.+@@.+@@.+@@.+@@.+@@. ",
63" ......................... ",
64" .+++.+++.+++.+++.+++.+++. ",
65" .+@@.+@@.+@@.+@@.+@@.+@@. ",
66" ......................... "};
67
68
69
70KeyboardImpl::KeyboardImpl()
71 : input(0), icn(0), ref(0)
72{
73}
74
75KeyboardImpl::~KeyboardImpl()
76{
77 delete input;
78 delete icn;
79}
80
81QWidget *KeyboardImpl::inputMethod( QWidget *parent, Qt::WFlags f )
82{
83 if ( !input )
84 input = new Keyboard( parent, "Keyboard", f );
85 return input;
86}
87
88void KeyboardImpl::resetState()
89{
90 if ( input )
91 input->resetState();
92}
93
94QPixmap *KeyboardImpl::icon()
95{
96 if ( !icn )
97 icn = new QPixmap( (const char **)kb_xpm );
98 return icn;
99}
100
101QString KeyboardImpl::name()
102{
103 return qApp->translate( "InputMethods", "Keyboard" );
104// return qApp->translate( "InputMethods", "Opti" );
105}
106
107void KeyboardImpl::onKeyPress( QObject *receiver, const char *slot )
108{
109 if ( input )
110 QObject::connect( input, SIGNAL(key(ushort,ushort,ushort,bool,bool)), receiver, slot );
111}
112
113#ifndef QT_NO_COMPONENT
114QRESULT KeyboardImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface )
115{
116 *iface = 0;
117 if ( uuid == IID_QUnknown )
118 *iface = this;
119 else if ( uuid == IID_InputMethod )
120 *iface = this;
121
122 if ( *iface )
123 (*iface)->addRef();
124 return QS_OK;
125}
126
127Q_EXPORT_INTERFACE()
128{
129 Q_CREATE_INSTANCE( KeyboardImpl )
130}
131#endif
diff --git a/inputmethods/keyboard/keyboardimpl.h b/inputmethods/keyboard/keyboardimpl.h
new file mode 100644
index 0000000..e756364
--- a/dev/null
+++ b/inputmethods/keyboard/keyboardimpl.h
@@ -0,0 +1,51 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#ifndef KEYBOARDIMPL_H
21#define KEYBOARDIMPL_H
22
23#include <qpe/inputmethodinterface.h>
24
25class Keyboard;
26class QPixmap;
27
28class KeyboardImpl : public InputMethodInterface
29{
30public:
31 KeyboardImpl();
32 virtual ~KeyboardImpl();
33
34#ifndef QT_NO_COMPONENT
35 QRESULT queryInterface( const QUuid&, QUnknownInterface** );
36 Q_REFCOUNT
37#endif
38
39 virtual QWidget *inputMethod( QWidget *parent, Qt::WFlags f );
40 virtual void resetState();
41 virtual QPixmap *icon();
42 virtual QString name();
43 virtual void onKeyPress( QObject *receiver, const char *slot );
44
45private:
46 Keyboard *input;
47 QPixmap *icn;
48 ulong ref;
49};
50
51#endif
diff --git a/inputmethods/keyboard/qpe-keyboard.control b/inputmethods/keyboard/qpe-keyboard.control
new file mode 100644
index 0000000..dae67f9
--- a/dev/null
+++ b/inputmethods/keyboard/qpe-keyboard.control
@@ -0,0 +1,9 @@
1Files: plugins/inputmethods/libqkeyboard.so*
2Priority: optional
3Section: qpe/inputmethods
4Maintainer: Martin Jones <mjones@trolltech.com>
5Architecture: arm
6Version: $QPE_VERSION-3
7Depends: qpe-base ($QPE_VERSION)
8Description: Keyboard input method
9 Keyboard input method for the Qtopia environment.
diff --git a/inputmethods/keyboard/qpe-keyboard.postinst b/inputmethods/keyboard/qpe-keyboard.postinst
new file mode 100755
index 0000000..c254b01
--- a/dev/null
+++ b/inputmethods/keyboard/qpe-keyboard.postinst
@@ -0,0 +1,2 @@
1#!/bin/sh
2/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadInputMethods()"
diff --git a/inputmethods/keyboard/qpe-keyboard.postrm b/inputmethods/keyboard/qpe-keyboard.postrm
new file mode 100755
index 0000000..c254b01
--- a/dev/null
+++ b/inputmethods/keyboard/qpe-keyboard.postrm
@@ -0,0 +1,2 @@
1#!/bin/sh
2/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadInputMethods()"
diff --git a/inputmethods/pickboard/.cvsignore b/inputmethods/pickboard/.cvsignore
new file mode 100644
index 0000000..edfa921
--- a/dev/null
+++ b/inputmethods/pickboard/.cvsignore
@@ -0,0 +1,3 @@
1moc_*
2*.moc
3Makefile
diff --git a/inputmethods/pickboard/Makefile.in b/inputmethods/pickboard/Makefile.in
new file mode 100644
index 0000000..d72e82d
--- a/dev/null
+++ b/inputmethods/pickboard/Makefile.in
@@ -0,0 +1,147 @@
1#############################################################################
2
3####### Compiler, tools and options
4
5 CXX =$(SYSCONF_CXX) $(QT_CXX_MT)
6 CXXFLAGS=$(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB)
7 CC =$(SYSCONF_CC) $(QT_C_MT)
8 CFLAGS =$(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB)
9 INCPATH =-I$(QPEDIR)/include
10 LFLAGS =$(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
11 LIBS =$(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP)
12 MOC =$(SYSCONF_MOC)
13 UIC =$(SYSCONF_UIC)
14
15####### Target
16
17DESTDIR = ../../plugins/inputmethods/
18VER_MAJ = 1
19VER_MIN = 0
20VER_PATCH = 0
21 TARGET= qpickboard
22TARGET1 = lib$(TARGET).so.$(VER_MAJ)
23
24####### Files
25
26 HEADERS =pickboard.h \
27 pickboardcfg.h \
28 pickboardimpl.h \
29 pickboardpicks.h
30 SOURCES =pickboard.cpp \
31 pickboardcfg.cpp \
32 pickboardimpl.cpp \
33 pickboardpicks.cpp
34 OBJECTS =pickboard.o \
35 pickboardcfg.o \
36 pickboardimpl.o \
37 pickboardpicks.o
38INTERFACES =
39UICDECLS =
40UICIMPLS =
41 SRCMOC =moc_pickboard.cpp \
42 moc_pickboardcfg.cpp \
43 moc_pickboardpicks.cpp
44 OBJMOC =moc_pickboard.o \
45 moc_pickboardcfg.o \
46 moc_pickboardpicks.o
47
48
49####### Implicit rules
50
51.SUFFIXES: .cpp .cxx .cc .C .c
52
53.cpp.o:
54 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
55
56.cxx.o:
57 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
58
59.cc.o:
60 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
61
62.C.o:
63 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
64
65.c.o:
66 $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
67
68####### Build rules
69
70
71all: $(DESTDIR)$(SYSCONF_LINK_TARGET)
72
73$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
74 $(SYSCONF_LINK_LIB)
75
76moc: $(SRCMOC)
77
78tmake:
79 tmake pickboard.pro
80
81clean:
82 -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
83 -rm -f *~ core
84 -rm -f allmoc.cpp
85
86####### Extension Modules
87
88listpromodules:
89 @echo
90
91listallmodules:
92 @echo
93
94listaddonpromodules:
95 @echo
96
97listaddonentmodules:
98 @echo
99
100
101REQUIRES=
102
103####### Sub-libraries
104
105
106###### Combined headers
107
108
109
110####### Compile
111
112pickboard.o: pickboard.cpp \
113 pickboard.h \
114 pickboardpicks.h \
115 pickboardcfg.h
116
117pickboardcfg.o: pickboardcfg.cpp \
118 pickboardcfg.h \
119 pickboardpicks.h
120
121pickboardimpl.o: pickboardimpl.cpp \
122 pickboard.h \
123 pickboardimpl.h
124
125pickboardpicks.o: pickboardpicks.cpp \
126 pickboardpicks.h \
127 pickboardcfg.h
128
129moc_pickboard.o: moc_pickboard.cpp \
130 pickboard.h
131
132moc_pickboardcfg.o: moc_pickboardcfg.cpp \
133 pickboardcfg.h
134
135moc_pickboardpicks.o: moc_pickboardpicks.cpp \
136 pickboardpicks.h
137
138moc_pickboard.cpp: pickboard.h
139 $(MOC) pickboard.h -o moc_pickboard.cpp
140
141moc_pickboardcfg.cpp: pickboardcfg.h
142 $(MOC) pickboardcfg.h -o moc_pickboardcfg.cpp
143
144moc_pickboardpicks.cpp: pickboardpicks.h
145 $(MOC) pickboardpicks.h -o moc_pickboardpicks.cpp
146
147
diff --git a/inputmethods/pickboard/pickboard.cpp b/inputmethods/pickboard/pickboard.cpp
new file mode 100644
index 0000000..087144e
--- a/dev/null
+++ b/inputmethods/pickboard/pickboard.cpp
@@ -0,0 +1,89 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#include "pickboard.h"
21#include "pickboardpicks.h"
22#include "pickboardcfg.h"
23
24#include <qpe/global.h>
25
26#include <qpainter.h>
27#include <qlist.h>
28#include <qbitmap.h>
29#include <qlayout.h>
30#include <qvbox.h>
31#include <qdialog.h>
32#include <qscrollview.h>
33#include <qpopupmenu.h>
34#include <qhbuttongroup.h>
35#include <qpushbutton.h>
36#include <qmessagebox.h>
37#include <qwindowsystem_qws.h>
38
39/* XPM */
40static const char * const menu_xpm[]={
41"9 9 2 1",
42"a c #000000",
43". c None",
44".........",
45".........",
46".........",
47"....a....",
48"...aaa...",
49"..aaaaa..",
50".aaaaaaa.",
51".........",
52"........."};
53
54class PickboardPrivate {
55public:
56 PickboardPrivate(Pickboard* parent)
57 {
58 picks = new PickboardPicks(parent);
59 picks->initialise();
60 menu = new QPushButton(parent);
61 menu->setSizePolicy(QSizePolicy(QSizePolicy::Minimum,QSizePolicy::Expanding));
62 menu->setPixmap(QPixmap((const char **)menu_xpm));
63 QObject::connect(menu,SIGNAL(clicked()),picks,SLOT(doMenu()));
64 QObject::connect(picks,SIGNAL(key(ushort,ushort,ushort,bool,bool)),
65 parent,SIGNAL(key(ushort,ushort,ushort,bool,bool)));
66 }
67
68 PickboardPicks* picks;
69 QPushButton* menu;
70};
71
72Pickboard::Pickboard(QWidget* parent, const char* name, WFlags f) :
73 QFrame(parent,name,f)
74{
75 (new QHBoxLayout(this))->setAutoAdd(TRUE);
76 d = new PickboardPrivate(this);
77 setFont( QFont( "smallsmooth", 9 ) );
78}
79
80Pickboard::~Pickboard()
81{
82 delete d;
83}
84
85void Pickboard::resetState()
86{
87 d->picks->resetState();
88}
89
diff --git a/inputmethods/pickboard/pickboard.h b/inputmethods/pickboard/pickboard.h
new file mode 100644
index 0000000..5fff875
--- a/dev/null
+++ b/inputmethods/pickboard/pickboard.h
@@ -0,0 +1,43 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#ifndef PICKBOARD_H
21#define PICKBOARD_H
22
23#include <qframe.h>
24
25class PickboardPrivate;
26
27class Pickboard : public QFrame
28{
29 Q_OBJECT
30public:
31 Pickboard(QWidget* parent=0, const char* name=0, WFlags f=0);
32 ~Pickboard();
33
34 void resetState();
35
36signals:
37 void key( ushort, ushort, ushort, bool, bool );
38
39private:
40 PickboardPrivate* d;
41};
42
43#endif
diff --git a/inputmethods/pickboard/pickboard.pro b/inputmethods/pickboard/pickboard.pro
new file mode 100644
index 0000000..50bc342
--- a/dev/null
+++ b/inputmethods/pickboard/pickboard.pro
@@ -0,0 +1,12 @@
1 TEMPLATE= lib
2 CONFIG += qt warn_on release
3 HEADERS= pickboard.h pickboardcfg.h pickboardimpl.h pickboardpicks.h
4 SOURCES= pickboard.cpp pickboardcfg.cpp pickboardimpl.cpp pickboardpicks.cpp
5 TARGET = qpickboard
6 DESTDIR = ../../plugins/inputmethods
7INCLUDEPATH += $(QPEDIR)/include
8DEPENDPATH += ../$(QPEDIR)/include ../../taskbar
9LIBS += -lqpe
10 VERSION = 1.0.0
11
12TRANSLATIONS += ../../i18n/de/libqpickboard.ts
diff --git a/inputmethods/pickboard/pickboardcfg.cpp b/inputmethods/pickboard/pickboardcfg.cpp
new file mode 100644
index 0000000..e8b47cb
--- a/dev/null
+++ b/inputmethods/pickboard/pickboardcfg.cpp
@@ -0,0 +1,731 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "pickboardcfg.h"
22#include "pickboardpicks.h"
23
24#include <qpe/global.h>
25
26#include <qpainter.h>
27#include <qlist.h>
28#include <qbitmap.h>
29#include <qlayout.h>
30#include <qvbox.h>
31#include <qdialog.h>
32#include <qscrollview.h>
33#include <qpopupmenu.h>
34#include <qhbuttongroup.h>
35#include <qpushbutton.h>
36#include <qmessagebox.h>
37#include <qwindowsystem_qws.h>
38
39static const char * pickboard_help =
40 "<h1>The Pickboard</h1>"
41 "<i>The smallest and fastest way to type.</i>"
42 "<p>"
43 "Enter a word by tapping letter-groups and picking the word."
44 "<br>Enter spaces with \"Space\", or other keys through \"KEY\"."
45 "<br>Use \"Shift\" to capitalize words that are not normally capitalized."
46 "<br>Press \"Shift\" twice for an all-capitals word."
47 "<br>Add custom words by picking them, then selecting \"Add...\" from the menu on the right."
48 ;
49
50const int intermatchmargin=5;
51
52
53PickboardConfig::~PickboardConfig() { }
54
55void PickboardConfig::updateRows(int from, int to)
56{
57 if ( from != to ) { // (all)
58 parent->update();
59 } else {
60 QFontMetrics fm = parent->fontMetrics();
61 parent->update(QRect(0,1+fm.descent() + from * fm.lineSpacing(), parent->width(),
62 fm.lineSpacing()));
63 }
64}
65
66void PickboardConfig::updateItem(int r, int)
67{
68 updateRows(r,r);
69}
70
71void PickboardConfig::changeMode(int m)
72{
73 parent->setMode(m);
74}
75void PickboardConfig::generateText(const QString& s)
76{
77#if defined(Q_WS_QWS) || defined(_WS_QWS_)
78 for (int i=0; i<(int)s.length(); i++) {
79 parent->emitKey(s[i].unicode(), 0, 0, true, false);
80 parent->emitKey(s[i].unicode(), 0, 0, false, false);
81 }
82#endif
83}
84void PickboardConfig::generateKey( int k )
85{
86#if defined(Q_WS_QWS) || defined(_WS_QWS_)
87 parent->emitKey(0, k, 0, true, false);
88 parent->emitKey(0, k, 0, false, false);
89#endif
90}
91
92void PickboardConfig::pickPoint(const QPoint& p, bool press)
93{
94 if ( press ) {
95 int ls=parent->height()/nrows;
96 int y=0;
97 pressx = -1;
98 for (int r=0; r<nrows; r++) {
99 if ( p.y() >= y && p.y() < y+ls ) {
100 pressrow = r;
101 pressx = p.x();
102 pickInRow( pressrow, pressx, TRUE );
103 return;
104 }
105 y += ls;
106 }
107 } else if ( pressx >= 0 ) {
108 pickInRow( pressrow, pressx, FALSE );
109 pressx = -1;
110 }
111}
112
113void PickboardConfig::fillMenu(QPopupMenu& menu)
114{
115 menu.insertItem("Reset",100);
116 menu.insertSeparator();
117 menu.insertItem("Help",1);
118}
119
120void PickboardConfig::doMenu(int i)
121{
122 switch (i) {
123 case 100:
124 if ( parent->currentMode() ) {
125 changeMode(0);
126 updateRows(0,1);
127 }
128 break;
129 case 1: {
130 QMessageBox help("Pickboard Help", pickboard_help,
131 QMessageBox::NoIcon, 1, 0, 0);
132 help.showMaximized();
133 help.exec();
134 }
135 }
136}
137
138void StringConfig::draw(QPainter* p)
139{
140 QFontMetrics fm = p->fontMetrics();
141
142 for (int r=0; r<nrows; r++) {
143 p->translate(0,fm.lineSpacing());
144 p->setPen(rowColor(r));
145
146 int tw=0;
147 QString s;
148 int i=0;
149 for (; !(s=text(r,i)).isNull(); ++i) {
150 int w = fm.width(s);
151 tw += w;
152 }
153 bool spread = spreadRow(r);// && parent->width() > tw;
154 int xw = spread ? (parent->width()-tw)/(i-1) : 3;
155 int x = spread ? (parent->width()-tw-xw*(i-1))/2 : 2;
156
157 i=0;
158 for (; !(s=text(r,i)).isNull(); ++i) {
159 int w = fm.width(s)+xw;
160 if ( highlight(r,i) ) {
161 p->fillRect(x-xw/2,1+fm.descent()-fm.lineSpacing(),w,fm.lineSpacing(),Qt::black);
162 p->setPen(Qt::white);
163 }else{
164 p->setPen(Qt::black);
165 }
166 p->drawText(x,-fm.descent()-1,s);
167 x += w;
168 }
169 }
170}
171
172void StringConfig::pickInRow(int r, int xpos, bool press)
173{
174 QFontMetrics fm = parent->fontMetrics();
175
176 int tw=0;
177 QString s;
178 int i=0;
179 for (; !(s=text(r,i)).isNull(); ++i) {
180 int w = fm.width(s);
181 tw += w;
182 }
183 bool spread = spreadRow(r) && parent->width() > tw;
184 int xw = spread ? (parent->width()-tw)/(i-1) : 3;
185 int x = spread ? (parent->width()-tw-xw*(i-1))/2 : 2;
186
187 i=0;
188 for (; !(s=text(r,i)).isNull(); ++i) {
189 int x2 = x + fm.width(s)+xw;
190 if ( xpos >= x && xpos < x2 ) {
191 pick(press, r, i);
192 return;
193 }
194 x = x2;
195 }
196}
197
198void StringConfig::updateItem(int r, int item)
199{
200 QFontMetrics fm = parent->fontMetrics();
201
202 int y = r * fm.lineSpacing();
203
204 int tw=0;
205 QString s;
206 int i=0;
207 for (; !(s=text(r,i)).isNull(); ++i) {
208 int w = fm.width(s);
209 tw += w;
210 }
211 bool spread = spreadRow(r) && parent->width() > tw;
212 int xw = spread ? (parent->width()-tw)/(i-1) : 3;
213 int x = spread ? (parent->width()-tw-xw*(i-1))/2 : 2;
214
215 i=0;
216 for (; !(s=text(r,i)).isNull(); ++i) {
217 int w = fm.width(s)+xw;
218 if ( i == item ) {
219 parent->update(QRect(x-xw/2,y+1+fm.descent(),w,fm.lineSpacing()));
220 return;
221 }
222 x += w;
223 }
224}
225
226bool StringConfig::highlight(int,int) const
227{
228 return FALSE;
229}
230
231LetterButton::LetterButton(const QChar& letter, QWidget* parent) :
232 QPushButton(letter,parent)
233{
234 setToggleButton(TRUE);
235 setAutoDefault(FALSE);
236 connect(this,SIGNAL(clicked()),this,SLOT(toggleCase()));
237 skip=TRUE;
238}
239
240void LetterButton::toggleCase()
241{
242 if ( skip ) {
243 // Don't toggle case the first time
244 skip=FALSE;
245 return;
246 }
247
248 QChar ch = text()[0];
249 QChar nch = ch.lower();
250 if ( ch == nch )
251 nch = ch.upper();
252 setText(nch);
253}
254
255LetterChoice::LetterChoice(QWidget* parent, const QString& set) :
256 QButtonGroup(parent)
257{
258 QHBoxLayout *l = new QHBoxLayout(this);
259 setFrameStyle(0);
260 setExclusive(TRUE);
261 for (int i=0; i<(int)set.length(); i++) {
262 LetterButton* b = new LetterButton(set[i],this);
263 l->addWidget(b,1,AlignCenter);
264 connect(b,SIGNAL(clicked()),this,SLOT(change()));
265 }
266}
267
268void LetterChoice::change()
269{
270 LetterButton* b = (LetterButton*)sender();
271 ch = b->text()[0];
272 emit changed();
273}
274
275
276PickboardAdd::PickboardAdd(QWidget* owner, const QStringList& setlist) :
277 QDialog( owner, 0, TRUE )
278{
279 QVBoxLayout* l = new QVBoxLayout(this);
280 l->setAutoAdd(TRUE);
281
282 QScrollView *sv = new QScrollView(this);
283 sv->setResizePolicy(QScrollView::AutoOneFit);
284 setMaximumHeight(200); // ### QDialog shouldn't allow us to be bigger than the screen
285 QVBox *letters = new QVBox(sv);
286 letters->setSpacing(0);
287 lc = new LetterChoice*[setlist.count()];
288 nlc = (int)setlist.count();
289 for (int i=0; i<nlc; i++) {
290 lc[i] = new LetterChoice(letters,setlist[i]);
291 connect(lc[i],SIGNAL(changed()),this,SLOT(checkAllDone()));
292 }
293 sv->addChild(letters);
294 QHBox* hb = new QHBox(this);
295 hb->setSpacing(0);
296 yes = new QPushButton("OK",hb);
297 yes->setEnabled(FALSE);
298 QPushButton *no = new QPushButton("Cancel",hb);
299 connect(yes, SIGNAL(clicked()), this, SLOT(accept()));
300 connect(no, SIGNAL(clicked()), this, SLOT(reject()));
301}
302
303PickboardAdd::~PickboardAdd()
304{
305 delete [] lc;
306}
307
308QString PickboardAdd::word() const
309{
310 QString str;
311 for (int i=0; i<nlc; i++) {
312 str += lc[i]->choice();
313 }
314 return str;
315}
316
317bool PickboardAdd::exec()
318{
319 QPoint pos = parentWidget()->mapToGlobal(QPoint(0,0));
320 pos.ry() -= height();
321 if ( QDialog::exec() ) {
322 Global::addWords(QStringList(word()));
323 return TRUE;
324 } else {
325 return FALSE;
326 }
327}
328
329void PickboardAdd::checkAllDone()
330{
331 if ( !yes->isEnabled() ) {
332 for (int i=0; i<nlc; i++) {
333 if ( lc[i]->choice().isNull() )
334 return;
335 }
336 yes->setEnabled(TRUE);
337 }
338}
339
340
341void DictFilterConfig::doMenu(int i)
342{
343 switch (i) {
344 case 300:
345 if ( input.count() == 0 ) {
346 QMessageBox::information(0, "Adding Words",
347 "To add words, pick the letters,\nthen "
348 "open the Add dialog. In that\ndialog, tap "
349 "the correct letters\nfrom the list "
350 "(tap twice for\ncapitals).");
351 } else {
352 PickboardAdd add(parent,capitalize(input));
353 if ( add.exec() )
354 generateText(add.word());
355 input.clear();
356 matches.clear();
357 updateRows(0,0);
358 }
359 break;
360 case 100:
361 if ( !input.isEmpty() ) {
362 input.clear();
363 matches.clear();
364 StringConfig::doMenu(i);
365 updateRows(0,1);
366 break;
367 } // else fall through
368 default:
369 StringConfig::doMenu(i);
370 }
371 shift = 0;
372 lit0 = -1;
373}
374
375QString DictFilterConfig::text(int r, int i)
376{
377 QStringList l = r ? sets : input.isEmpty() ? othermodes : matches;
378 return i < (int)l.count() ?
379 (input.isEmpty() ? l[i] : capitalize(l[i]))
380 : QString::null;
381}
382
383bool DictFilterConfig::spreadRow(int r)
384{
385 return r ? TRUE : input.isEmpty() ? TRUE : FALSE;
386}
387
388QStringList DictFilterConfig::capitalize(const QStringList& l)
389{
390 switch ( shift ) {
391 case 1: {
392 QStringList r;
393 QStringList::ConstIterator it = l.begin();
394 r.append((*it).upper());
395 for (++it; it != l.end(); ++it)
396 r.append(*it);
397 return r;
398 } case 2: {
399 QStringList r;
400 for (QStringList::ConstIterator it = l.begin(); it != l.end(); ++it)
401 r.append((*it).upper());
402 return r;
403 }
404 }
405 return l;
406}
407
408QString DictFilterConfig::capitalize(const QString& s)
409{
410 switch ( shift ) {
411 case 1: {
412 QString u = s;
413 u[0] = u[0].upper();
414 return u;
415 break;
416 } case 2:
417 return s.upper();
418 break;
419 }
420 return s;
421}
422
423void DictFilterConfig::pick(bool press, int row, int item)
424{
425 if ( row == 0 ) {
426 if ( press ) {
427 if ( input.isEmpty() ) {
428 lit0 = item;
429 if ( othermodes[item] == "Space" ) {
430 updateItem(row,item);
431 generateText(" ");
432 } else if ( othermodes[item] == "Back" ) {
433 updateItem(row,item);
434 generateKey(Qt::Key_Backspace);
435 } else if ( othermodes[item] == "Enter" ) {
436 updateItem(row,item);
437 generateKey(Qt::Key_Return);
438 } else if ( othermodes[item] == "Shift" ) {
439 updateItem(row,item);
440 shift = (shift+1)%3;
441 }
442 }
443 } else {
444 if ( !input.isEmpty() ) {
445 input.clear();
446 if ( item>=0 ) {
447 generateText(capitalize(matches[item]));
448 }
449 shift = 0;
450 matches.clear();
451 updateRows(0,0);
452 } else if ( item < 3 ) {
453 lit0 = -1;
454 changeMode(item+1); // I'm mode 0! ####
455 updateRows(0,1);
456 }
457 if ( lit0 >= 0 ) {
458 if ( !shift || othermodes[lit0] != "Shift" ) {
459 updateItem(0,lit0);
460 lit0 = -1;
461 }
462 }
463 }
464 } else {
465 lit0 = -1;
466 if ( press && item >= 0 ) {
467 lit1 = item;
468 add(sets[item]);
469 updateItem(1,item);
470 updateRows(0,0);
471 } else {
472 updateItem(1,lit1);
473 lit1 = -1;
474 }
475 }
476}
477
478bool DictFilterConfig::scanMatch(const QString& set, const QChar& l) const
479{
480 return set == "?" || set == "*" || set.contains(l);
481}
482
483//static int visit=0;
484//static int lvisit=0;
485
486void DictFilterConfig::scan(const QDawg::Node* n, int ipos, const QString& str, int length, bool extend)
487{
488 if ( n ) {
489 do {
490//visit++;
491 bool pastend = ipos >= (int)input.count();
492 if ( pastend && extend || !pastend && scanMatch(input[ipos],n->letter().lower()) ) {
493 if ( length>1 ) {
494 if ( !pastend && input[ipos] == "*" ) {
495 scan(n->jump(),ipos+1,str+n->letter(),length-1,FALSE);
496 scan(n->jump(),ipos,str+n->letter(),length,FALSE);
497 } else {
498 scan(n->jump(),ipos+1,str+n->letter(),length-1,extend);
499 }
500 } else {
501 if ( n->isWord() ) {
502 matches.append(str+n->letter());
503 }
504 }
505 }
506 n = n->next();
507 } while (n);
508 }
509}
510
511void DictFilterConfig::scanLengths(const QDawg::Node* n, int ipos, int& length_bitarray)
512{
513 if ( n ) {
514 do {
515//lvisit++;
516 bool pastend = ipos >= (int)input.count();
517 if ( pastend || scanMatch(input[ipos],n->letter().lower()) ) {
518 scanLengths(n->jump(),ipos+1,length_bitarray);
519 if ( n->isWord() )
520 length_bitarray |= (1<<(ipos+1));
521 }
522 n = n->next();
523 } while (n);
524 }
525}
526
527void DictFilterConfig::add(const QString& set)
528{
529 QFontMetrics fm = parent->fontMetrics();
530 input.append(set.lower());
531 matches.clear();
532//visit=0;
533//lvisit=0;
534 int length_bitarray = 0;
535 if ( input.count() > 4 ) {
536 scanLengths(Global::addedDawg().root(),0,length_bitarray);
537 scanLengths(Global::fixedDawg().root(),0,length_bitarray);
538 } else {
539 length_bitarray = 0xffffffff;
540 }
541 for (int len=input.count(); len<22 /* 32 */; ++len) {
542 if ( length_bitarray & (1<<len) ) {
543 scan(Global::addedDawg().root(),0,"",len,TRUE);
544 scan(Global::fixedDawg().root(),0,"",len,TRUE);
545 int x = 2;
546 for (QStringList::Iterator it=matches.begin(); it!=matches.end(); ++it) {
547 x += fm.width(*it)+intermatchmargin;
548 if ( x >= parent->width() ) {
549//qDebug("%d+%d visits",lvisit,visit);
550 return; // RETURN - No point finding more
551 }
552 }
553 }
554 if ( len == 1 && input.count() == 1 ) {
555 // Allow all single-characters to show as "matches"
556 for ( int i=0; i<(int)set.length(); i++ ) {
557 QChar ch = set[i].lower();
558 matches.append(ch);
559 }
560 }
561 }
562//qDebug("%d+%d visits",lvisit,visit);
563}
564
565bool DictFilterConfig::highlight(int r,int c) const
566{
567 return r == 0 ? c == lit0 : c == lit1;
568}
569
570
571void DictFilterConfig::addSet(const QString& s)
572{
573 sets.append(s);
574}
575
576void DictFilterConfig::addMode(const QString& s)
577{
578 othermodes.append(s);
579}
580
581void DictFilterConfig::fillMenu(QPopupMenu& menu)
582{
583 menu.insertItem("Add...",300);
584 StringConfig::fillMenu(menu);
585}
586
587QValueList<QPixmap> KeycodeConfig::row(int i)
588{
589 return i ? keypm2 : keypm1;
590}
591
592void KeycodeConfig::pickInRow(int r, int xpos, bool press)
593{
594 QValueList<QPixmap> pl = row(r);
595 QValueList<QPixmap>::Iterator it;
596 int item=0;
597 int x=xmarg;
598 for (it=pl.begin(); it!=pl.end(); ++it) {
599 int x2 = x + (*it).width();
600 if ( (*it).height() > 1 )
601 x2 += xw;
602 if ( xpos >= x && xpos < x2 ) {
603 pick(press, r, item);
604 return;
605 }
606 x = x2;
607 item++;
608 }
609}
610
611void KeycodeConfig::pick(bool press, int row, int item)
612{
613 if ( !press ) {
614 if ( item >= 0 ) {
615 int k = row == 0 ? keys1[item] : keys2[item];
616 if ( k )
617 generateKey(k);
618 }
619 changeMode(0);
620 updateRows(0,1);
621 }
622}
623
624void KeycodeConfig::draw(QPainter* p)
625{
626 int y=3;
627 QValueList<QPixmap>::Iterator it;
628 for (int r=0; r<nrows; r++) {
629 QValueList<QPixmap> pl = row(r);
630 int x = xmarg;
631 for (it=pl.begin(); it!=pl.end(); ++it) {
632 if ( (*it).height() == 1 ) {
633 // just a gap
634 x += (*it).width();
635 } else {
636 p->drawPixmap(x,y,*it);
637 x += (*it).width()+xw;
638 }
639 }
640 y += parent->height()/nrows;
641 }
642}
643
644
645void KeycodeConfig::addKey(int r, const QPixmap& pm, int code)
646{
647 if ( r == 0 ) {
648 keypm1.append(pm);
649 keys1.append(code);
650 } else {
651 keypm2.append(pm);
652 keys2.append(code);
653 }
654}
655void KeycodeConfig::addGap(int r, int w)
656{
657 QBitmap pm(w,1); // ick.
658 addKey(r,pm,0);
659}
660
661QString CharConfig::text(int r, int i)
662{
663 QStringList l = r ? chars2 : chars1;
664 return i < (int)l.count() ? l[i] : QString::null;
665}
666bool CharConfig::spreadRow(int)
667{
668 return TRUE;
669}
670
671void CharConfig::pick(bool press, int row, int item)
672{
673 if ( !press ) {
674 if ( item >= 0 ) {
675 generateText(row == 0 ? chars1[item] : chars2[item]);
676 }
677 changeMode(0);
678 updateRows(0,1);
679 }
680}
681
682void CharConfig::addChar(int r, const QString& s)
683{
684 if ( r ) chars2.append(s); else chars1.append(s);
685}
686
687QString CharStringConfig::text(int r, int i)
688{
689 QStringList l = r ? chars : QStringList(input);
690 return i < (int)l.count() ? l[i] : QString::null;
691}
692
693bool CharStringConfig::spreadRow(int i)
694{
695 return i ? TRUE : FALSE;
696}
697
698void CharStringConfig::pick(bool press, int row, int item)
699{
700 if ( row == 0 ) {
701 if ( !press ) {
702 if ( item>=0 ) {
703 generateText(input);
704 }
705 input = "";
706 changeMode(0);
707 updateRows(0,1);
708 }
709 } else {
710 if ( press && item >= 0 ) {
711 input.append(chars[item]);
712 updateRows(0,0);
713 }
714 }
715}
716
717void CharStringConfig::addChar(const QString& s)
718{
719 chars.append(s);
720}
721
722void CharStringConfig::doMenu(int i)
723{
724 if ( i == 100 ) {
725 input = "";
726 updateRows(0,0);
727 }
728
729 StringConfig::doMenu(i);
730}
731
diff --git a/inputmethods/pickboard/pickboardcfg.h b/inputmethods/pickboard/pickboardcfg.h
new file mode 100644
index 0000000..e0dc0dd
--- a/dev/null
+++ b/inputmethods/pickboard/pickboardcfg.h
@@ -0,0 +1,213 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#ifndef PICKBOARDCFG_H
21#define PICKBOARDCFG_H
22
23#include <qpe/qdawg.h>
24
25#include <qpushbutton.h>
26#include <qhbuttongroup.h>
27#include <qdialog.h>
28#include <qlist.h>
29
30// Internal stuff...
31
32class PickboardPicks;
33
34class LetterButton : public QPushButton {
35 Q_OBJECT
36public:
37 LetterButton(const QChar& letter, QWidget* parent);
38private slots:
39 void toggleCase();
40private:
41 bool skip;
42};
43
44class LetterChoice : public QButtonGroup {
45 Q_OBJECT
46public:
47 LetterChoice(QWidget* parent, const QString& set);
48
49 QChar choice() { return ch; }
50
51signals:
52 void changed();
53
54private slots:
55 void change();
56
57private:
58 QChar ch;
59};
60
61class PickboardAdd : public QDialog {
62 Q_OBJECT
63public:
64 PickboardAdd(QWidget* owner, const QStringList& setlist);
65 ~PickboardAdd();
66
67 QString word() const;
68 bool exec();
69
70private slots:
71 void checkAllDone();
72
73private:
74 QPushButton *yes;
75 LetterChoice **lc;
76 int nlc;
77};
78
79class PickboardConfig : QObject {
80public:
81 PickboardConfig(PickboardPicks* p) : parent(p), nrows(2), pressx(-1) { }
82 virtual ~PickboardConfig();
83 virtual void pickPoint(const QPoint& p, bool press);
84 virtual void draw(QPainter*)=0;
85 virtual void fillMenu(QPopupMenu&);
86 virtual void doMenu(int);
87
88protected:
89 void updateRows(int from, int to);
90 virtual void updateItem(int r, int i);
91 virtual void pickInRow(int r, int xpos, bool press)=0;
92
93 void changeMode(int m);
94 virtual void generateText(const QString& s);
95 void generateKey( int k );
96
97 virtual void pick(bool press, int row, int item)=0;
98
99protected:
100 PickboardPicks* parent;
101 int nrows;
102private:
103 int pressrow, pressx;
104};
105
106class StringConfig : public PickboardConfig {
107public:
108 StringConfig(PickboardPicks* p) : PickboardConfig(p) { }
109
110 void draw(QPainter* p);
111
112protected:
113 virtual QString text(int r, int i)=0;
114 virtual bool spreadRow(int i)=0;
115 virtual QColor rowColor(int) { return Qt::black; }
116 virtual void pickInRow(int r, int xpos, bool press);
117 virtual void updateItem(int r, int i);
118 virtual bool highlight(int,int) const;
119};
120
121class CharStringConfig : public StringConfig {
122 QString input;
123 QStringList chars;
124public:
125 CharStringConfig(PickboardPicks* p) : StringConfig(p) { }
126
127 void addChar(const QString& s);
128 virtual void doMenu(int);
129
130protected:
131 QString text(int r, int i);
132 bool spreadRow(int i);
133 void pick(bool press, int row, int item);
134};
135
136class DictFilterConfig : public StringConfig {
137 QStringList matches;
138 QStringList sets;
139 QStringList othermodes;
140 int lit0;
141 int lit1;
142 int shift;
143 QString capitalize(const QString& s);
144 QStringList capitalize(const QStringList& s);
145
146public:
147 QStringList input;
148 DictFilterConfig(PickboardPicks* p) : StringConfig(p)
149 {
150 shift = 0;
151 lit0 = -1;
152 lit1 = -1;
153 }
154
155 void addSet(const QString& s);
156 void addMode(const QString& s);
157
158 void fillMenu(QPopupMenu& menu);
159 void doMenu(int i);
160
161 void add(const QString& set);
162
163protected:
164 QString text(int r, int i);
165
166 bool spreadRow(int i);
167
168 void pick(bool press, int row, int item);
169
170 bool scanMatch(const QString& set, const QChar& l) const;
171 void scan(const QDawg::Node* n, int ipos, const QString& str, int length, bool extend);
172 void scanLengths(const QDawg::Node* n, int ipos, int& bitarray);
173
174 bool highlight(int r,int c) const;
175};
176
177class CharConfig : public StringConfig {
178 QStringList chars1;
179 QStringList chars2;
180public:
181 CharConfig(PickboardPicks* p) : StringConfig(p) { }
182 void addChar(int r, const QString& s);
183
184protected:
185 QString text(int r, int i);
186 bool spreadRow(int);
187 void pick(bool press, int row, int item);
188};
189
190class KeycodeConfig : public PickboardConfig {
191 QValueList<int> keys1;
192 QValueList<int> keys2;
193 QValueList<QPixmap> keypm1;
194 QValueList<QPixmap> keypm2;
195 static const int xw = 8;
196 static const int xmarg = 8;
197
198public:
199 KeycodeConfig(PickboardPicks* p) : PickboardConfig(p) { }
200 void addKey(int r, const QPixmap& pm, int code);
201 void addGap(int r, int w);
202
203 void draw(QPainter* p);
204
205protected:
206 void pickInRow(int r, int xpos, bool press);
207 QValueList<QPixmap> row(int i);
208
209 void pick(bool press, int row, int item);
210};
211
212
213#endif
diff --git a/inputmethods/pickboard/pickboardimpl.cpp b/inputmethods/pickboard/pickboardimpl.cpp
new file mode 100644
index 0000000..a4e8f02
--- a/dev/null
+++ b/inputmethods/pickboard/pickboardimpl.cpp
@@ -0,0 +1,101 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#include <qapplication.h>
21#include <qobject.h>
22#include <qpixmap.h>
23#include "pickboard.h"
24#include "pickboardimpl.h"
25
26/* XPM */
27static const char * pb_xpm[]={
28"28 7 2 1",
29"# c #303030",
30" c None",
31" ########################## ",
32" # # # # # # # ",
33" # # # # # # # ",
34" ########################## ",
35" # # # # # # ",
36" # # # # # # ",
37" ########################## "};
38
39
40PickboardImpl::PickboardImpl()
41 : pickboard(0), icn(0), ref(0)
42{
43}
44
45PickboardImpl::~PickboardImpl()
46{
47 delete pickboard;
48 delete icn;
49}
50
51QWidget *PickboardImpl::inputMethod( QWidget *parent, Qt::WFlags f )
52{
53 if ( !pickboard )
54 pickboard = new Pickboard( parent, "pickboard", f );
55 return pickboard;
56}
57
58void PickboardImpl::resetState()
59{
60 if ( pickboard )
61 pickboard->resetState();
62}
63
64QPixmap *PickboardImpl::icon()
65{
66 if ( !icn )
67 icn = new QPixmap( (const char **)pb_xpm );
68 return icn;
69}
70
71QString PickboardImpl::name()
72{
73 return qApp->translate( "InputMethods", "Pickboard" );
74}
75
76void PickboardImpl::onKeyPress( QObject *receiver, const char *slot )
77{
78 if ( pickboard )
79 QObject::connect( pickboard, SIGNAL(key(ushort,ushort,ushort,bool,bool)), receiver, slot );
80}
81
82#ifndef QT_NO_COMPONENT
83QRESULT PickboardImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface )
84{
85 *iface = 0;
86 if ( uuid == IID_QUnknown )
87 *iface = this;
88 else if ( uuid == IID_InputMethod )
89 *iface = this;
90
91 if ( *iface )
92 (*iface)->addRef();
93 return QS_OK;
94}
95
96Q_EXPORT_INTERFACE()
97{
98 Q_CREATE_INSTANCE( PickboardImpl )
99}
100#endif
101
diff --git a/inputmethods/pickboard/pickboardimpl.h b/inputmethods/pickboard/pickboardimpl.h
new file mode 100644
index 0000000..4f23665
--- a/dev/null
+++ b/inputmethods/pickboard/pickboardimpl.h
@@ -0,0 +1,51 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#ifndef PICKBOARDIMPL_H
21#define PICKBOARDIMPL_H
22
23#include <qpe/inputmethodinterface.h>
24
25class Pickboard;
26class QPixmap;
27
28class PickboardImpl : public InputMethodInterface
29{
30public:
31 PickboardImpl();
32 virtual ~PickboardImpl();
33
34#ifndef QT_NO_COMPONENT
35 QRESULT queryInterface( const QUuid&, QUnknownInterface** );
36 Q_REFCOUNT
37#endif
38
39 virtual QWidget *inputMethod( QWidget *parent, Qt::WFlags f );
40 virtual void resetState();
41 virtual QPixmap *icon();
42 virtual QString name();
43 virtual void onKeyPress( QObject *receiver, const char *slot );
44
45private:
46 Pickboard *pickboard;
47 QPixmap *icn;
48 ulong ref;
49};
50
51#endif
diff --git a/inputmethods/pickboard/pickboardpicks.cpp b/inputmethods/pickboard/pickboardpicks.cpp
new file mode 100644
index 0000000..a80bbf8
--- a/dev/null
+++ b/inputmethods/pickboard/pickboardpicks.cpp
@@ -0,0 +1,418 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#include "pickboardpicks.h"
21#include "pickboardcfg.h"
22
23#include <qpe/global.h>
24
25#include <qpainter.h>
26#include <qlist.h>
27#include <qbitmap.h>
28#include <qlayout.h>
29#include <qvbox.h>
30#include <qdialog.h>
31#include <qscrollview.h>
32#include <qpopupmenu.h>
33#include <qhbuttongroup.h>
34#include <qpushbutton.h>
35#include <qmessagebox.h>
36#include <qwindowsystem_qws.h>
37
38void PickboardPicks::doMenu()
39{
40 QWidget* cause = (QWidget*)sender(); // evil
41
42 QPopupMenu popup(this);
43 config()->fillMenu(popup);
44
45 QPoint pos = cause->mapToGlobal(cause->rect().topRight());
46 QSize sz = popup.sizeHint();
47 pos.ry() -= sz.height();
48 pos.rx() -= sz.width();
49 popup.move(pos);
50 config()->doMenu(popup.exec());
51}
52
53static const char *BS_xpm[] = {
54"5 7 2 1",
55"a c #000000",
56". c None",
57"...aa",
58"..aaa",
59".aaaa",
60"aaaaa",
61".aaaa",
62"..aaa",
63"...aa",
64};
65static const char *Del_xpm[] = {
66"14 7 2 1",
67"a c #000000",
68". c None",
69"aaa..aaaa.a...",
70"a..a.a....a...",
71"a..a.a....a...",
72"a..a.aaa..a...",
73"a..a.a....a...",
74"a..a.a....a...",
75"aaa..aaaa.aaaa"
76};
77static const char *Home_xpm[] = {
78"20 7 2 1",
79"a c #000000",
80". c None",
81"a..a..aa..a...a.aaaa",
82"a..a.a..a.aa.aa.a...",
83"a..a.a..a.a.a.a.a...",
84"aaaa.a..a.a.a.a.aaa.",
85"a..a.a..a.a...a.a...",
86"a..a.a..a.a...a.a...",
87"a..a..aa..a...a.aaaa"
88};
89static const char *PgUp_xpm[] = {
90"20 7 2 1",
91"a c #000000",
92". c None",
93"aaa.......a..a......",
94"a..a......a..a......",
95"a..a.aa...a..a.aaa..",
96"aaa.a.....a..a.a..a.",
97"a...a.aa..a..a.aaa..",
98"a...a..a..a..a.a....",
99"a....aaa...aa..a...."
100};
101static const char *PgDn_xpm[] = {
102"20 7 2 1",
103"a c #000000",
104". c None",
105"aaa.......aaa.......",
106"a..a......a..a......",
107"a..a.aa...a..a.a..a.",
108"aaa.a.....a..a.aa.a.",
109"a...a.aa..a..a.a.aa.",
110"a...a..a..a..a.a..a.",
111"a....aaa..aaa..a..a."
112};
113static const char *End_xpm[] = {
114"14 7 2 1",
115"a c #000000",
116". c None",
117"aaaa.a..a.aaa.",
118"a....aa.a.a..a",
119"a....a.aa.a..a",
120"aaa..a..a.a..a",
121"a....a..a.a..a",
122"a....a..a.a..a",
123"aaaa.a..a.aaa."
124};
125static const char *Enter_xpm[] = {
126"14 7 2 1",
127"a c #000000",
128". c None",
129".............a",
130".............a",
131"..a..........a",
132".aa.........a.",
133"aaaaaaaaaaaa..",
134".aa...........",
135"..a..........."
136};
137static const char *Esc_xpm[] = {
138"14 7 2 1",
139"a c #000000",
140". c None",
141"aaaa..aa...aa.",
142"a....a..a.a..a",
143"a....a....a...",
144"aaa...aa..a...",
145"a.......a.a...",
146"a....a..a.a..a",
147"aaaa..aa...aa."
148};
149static const char *Ins_xpm[] = {
150"13 7 2 1",
151"a c #000000",
152". c None",
153"aaa.a..a..aa.",
154".a..aa.a.a..a",
155".a..a.aa.a...",
156".a..a..a..aa.",
157".a..a..a....a",
158".a..a..a.a..a",
159"aaa.a..a..aa."
160};
161static const char *Up_xpm[] = {
162"7 7 2 1",
163"a c #000000",
164". c None",
165"...a...",
166"..aaa..",
167".a.a.a.",
168"a..a..a",
169"...a...",
170"...a...",
171"...a..."
172};
173static const char *Left_xpm[] = {
174"7 7 2 1",
175"a c #000000",
176". c None",
177"...a...",
178"..a....",
179".a.....",
180"aaaaaaa",
181".a.....",
182"..a....",
183"...a..."
184};
185static const char *Down_xpm[] = {
186"7 7 2 1",
187"a c #000000",
188". c None",
189"...a...",
190"...a...",
191"...a...",
192"a..a..a",
193".a.a.a.",
194"..aaa..",
195"...a..."
196};
197static const char *Right_xpm[] = {
198"7 7 2 1",
199"a c #000000",
200". c None",
201"...a...",
202"....a..",
203".....a.",
204"aaaaaaa",
205".....a.",
206"....a..",
207"...a..."
208};
209static const char *BackTab_xpm[] = {
210"8 7 2 1",
211"a c #000000",
212". c None",
213"a.......",
214"a..a....",
215"a.aa....",
216"aaaaaaaa",
217"a.aa....",
218"a..a....",
219"a......."
220};
221static const char *Tab_xpm[] = {
222"8 7 2 1",
223"a c #000000",
224". c None",
225".......a",
226"....a..a",
227"....aa.a",
228"aaaaaaaa",
229"....aa.a",
230"....a..a",
231".......a"
232};
233static const char *Space_xpm[] = {
234"9 9 2 1",
235"a c #000000",
236". c None",
237"aaaaaaaaa",
238"a.......a",
239"a.......a",
240"a.......a",
241"a.......a",
242"a.......a",
243"a.......a",
244"a.......a",
245"aaaaaaaaa"
246};
247
248PickboardPicks::PickboardPicks(QWidget* parent, const char* name, WFlags f ) :
249 QFrame(parent,name,f)
250{
251}
252
253void PickboardPicks::initialise(void)
254{
255 setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
256 mode = 0;
257
258 DictFilterConfig* dc = new DictFilterConfig(this);
259 dc->addSet("ABC");
260 dc->addSet("DEF");
261 dc->addSet("GHI");
262 dc->addSet("JKL");
263 dc->addSet("MNO");
264 dc->addSet("PQR");
265 dc->addSet("STU");
266 dc->addSet("VWX");
267 dc->addSet("YZ-'");
268 dc->addMode("123");
269 dc->addMode("@*!?");
270 dc->addMode("KEY");
271 dc->addMode("Space");
272 dc->addMode("Back");
273 dc->addMode("Enter");
274 dc->addMode("Shift");
275 configs.append(dc);
276
277 CharStringConfig* number = new CharStringConfig(this);
278 number->addChar("0");
279 number->addChar("1");
280 number->addChar("2");
281 number->addChar("3");
282 number->addChar("4");
283 number->addChar("5");
284 number->addChar("6");
285 number->addChar("7");
286 number->addChar("8");
287 number->addChar("9");
288 number->addChar("."); // #### or "," in some locales
289 configs.append(number);
290
291 CharConfig* punc = new CharConfig(this);
292
293 punc->addChar(0,"\"");
294 punc->addChar(0,"`");
295 punc->addChar(0,"'");
296 punc->addChar(0,"\253");
297 punc->addChar(0,"\273");
298 punc->addChar(0,"\277");
299 punc->addChar(1,"(");
300 punc->addChar(1,")");
301 punc->addChar(1,"[");
302 punc->addChar(1,"]");
303 punc->addChar(1,"{");
304 punc->addChar(1,"}");
305
306 punc->addChar(0,"+");
307 punc->addChar(0,"-");
308 punc->addChar(0,"*");
309 punc->addChar(0,"/");
310 punc->addChar(0,"=");
311 punc->addChar(0,"_");
312 punc->addChar(0,"$");
313 punc->addChar(0,"&");
314 punc->addChar(1,"|");
315 punc->addChar(1,"@");
316 punc->addChar(1,"\\");
317 punc->addChar(1,"#");
318 punc->addChar(1,"^");
319 punc->addChar(1,"~");
320 punc->addChar(1,"<");
321 punc->addChar(1,">");
322
323 punc->addChar(0,".");
324 punc->addChar(0,"?");
325 punc->addChar(0,"!");
326 punc->addChar(0,",");
327 punc->addChar(0,";");
328 punc->addChar(1,":");
329 punc->addChar(1,"\267");
330 punc->addChar(1,"\277");
331 punc->addChar(1,"\241");
332 punc->addChar(1,"\367");
333
334 punc->addChar(0,"$");
335 punc->addChar(0,"\242");
336 punc->addChar(0,"\245");
337 punc->addChar(1,"\243");
338 punc->addChar(1,"\244");
339 punc->addChar(1,"\260");
340
341 configs.append(punc);
342
343 KeycodeConfig* keys = new KeycodeConfig(this);
344 keys->addKey(0,QPixmap(Esc_xpm),Key_Escape);
345 keys->addKey(0,QPixmap(BS_xpm),Key_Backspace);
346 keys->addGap(0,10);
347
348 keys->addKey(0,QPixmap(Ins_xpm),Key_Insert);
349 keys->addKey(0,QPixmap(Home_xpm),Key_Home);
350 keys->addKey(0,QPixmap(PgUp_xpm),Key_PageUp);
351
352 keys->addGap(0,25);
353 keys->addKey(0,QPixmap(Up_xpm),Key_Up);
354 keys->addGap(0,15);
355
356 keys->addKey(1,QPixmap(BackTab_xpm),Key_Tab);
357 keys->addGap(1,3);
358 keys->addKey(1,QPixmap(Tab_xpm),Key_Tab);
359 keys->addGap(1,10);
360
361 keys->addKey(1,QPixmap(Del_xpm),Key_Delete);
362 keys->addGap(1,2);
363 keys->addKey(1,QPixmap(End_xpm),Key_End);
364 keys->addGap(1,3);
365 keys->addKey(1,QPixmap(PgDn_xpm),Key_PageDown);
366
367 keys->addGap(1,10);
368 keys->addKey(1,QPixmap(Left_xpm),Key_Left);
369 keys->addKey(1,QPixmap(Down_xpm),Key_Down);
370 keys->addKey(1,QPixmap(Right_xpm),Key_Right);
371
372 keys->addGap(1,13);
373 keys->addKey(1,QPixmap(Space_xpm),Key_Space);
374
375 keys->addGap(0,10);
376 keys->addKey(0,QPixmap(Enter_xpm),Key_Return);
377
378 configs.append(keys);
379}
380
381PickboardPicks::~PickboardPicks()
382{
383}
384
385QSize PickboardPicks::sizeHint() const
386{
387 return QSize(240,fontMetrics().lineSpacing()*2+3);
388}
389
390void PickboardPicks::drawContents(QPainter* p)
391{
392 config()->draw(p);
393}
394
395void PickboardPicks::mousePressEvent(QMouseEvent* e)
396{
397 config()->pickPoint(e->pos(),TRUE);
398}
399
400void PickboardPicks::mouseDoubleClickEvent(QMouseEvent* e)
401{
402 config()->pickPoint(e->pos(),TRUE);
403}
404
405void PickboardPicks::mouseReleaseEvent(QMouseEvent* e)
406{
407 config()->pickPoint(e->pos(),FALSE);
408}
409
410void PickboardPicks::setMode(int m)
411{
412 mode = m;
413}
414
415void PickboardPicks::resetState()
416{
417 config()->doMenu(100);
418}
diff --git a/inputmethods/pickboard/pickboardpicks.h b/inputmethods/pickboard/pickboardpicks.h
new file mode 100644
index 0000000..1881e92
--- a/dev/null
+++ b/inputmethods/pickboard/pickboardpicks.h
@@ -0,0 +1,66 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#ifndef PICKBOARDPICKS_H
21#define PICKBOARDPICKS_H
22
23#include <qframe.h>
24#include <qlist.h>
25
26// Internal stuff...
27
28class PickboardConfig;
29
30class PickboardPicks : public QFrame {
31 Q_OBJECT
32public:
33 PickboardPicks(QWidget* parent=0, const char* name=0, WFlags f=0);
34 ~PickboardPicks();
35 QSize sizeHint() const;
36 void initialise();
37 void setMode(int);
38 int currentMode() const { return mode; }
39
40 void mousePressEvent(QMouseEvent*);
41
42 void emitKey( ushort scan, ushort uni, ushort mod, bool press, bool repeat )
43 { key(scan,uni,mod,press, repeat); }
44 void resetState();
45
46signals:
47 void key( ushort scan, ushort uni, ushort mod, bool, bool );
48
49public slots:
50 void doMenu();
51
52protected:
53 void drawContents( QPainter * );
54 void mouseDoubleClickEvent(QMouseEvent*);
55 void mouseReleaseEvent(QMouseEvent*);
56
57protected:
58 int mode;
59 QList<PickboardConfig> configs;
60
61private:
62 PickboardConfig* config() { return configs.at(mode); }
63};
64
65
66#endif
diff --git a/inputmethods/pickboard/qpe-pickboard.control b/inputmethods/pickboard/qpe-pickboard.control
new file mode 100644
index 0000000..8d12181
--- a/dev/null
+++ b/inputmethods/pickboard/qpe-pickboard.control
@@ -0,0 +1,9 @@
1Files: plugins/inputmethods/libqpickboard.so*
2Priority: optional
3Section: qpe/inputmethods
4Maintainer: Warwick Allison <warwick@trolltech.com>
5Architecture: arm
6Version: $QPE_VERSION-3
7Depends: qpe-base ($QPE_VERSION)
8Description: Pickboard input method
9 Pickboard dictionary-based input method for the Qtopia environment.
diff --git a/inputmethods/pickboard/qpe-pickboard.postinst b/inputmethods/pickboard/qpe-pickboard.postinst
new file mode 100755
index 0000000..c254b01
--- a/dev/null
+++ b/inputmethods/pickboard/qpe-pickboard.postinst
@@ -0,0 +1,2 @@
1#!/bin/sh
2/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadInputMethods()"
diff --git a/inputmethods/pickboard/qpe-pickboard.postrm b/inputmethods/pickboard/qpe-pickboard.postrm
new file mode 100755
index 0000000..c254b01
--- a/dev/null
+++ b/inputmethods/pickboard/qpe-pickboard.postrm
@@ -0,0 +1,2 @@
1#!/bin/sh
2/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadInputMethods()"
diff --git a/inputmethods/unikeyboard/.cvsignore b/inputmethods/unikeyboard/.cvsignore
new file mode 100644
index 0000000..edfa921
--- a/dev/null
+++ b/inputmethods/unikeyboard/.cvsignore
@@ -0,0 +1,3 @@
1moc_*
2*.moc
3Makefile
diff --git a/inputmethods/unikeyboard/Makefile.in b/inputmethods/unikeyboard/Makefile.in
new file mode 100644
index 0000000..ebbab50
--- a/dev/null
+++ b/inputmethods/unikeyboard/Makefile.in
@@ -0,0 +1,115 @@
1#############################################################################
2
3####### Compiler, tools and options
4
5 CXX =$(SYSCONF_CXX) $(QT_CXX_MT)
6 CXXFLAGS=$(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB)
7 CC =$(SYSCONF_CC) $(QT_C_MT)
8 CFLAGS =$(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB)
9 INCPATH =-I$(QPEDIR)/include
10 LFLAGS =$(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
11 LIBS =$(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP)
12 MOC =$(SYSCONF_MOC)
13 UIC =$(SYSCONF_UIC)
14
15####### Target
16
17DESTDIR = ../../plugins/inputmethods/
18VER_MAJ = 1
19VER_MIN = 0
20VER_PATCH = 0
21 TARGET= qunikeyboard
22TARGET1 = lib$(TARGET).so.$(VER_MAJ)
23
24####### Files
25
26 HEADERS =unikeyboard.h \
27 unikeyboardimpl.h
28 SOURCES =unikeyboard.cpp \
29 unikeyboardimpl.cpp
30 OBJECTS =unikeyboard.o \
31 unikeyboardimpl.o
32INTERFACES =
33UICDECLS =
34UICIMPLS =
35 SRCMOC =moc_unikeyboard.cpp
36 OBJMOC =moc_unikeyboard.o
37
38
39####### Implicit rules
40
41.SUFFIXES: .cpp .cxx .cc .C .c
42
43.cpp.o:
44 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
45
46.cxx.o:
47 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
48
49.cc.o:
50 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
51
52.C.o:
53 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
54
55.c.o:
56 $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
57
58####### Build rules
59
60
61all: $(DESTDIR)$(SYSCONF_LINK_TARGET)
62
63$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
64 $(SYSCONF_LINK_LIB)
65
66moc: $(SRCMOC)
67
68tmake:
69 tmake unikeyboard.pro
70
71clean:
72 -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
73 -rm -f *~ core
74 -rm -f allmoc.cpp
75
76####### Extension Modules
77
78listpromodules:
79 @echo
80
81listallmodules:
82 @echo
83
84listaddonpromodules:
85 @echo
86
87listaddonentmodules:
88 @echo
89
90
91REQUIRES=
92
93####### Sub-libraries
94
95
96###### Combined headers
97
98
99
100####### Compile
101
102unikeyboard.o: unikeyboard.cpp \
103 unikeyboard.h
104
105unikeyboardimpl.o: unikeyboardimpl.cpp \
106 unikeyboard.h \
107 unikeyboardimpl.h
108
109moc_unikeyboard.o: moc_unikeyboard.cpp \
110 unikeyboard.h
111
112moc_unikeyboard.cpp: unikeyboard.h
113 $(MOC) unikeyboard.h -o moc_unikeyboard.cpp
114
115
diff --git a/inputmethods/unikeyboard/qpe-unikeyboard.control b/inputmethods/unikeyboard/qpe-unikeyboard.control
new file mode 100644
index 0000000..a8c9bd3
--- a/dev/null
+++ b/inputmethods/unikeyboard/qpe-unikeyboard.control
@@ -0,0 +1,9 @@
1Files: plugins/inputmethods/libqunikeyboard.so*
2Priority: optional
3Section: qpe/inputmethods
4Maintainer: Warwick Allison <warwick@trolltech.com>
5Architecture: arm
6Version: $QPE_VERSION-3
7Depends: qpe-base ($QPE_VERSION)
8Description: Unicode input method
9 Basic unicode input method for the Qtopia environment.
diff --git a/inputmethods/unikeyboard/qpe-unikeyboard.postinst b/inputmethods/unikeyboard/qpe-unikeyboard.postinst
new file mode 100755
index 0000000..c254b01
--- a/dev/null
+++ b/inputmethods/unikeyboard/qpe-unikeyboard.postinst
@@ -0,0 +1,2 @@
1#!/bin/sh
2/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadInputMethods()"
diff --git a/inputmethods/unikeyboard/qpe-unikeyboard.postrm b/inputmethods/unikeyboard/qpe-unikeyboard.postrm
new file mode 100755
index 0000000..c254b01
--- a/dev/null
+++ b/inputmethods/unikeyboard/qpe-unikeyboard.postrm
@@ -0,0 +1,2 @@
1#!/bin/sh
2/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadInputMethods()"
diff --git a/inputmethods/unikeyboard/unikeyboard.cpp b/inputmethods/unikeyboard/unikeyboard.cpp
new file mode 100644
index 0000000..aa74c66
--- a/dev/null
+++ b/inputmethods/unikeyboard/unikeyboard.cpp
@@ -0,0 +1,278 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "unikeyboard.h"
22
23#include <qpe/fontmanager.h>
24
25#include <qpainter.h>
26#include <qfontmetrics.h>
27#include <qcombobox.h>
28#if defined(Q_WS_QWS) || defined(_WS_QWS_)
29#include <qwindowsystem_qws.h>
30#endif
31
32static const int nw = 8;
33
34typedef struct BlockMap {
35 ushort start;
36 ushort stop;
37 const char *name;
38};
39
40//# Start Code; Block Name
41
42static const BlockMap blockMap[] =
43{
44{0x0000, 0x007F, "Basic Latin"},
45{0x0080, 0x00FF, "Latin-1 Supplement"},
46{0x0100, 0x017F, "Latin Extended-A"},
47{0x0180, 0x024F, "Latin Extended-B"},
48{0x0250, 0x02AF, "IPA Extensions"},
49{0x02B0, 0x02FF, "Spacing Modifier Letters"},
50{0x0300, 0x036F, "Combining Diacritical Marks"},
51{0x0370, 0x03FF, "Greek"},
52{0x0400, 0x04FF, "Cyrillic"},
53{0x0530, 0x058F, "Armenian"},
54{0x0590, 0x05FF, "Hebrew"},
55{0x0600, 0x06FF, "Arabic"},
56{0x0700, 0x074F, "Syriac "},
57{0x0780, 0x07BF, "Thaana"},
58{0x0900, 0x097F, "Devanagari"},
59{0x0980, 0x09FF, "Bengali"},
60{0x0A00, 0x0A7F, "Gurmukhi"},
61{0x0A80, 0x0AFF, "Gujarati"},
62{0x0B00, 0x0B7F, "Oriya"},
63{0x0B80, 0x0BFF, "Tamil"},
64{0x0C00, 0x0C7F, "Telugu"},
65{0x0C80, 0x0CFF, "Kannada"},
66{0x0D00, 0x0D7F, "Malayalam"},
67{0x0D80, 0x0DFF, "Sinhala"},
68{0x0E00, 0x0E7F, "Thai"},
69{0x0E80, 0x0EFF, "Lao"},
70{0x0F00, 0x0FFF, "Tibetan"},
71{0x1000, 0x109F, "Myanmar "},
72{0x10A0, 0x10FF, "Georgian"},
73{0x1100, 0x11FF, "Hangul Jamo"},
74{0x1200, 0x137F, "Ethiopic"},
75{0x13A0, 0x13FF, "Cherokee"},
76{0x1400, 0x167F, "Unified Canadian Aboriginal Syllabics"},
77{0x1680, 0x169F, "Ogham"},
78{0x16A0, 0x16FF, "Runic"},
79{0x1780, 0x17FF, "Khmer"},
80{0x1800, 0x18AF, "Mongolian"},
81{0x1E00, 0x1EFF, "Latin Extended Additional"},
82{0x1F00, 0x1FFF, "Greek Extended"},
83{0x2000, 0x206F, "General Punctuation"},
84{0x2070, 0x209F, "Superscripts and Subscripts"},
85{0x20A0, 0x20CF, "Currency Symbols"},
86{0x20D0, 0x20FF, "Combining Marks for Symbols"},
87{0x2100, 0x214F, "Letterlike Symbols"},
88{0x2150, 0x218F, "Number Forms"},
89{0x2190, 0x21FF, "Arrows"},
90{0x2200, 0x22FF, "Mathematical Operators"},
91{0x2300, 0x23FF, "Miscellaneous Technical"},
92{0x2400, 0x243F, "Control Pictures"},
93{0x2440, 0x245F, "Optical Character Recognition"},
94{0x2460, 0x24FF, "Enclosed Alphanumerics"},
95{0x2500, 0x257F, "Box Drawing"},
96{0x2580, 0x259F, "Block Elements"},
97{0x25A0, 0x25FF, "Geometric Shapes"},
98{0x2600, 0x26FF, "Miscellaneous Symbols"},
99{0x2700, 0x27BF, "Dingbats"},
100{0x2800, 0x28FF, "Braille Patterns"},
101{0x2E80, 0x2EFF, "CJK Radicals Supplement"},
102{0x2F00, 0x2FDF, "Kangxi Radicals"},
103{0x2FF0, 0x2FFF, "Ideographic Description Characters"},
104{0x3000, 0x303F, "CJK Symbols and Punctuation"},
105{0x3040, 0x309F, "Hiragana"},
106{0x30A0, 0x30FF, "Katakana"},
107{0x3100, 0x312F, "Bopomofo"},
108{0x3130, 0x318F, "Hangul Compatibility Jamo"},
109{0x3190, 0x319F, "Kanbun"},
110{0x31A0, 0x31BF, "Bopomofo Extended"},
111{0x3200, 0x32FF, "Enclosed CJK Letters and Months"},
112{0x3300, 0x33FF, "CJK Compatibility"},
113{0x3400, 0x4DB5, "CJK Unified Ideographs Extension A"},
114{0x4E00, 0x9FFF, "CJK Unified Ideographs"},
115{0xA000, 0xA48F, "Yi Syllables"},
116{0xA490, 0xA4CF, "Yi Radicals"},
117{0xAC00, 0xD7A3, "Hangul Syllables"},
118{0xD800, 0xDB7F, "High Surrogates"},
119{0xDB80, 0xDBFF, "High Private Use Surrogates"},
120{0xDC00, 0xDFFF, "Low Surrogates"},
121{0xE000, 0xF8FF, "Private Use"},
122{0xF900, 0xFAFF, "CJK Compatibility Ideographs"},
123{0xFB00, 0xFB4F, "Alphabetic Presentation Forms"},
124{0xFB50, 0xFDFF, "Arabic Presentation Forms-A"},
125{0xFE20, 0xFE2F, "Combining Half Marks"},
126{0xFE30, 0xFE4F, "CJK Compatibility Forms"},
127{0xFE50, 0xFE6F, "Small Form Variants"},
128{0xFE70, 0xFEFE, "Arabic Presentation Forms-B"},
129{0xFF00, 0xFEFF, "Halfwidth and Fullwidth Forms"},
130{0xFFF0, 0xFFEF, "Specials"},
131 {0xFFFF, 0xFFFF, 0} };
132
133
134UniScrollview::UniScrollview(QWidget* parent, const char* name, int f) :
135 QScrollView(parent, name, f)
136{
137 // smallFont.setRawName( "-adobe-courier-medium-r-normal--10-100-75-75-m-60-iso8859-1" ); //######
138 smallFont = QFont( "Helvetica", 8 );
139 QFontMetrics sfm( smallFont );
140 xoff = sfm.width( "AAA" );
141 setFont( FontManager::unicodeFont( FontManager::Fixed ) );
142 QFontMetrics fm( font() );
143 cellsize = fm.lineSpacing() + 2;
144 resizeContents( cellsize*nw, cellsize*65536/nw );
145 verticalScrollBar()->setLineStep(cellsize);
146
147 viewport()->setBackgroundMode( QWidget::PaletteBase );
148}
149
150
151
152void UniScrollview::contentsMousePressEvent(QMouseEvent* e)
153{
154 if ( e->x() < xoff || e->x() > xoff + nw*cellsize )
155 return;
156 int row = e->y()/cellsize;
157 int col = (e->x()-xoff)/cellsize;
158 int u = row*nw+col;
159#if defined(Q_WS_QWS) || defined(_WS_QWS_)
160 emit key( u, 0, 0, true, false );
161 emit key( u, 0, 0, false, false );
162#endif
163}
164
165
166void UniScrollview::contentsMouseReleaseEvent(QMouseEvent*)
167{
168}
169
170void UniScrollview::scrollTo( int unicode )
171{
172 int row = unicode / nw;
173 setContentsPos( 0, row*cellsize );
174}
175
176
177void UniScrollview::drawContents( QPainter *p, int /*cx*/, int cy, int /*cw*/, int ch )
178{
179 QFontMetrics fm = fontMetrics();
180 int row = cy / cellsize;
181 int y = row*cellsize;
182 while ( y < cy+ch ) {
183 p->drawLine( xoff, y, xoff+nw*cellsize, y );
184 if ( row*nw%16 == 0 ) {
185 p->setFont( smallFont );
186 QString s;
187 s.sprintf( "%03X", row*nw/16 );
188 p->drawText( 0, y, xoff, cellsize, AlignLeft, s );
189 p->setFont( font() );
190 }
191 for ( int i = 0; i < nw; i++ ) {
192 p->drawLine( xoff+i*cellsize, y, xoff+i*cellsize, y+cellsize );
193 QChar u = row*nw + i;
194 if ( fm.inFont( u ) )
195 p->drawText( xoff+i*cellsize, y, cellsize, cellsize, AlignCenter,
196 u );
197 }
198 p->drawLine( xoff+nw*cellsize, y, xoff+nw*cellsize, y+cellsize );
199 row++;
200 y += cellsize;
201 }
202}
203
204
205
206
207UniKeyboard::UniKeyboard(QWidget* parent, const char* name, int f )
208 : QFrame( parent, name, f )
209{
210 setFrameStyle( NoFrame );
211 sv = new UniScrollview( this );
212 cb = new QComboBox( FALSE, this );
213 currentBlock = 0;
214 QFontMetrics fm = sv->fontMetrics();
215 cbmap = new int[sizeof(blockMap)/sizeof(blockMap[0])];
216 for ( int i = 0; blockMap[i].name; i++ ) {
217 bool any=FALSE;
218 for ( int c=blockMap[i].start; !any && c<=blockMap[i].stop; c++ )
219 any = fm.inFont(QChar(c));
220 if ( any ) {
221 cbmap[cb->count()]=i;
222 cb->insertItem( blockMap[i].name );
223 }
224 }
225 connect( cb, SIGNAL( activated(int)), this, SLOT( handleCombo(int)) );
226 connect( sv, SIGNAL( contentsMoving(int,int)), this, SLOT( svMove(int,int)) );
227 connect( sv, SIGNAL( key(ushort,ushort,ushort,bool,bool)),
228 this, SIGNAL( key(ushort,ushort,ushort,bool,bool)) );
229}
230
231UniKeyboard::~UniKeyboard()
232{
233 delete [] cbmap;
234}
235
236void UniKeyboard::resizeEvent(QResizeEvent *)
237{
238 int d = frameWidth();
239 cb->setGeometry( d, d, width()-2*d, cb->sizeHint().height() );
240 sv->setGeometry( d, cb->height()+d, width()-2*d, height()-cb->height()-2*d );
241}
242
243void UniKeyboard::svMove( int /*x*/, int y )
244{
245 int cs = sv->cellSize();
246 int u = ((y+cs-1)/cs) * nw;
247 int i = currentBlock;
248 while ( i > 0 && blockMap[i].start > u ) {
249 i--;
250 }
251 while ( blockMap[i+1].name && blockMap[i+1].start < u ) {
252 i++;
253 }
254 if ( i != currentBlock ) {
255 currentBlock = i;
256 for (int ind=0; ind<cb->count(); ind++) {
257 if ( cbmap[ind] == i ) {
258 cb->setCurrentItem( ind );
259 break;
260 }
261 }
262 }
263}
264
265void UniKeyboard::handleCombo( int i )
266{
267 currentBlock = cbmap[i];
268 sv->scrollTo( blockMap[currentBlock].start );
269}
270
271void UniKeyboard::resetState()
272{
273}
274
275QSize UniKeyboard::sizeHint() const
276{
277 return QSize( 240, 2+sv->cellSize()*4+cb->sizeHint().height() );
278}
diff --git a/inputmethods/unikeyboard/unikeyboard.h b/inputmethods/unikeyboard/unikeyboard.h
new file mode 100644
index 0000000..1a716c0
--- a/dev/null
+++ b/inputmethods/unikeyboard/unikeyboard.h
@@ -0,0 +1,77 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#include <qscrollview.h>
21
22class QComboBox;
23
24class UniScrollview : public QScrollView {
25 Q_OBJECT
26public:
27 UniScrollview(QWidget* parent=0, const char* name=0, int f=0);
28 int cellSize() const { return cellsize; }
29
30signals:
31 void key( ushort unicode, ushort scancode, ushort modifiers, bool, bool );
32
33public slots:
34 void scrollTo( int unicode );
35
36protected:
37 void contentsMousePressEvent(QMouseEvent*);
38 void contentsMouseReleaseEvent(QMouseEvent*);
39 void drawContents( QPainter *, int cx, int cy, int cw, int ch ) ;
40
41private:
42 int cellsize;
43 QFont smallFont;
44 int xoff;
45};
46
47
48class UniKeyboard : public QFrame
49{
50 Q_OBJECT
51public:
52 UniKeyboard(QWidget* parent=0, const char* name=0, int f=0);
53 ~UniKeyboard();
54
55 void resetState();
56
57 QSize sizeHint() const;
58
59signals:
60 void key( ushort, ushort, ushort, bool, bool );
61
62protected:
63 void resizeEvent(QResizeEvent *);
64
65private slots:
66 void handleCombo( int );
67 void svMove( int, int );
68
69private:
70 UniScrollview *sv;
71 QComboBox *cb;
72 int currentBlock;
73 int* cbmap;
74};
75
76
77
diff --git a/inputmethods/unikeyboard/unikeyboard.pro b/inputmethods/unikeyboard/unikeyboard.pro
new file mode 100644
index 0000000..c0aad42
--- a/dev/null
+++ b/inputmethods/unikeyboard/unikeyboard.pro
@@ -0,0 +1,12 @@
1 TEMPLATE= lib
2 CONFIG += qt warn_on release
3 HEADERS= unikeyboard.h unikeyboardimpl.h
4 SOURCES= unikeyboard.cpp unikeyboardimpl.cpp
5 TARGET = qunikeyboard
6 DESTDIR = ../../plugins/inputmethods
7INCLUDEPATH += $(QPEDIR)/include
8DEPENDPATH += ../$(QPEDIR)/include ../../taskbar
9LIBS += -lqpe
10 VERSION = 1.0.0
11
12TRANSLATIONS += ../../i18n/de/libqunikeyboard.ts
diff --git a/inputmethods/unikeyboard/unikeyboardimpl.cpp b/inputmethods/unikeyboard/unikeyboardimpl.cpp
new file mode 100644
index 0000000..fe601e0
--- a/dev/null
+++ b/inputmethods/unikeyboard/unikeyboardimpl.cpp
@@ -0,0 +1,105 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#include <qapplication.h>
21#include <qobject.h>
22#include <qpixmap.h>
23#include "unikeyboard.h"
24#include "unikeyboardimpl.h"
25
26/* XPM */
27static const char * uni_xpm[]={
28"28 13 2 1",
29"# c #000000",
30". c None",
31"............................",
32"...####....#####.....####...",
33"...####....######....####...",
34"...####....#######..........",
35"...####....########..####...",
36"...####....####.####.####...",
37"...####....####..########...",
38"...####....####...#######...",
39"...####....####....######...",
40"...#####..#####.....#####...",
41"....##########.......####...",
42"......######..........###...",
43"............................"};
44
45UniKeyboardImpl::UniKeyboardImpl()
46 : input(0), icn(0), ref(0)
47{
48}
49
50UniKeyboardImpl::~UniKeyboardImpl()
51{
52 delete input;
53 delete icn;
54}
55
56QWidget *UniKeyboardImpl::inputMethod( QWidget *parent, Qt::WFlags f )
57{
58 if ( !input )
59 input = new UniKeyboard( parent, "UniKeyboard", f );
60 return input;
61}
62
63void UniKeyboardImpl::resetState()
64{
65 if ( input )
66 input->resetState();
67}
68
69QPixmap *UniKeyboardImpl::icon()
70{
71 if ( !icn )
72 icn = new QPixmap( (const char **)uni_xpm );
73 return icn;
74}
75
76QString UniKeyboardImpl::name()
77{
78 return qApp->translate( "InputMethods", "Unicode" );
79}
80
81void UniKeyboardImpl::onKeyPress( QObject *receiver, const char *slot )
82{
83 if ( input )
84 QObject::connect( input, SIGNAL(key(ushort,ushort,ushort,bool,bool)), receiver, slot );
85}
86
87QRESULT UniKeyboardImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface )
88{
89 *iface = 0;
90 if ( uuid == IID_QUnknown )
91 *iface = this;
92 else if ( uuid == IID_InputMethod )
93 *iface = this;
94
95 if ( *iface )
96 (*iface)->addRef();
97 return QS_OK;
98}
99
100Q_EXPORT_INTERFACE()
101{
102 Q_CREATE_INSTANCE( UniKeyboardImpl )
103}
104
105
diff --git a/inputmethods/unikeyboard/unikeyboardimpl.h b/inputmethods/unikeyboard/unikeyboardimpl.h
new file mode 100644
index 0000000..97b1ff6
--- a/dev/null
+++ b/inputmethods/unikeyboard/unikeyboardimpl.h
@@ -0,0 +1,49 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia 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** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#ifndef UNIKEYBOARDIMPL_H
21#define UNIKEYBOARDIMPL_H
22
23#include <qpe/inputmethodinterface.h>
24
25class UniKeyboard;
26class QPixmap;
27
28class UniKeyboardImpl : public InputMethodInterface
29{
30public:
31 UniKeyboardImpl();
32 virtual ~UniKeyboardImpl();
33
34 QRESULT queryInterface( const QUuid&, QUnknownInterface** );
35 Q_REFCOUNT
36
37 virtual QWidget *inputMethod( QWidget *parent, Qt::WFlags f );
38 virtual void resetState();
39 virtual QPixmap *icon();
40 virtual QString name();
41 virtual void onKeyPress( QObject *receiver, const char *slot );
42
43private:
44 UniKeyboard *input;
45 QPixmap *icn;
46 ulong ref;
47};
48
49#endif