summaryrefslogtreecommitdiff
path: root/noncore/unsupported
authormickeyl <mickeyl>2004-11-16 19:14:18 (UTC)
committer mickeyl <mickeyl>2004-11-16 19:14:18 (UTC)
commitea3945a9bd8f9830f70b1efa133f9df13b19362f (patch) (unidiff)
treef2ea22cc50e9aa8aa73ee7dea148f41c563c9666 /noncore/unsupported
parent1c6f490e8541626f68422e0a3a7c7281d7f5b7d3 (diff)
downloadopie-ea3945a9bd8f9830f70b1efa133f9df13b19362f.zip
opie-ea3945a9bd8f9830f70b1efa133f9df13b19362f.tar.gz
opie-ea3945a9bd8f9830f70b1efa133f9df13b19362f.tar.bz2
libopie1 goes into unsupported
Diffstat (limited to 'noncore/unsupported') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/unsupported/libopie/.cvsignore7
-rw-r--r--noncore/unsupported/libopie/colordialog.cpp856
-rw-r--r--noncore/unsupported/libopie/colordialog.h90
-rw-r--r--noncore/unsupported/libopie/colorpopupmenu.cpp172
-rw-r--r--noncore/unsupported/libopie/colorpopupmenu.h255
-rw-r--r--noncore/unsupported/libopie/config.in4
-rw-r--r--noncore/unsupported/libopie/libopie.pro102
-rw-r--r--noncore/unsupported/libopie/libopie1.control11
-rwxr-xr-xnoncore/unsupported/libopie/libopie1.postinst4
-rw-r--r--noncore/unsupported/libopie/oapplicationfactory.h264
-rw-r--r--noncore/unsupported/libopie/ocheckitem.cpp105
-rw-r--r--noncore/unsupported/libopie/ocheckitem.h62
-rw-r--r--noncore/unsupported/libopie/oclickablelabel.cpp117
-rw-r--r--noncore/unsupported/libopie/oclickablelabel.h68
-rw-r--r--noncore/unsupported/libopie/ocolorbutton.cpp139
-rw-r--r--noncore/unsupported/libopie/ocolorbutton.h73
-rw-r--r--noncore/unsupported/libopie/odevice.cpp2827
-rw-r--r--noncore/unsupported/libopie/odevice.h302
-rw-r--r--noncore/unsupported/libopie/odevicebutton.cpp237
-rw-r--r--noncore/unsupported/libopie/odevicebutton.h107
-rw-r--r--noncore/unsupported/libopie/ofiledialog.cc212
-rw-r--r--noncore/unsupported/libopie/ofiledialog.h101
-rw-r--r--noncore/unsupported/libopie/ofileselector.cpp929
-rw-r--r--noncore/unsupported/libopie/ofileselector.h210
-rw-r--r--noncore/unsupported/libopie/ofileselector_p.h151
-rw-r--r--noncore/unsupported/libopie/ofileview.h87
-rw-r--r--noncore/unsupported/libopie/ofontmenu.cc156
-rw-r--r--noncore/unsupported/libopie/ofontmenu.h113
-rw-r--r--noncore/unsupported/libopie/ofontselector.cpp411
-rw-r--r--noncore/unsupported/libopie/ofontselector.h96
-rw-r--r--noncore/unsupported/libopie/oprocctrl.cpp267
-rw-r--r--noncore/unsupported/libopie/oprocctrl.h121
-rw-r--r--noncore/unsupported/libopie/oprocess.cpp925
-rw-r--r--noncore/unsupported/libopie/oprocess.h747
-rw-r--r--noncore/unsupported/libopie/orecurrancebase.ui713
-rw-r--r--noncore/unsupported/libopie/orecurrancewidget.cpp632
-rw-r--r--noncore/unsupported/libopie/orecurrancewidget.h93
-rw-r--r--noncore/unsupported/libopie/otabbar.cpp81
-rw-r--r--noncore/unsupported/libopie/otabbar.h80
-rw-r--r--noncore/unsupported/libopie/otabinfo.h134
-rw-r--r--noncore/unsupported/libopie/otabwidget.cpp419
-rw-r--r--noncore/unsupported/libopie/otabwidget.h285
-rw-r--r--noncore/unsupported/libopie/oticker.cpp132
-rw-r--r--noncore/unsupported/libopie/oticker.h148
-rw-r--r--noncore/unsupported/libopie/otimepicker.cpp242
-rw-r--r--noncore/unsupported/libopie/otimepicker.h86
-rw-r--r--noncore/unsupported/libopie/otimepickerbase.ui292
-rw-r--r--noncore/unsupported/libopie/owait.cpp91
-rw-r--r--noncore/unsupported/libopie/owait.h77
-rw-r--r--noncore/unsupported/libopie/pim/.cvsignore2
-rw-r--r--noncore/unsupported/libopie/pim/config.in2
-rw-r--r--noncore/unsupported/libopie/pim/libopie.pro64
-rw-r--r--noncore/unsupported/libopie/pim/obackendfactory.h197
-rw-r--r--noncore/unsupported/libopie/pim/ocontact.cpp1207
-rw-r--r--noncore/unsupported/libopie/pim/ocontact.h240
-rw-r--r--noncore/unsupported/libopie/pim/ocontactaccess.cpp176
-rw-r--r--noncore/unsupported/libopie/pim/ocontactaccess.h196
-rw-r--r--noncore/unsupported/libopie/pim/ocontactaccessbackend.h131
-rw-r--r--noncore/unsupported/libopie/pim/ocontactaccessbackend_sql.cpp948
-rw-r--r--noncore/unsupported/libopie/pim/ocontactaccessbackend_sql.h110
-rw-r--r--noncore/unsupported/libopie/pim/ocontactaccessbackend_vcard.cpp649
-rw-r--r--noncore/unsupported/libopie/pim/ocontactaccessbackend_vcard.h99
-rw-r--r--noncore/unsupported/libopie/pim/ocontactaccessbackend_xml.cpp824
-rw-r--r--noncore/unsupported/libopie/pim/ocontactaccessbackend_xml.h163
-rw-r--r--noncore/unsupported/libopie/pim/ocontactfields.cpp477
-rw-r--r--noncore/unsupported/libopie/pim/ocontactfields.h67
-rw-r--r--noncore/unsupported/libopie/pim/oconversion.cpp113
-rw-r--r--noncore/unsupported/libopie/pim/oconversion.h48
-rw-r--r--noncore/unsupported/libopie/pim/odatebookaccess.cpp81
-rw-r--r--noncore/unsupported/libopie/pim/odatebookaccess.h44
-rw-r--r--noncore/unsupported/libopie/pim/odatebookaccessbackend.cpp182
-rw-r--r--noncore/unsupported/libopie/pim/odatebookaccessbackend.h90
-rw-r--r--noncore/unsupported/libopie/pim/odatebookaccessbackend_sql.cpp374
-rw-r--r--noncore/unsupported/libopie/pim/odatebookaccessbackend_sql.h65
-rw-r--r--noncore/unsupported/libopie/pim/odatebookaccessbackend_xml.cpp612
-rw-r--r--noncore/unsupported/libopie/pim/odatebookaccessbackend_xml.h55
-rw-r--r--noncore/unsupported/libopie/pim/oevent.cpp717
-rw-r--r--noncore/unsupported/libopie/pim/oevent.h236
-rw-r--r--noncore/unsupported/libopie/pim/opimaccessbackend.h160
-rw-r--r--noncore/unsupported/libopie/pim/opimaccesstemplate.h302
-rw-r--r--noncore/unsupported/libopie/pim/opimcache.h131
-rw-r--r--noncore/unsupported/libopie/pim/opimmaintainer.cpp37
-rw-r--r--noncore/unsupported/libopie/pim/opimmaintainer.h40
-rw-r--r--noncore/unsupported/libopie/pim/opimmainwindow.cpp150
-rw-r--r--noncore/unsupported/libopie/pim/opimmainwindow.h99
-rw-r--r--noncore/unsupported/libopie/pim/opimnotify.cpp227
-rw-r--r--noncore/unsupported/libopie/pim/opimnotify.h144
-rw-r--r--noncore/unsupported/libopie/pim/opimnotifymanager.cpp162
-rw-r--r--noncore/unsupported/libopie/pim/opimnotifymanager.h91
-rw-r--r--noncore/unsupported/libopie/pim/opimrecord.cpp182
-rw-r--r--noncore/unsupported/libopie/pim/opimrecord.h158
-rw-r--r--noncore/unsupported/libopie/pim/opimresolver.cpp198
-rw-r--r--noncore/unsupported/libopie/pim/opimresolver.h90
-rw-r--r--noncore/unsupported/libopie/pim/opimstate.cpp64
-rw-r--r--noncore/unsupported/libopie/pim/opimstate.h46
-rw-r--r--noncore/unsupported/libopie/pim/opimxref.cpp47
-rw-r--r--noncore/unsupported/libopie/pim/opimxref.h39
-rw-r--r--noncore/unsupported/libopie/pim/opimxrefmanager.cpp71
-rw-r--r--noncore/unsupported/libopie/pim/opimxrefmanager.h43
-rw-r--r--noncore/unsupported/libopie/pim/opimxrefpartner.cpp43
-rw-r--r--noncore/unsupported/libopie/pim/opimxrefpartner.h40
-rw-r--r--noncore/unsupported/libopie/pim/orecordlist.h306
-rw-r--r--noncore/unsupported/libopie/pim/orecur.cpp593
-rw-r--r--noncore/unsupported/libopie/pim/orecur.h107
-rw-r--r--noncore/unsupported/libopie/pim/otemplatebase.h98
-rw-r--r--noncore/unsupported/libopie/pim/otimezone.cpp113
-rw-r--r--noncore/unsupported/libopie/pim/otimezone.h71
-rw-r--r--noncore/unsupported/libopie/pim/otodo.cpp519
-rw-r--r--noncore/unsupported/libopie/pim/otodo.h285
-rw-r--r--noncore/unsupported/libopie/pim/otodoaccess.cpp62
-rw-r--r--noncore/unsupported/libopie/pim/otodoaccess.h105
-rw-r--r--noncore/unsupported/libopie/pim/otodoaccessbackend.cpp10
-rw-r--r--noncore/unsupported/libopie/pim/otodoaccessbackend.h28
-rw-r--r--noncore/unsupported/libopie/pim/otodoaccesssql.cpp694
-rw-r--r--noncore/unsupported/libopie/pim/otodoaccesssql.h61
-rw-r--r--noncore/unsupported/libopie/pim/otodoaccessvcal.cpp249
-rw-r--r--noncore/unsupported/libopie/pim/otodoaccessvcal.h40
-rw-r--r--noncore/unsupported/libopie/pim/otodoaccessxml.cpp876
-rw-r--r--noncore/unsupported/libopie/pim/otodoaccessxml.h60
-rw-r--r--noncore/unsupported/libopie/sharp_compat.cpp18
-rw-r--r--noncore/unsupported/libopie/todayconfigwidget.h39
-rw-r--r--noncore/unsupported/libopie/todayplugininterface.h133
-rw-r--r--noncore/unsupported/libopie/xmltree.cc322
-rw-r--r--noncore/unsupported/libopie/xmltree.h119
124 files changed, 29474 insertions, 0 deletions
diff --git a/noncore/unsupported/libopie/.cvsignore b/noncore/unsupported/libopie/.cvsignore
new file mode 100644
index 0000000..f76e42e
--- a/dev/null
+++ b/noncore/unsupported/libopie/.cvsignore
@@ -0,0 +1,7 @@
1*.moc
2Makefile*
3moc_*
4orecurrancebase.cpp
5orecurrancebase.h
6otimepickerbase.cpp
7otimepickerbase.h
diff --git a/noncore/unsupported/libopie/colordialog.cpp b/noncore/unsupported/libopie/colordialog.cpp
new file mode 100644
index 0000000..b2854a6
--- a/dev/null
+++ b/noncore/unsupported/libopie/colordialog.cpp
@@ -0,0 +1,856 @@
1/****************************************************************************
2** $Id$
3**
4** Implementation of OColorDialog class
5**
6** Created : 990222
7**
8** Copyright (C) 1999-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the dialogs module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "colordialog.h"
39
40#include "qpainter.h"
41#include "qlayout.h"
42#include "qlabel.h"
43#include "qpushbutton.h"
44#include "qlineedit.h"
45#include "qimage.h"
46#include "qpixmap.h"
47#include "qdrawutil.h"
48#include "qvalidator.h"
49#include "qapplication.h"
50
51static inline void rgb2hsv( QRgb rgb, int&h, int&s, int&v )
52{
53 QColor c;
54 c.setRgb( rgb );
55 c.getHsv(h,s,v);
56}
57
58/*
59 * avoid clashes with the original Qt
60 */
61namespace {
62
63class QColorPicker : public QFrame
64{
65 Q_OBJECT
66public:
67 QColorPicker(QWidget* parent=0, const char* name=0);
68 ~QColorPicker();
69
70public slots:
71 void setCol( int h, int s );
72
73signals:
74 void newCol( int h, int s );
75
76protected:
77 QSize sizeHint() const;
78 QSizePolicy sizePolicy() const;
79 void drawContents(QPainter* p);
80 void mouseMoveEvent( QMouseEvent * );
81 void mousePressEvent( QMouseEvent * );
82
83private:
84 int hue;
85 int sat;
86
87 QPoint colPt();
88 int huePt( const QPoint &pt );
89 int satPt( const QPoint &pt );
90 void setCol( const QPoint &pt );
91
92 QPixmap *pix;
93};
94
95static int pWidth = 200;
96static int pHeight = 200;
97
98class QColorLuminancePicker : public QWidget
99{
100 Q_OBJECT
101public:
102 QColorLuminancePicker(QWidget* parent=0, const char* name=0);
103 ~QColorLuminancePicker();
104
105public slots:
106 void setCol( int h, int s, int v );
107 void setCol( int h, int s );
108
109signals:
110 void newHsv( int h, int s, int v );
111
112protected:
113// QSize sizeHint() const;
114// QSizePolicy sizePolicy() const;
115 void paintEvent( QPaintEvent*);
116 void mouseMoveEvent( QMouseEvent * );
117 void mousePressEvent( QMouseEvent * );
118
119private:
120 enum { foff = 3, coff = 4 }; //frame and contents offset
121 int val;
122 int hue;
123 int sat;
124
125 int y2val( int y );
126 int val2y( int val );
127 void setVal( int v );
128
129 QPixmap *pix;
130};
131
132
133int QColorLuminancePicker::y2val( int y )
134{
135 int d = height() - 2*coff - 1;
136 return 255 - (y - coff)*255/d;
137}
138
139int QColorLuminancePicker::val2y( int v )
140{
141 int d = height() - 2*coff - 1;
142 return coff + (255-v)*d/255;
143}
144
145QColorLuminancePicker::QColorLuminancePicker(QWidget* parent,
146 const char* name)
147 :QWidget( parent, name )
148{
149 hue = 100; val = 100; sat = 100;
150 pix = 0;
151 // setBackgroundMode( NoBackground );
152}
153
154QColorLuminancePicker::~QColorLuminancePicker()
155{
156 delete pix;
157}
158
159void QColorLuminancePicker::mouseMoveEvent( QMouseEvent *m )
160{
161 setVal( y2val(m->y()) );
162}
163void QColorLuminancePicker::mousePressEvent( QMouseEvent *m )
164{
165 setVal( y2val(m->y()) );
166}
167
168void QColorLuminancePicker::setVal( int v )
169{
170 if ( val == v )
171 return;
172 val = QMAX( 0, QMIN(v,255));
173 delete pix; pix=0;
174 repaint( FALSE ); //###
175 emit newHsv( hue, sat, val );
176}
177
178//receives from a hue,sat chooser and relays.
179void QColorLuminancePicker::setCol( int h, int s )
180{
181 setCol( h, s, val );
182 emit newHsv( h, s, val );
183}
184
185void QColorLuminancePicker::paintEvent( QPaintEvent * )
186{
187 int w = width() - 5;
188
189 QRect r( 0, foff, w, height() - 2*foff );
190 int wi = r.width() - 2;
191 int hi = r.height() - 2;
192 if ( !pix || pix->height() != hi || pix->width() != wi ) {
193 delete pix;
194 QImage img( wi, hi, 32 );
195 int y;
196 for ( y = 0; y < hi; y++ ) {
197 QColor c( hue, sat, y2val(y+coff), QColor::Hsv );
198 QRgb r = c.rgb();
199 int x;
200 for ( x = 0; x < wi; x++ )
201 img.setPixel( x, y, r );
202 }
203 pix = new QPixmap;
204 pix->convertFromImage(img);
205 }
206 QPainter p(this);
207 p.drawPixmap( 1, coff, *pix );
208 QColorGroup g = colorGroup();
209 qDrawShadePanel( &p, r, g, TRUE );
210 p.setPen( g.foreground() );
211 p.setBrush( g.foreground() );
212 QPointArray a;
213 int y = val2y(val);
214 a.setPoints( 3, w, y, w+5, y+5, w+5, y-5 );
215 erase( w, 0, 5, height() );
216 p.drawPolygon( a );
217}
218
219void QColorLuminancePicker::setCol( int h, int s , int v )
220{
221 val = v;
222 hue = h;
223 sat = s;
224 delete pix; pix=0;
225 repaint( FALSE );//####
226}
227
228QPoint QColorPicker::colPt()
229{ return QPoint( (360-hue)*(pWidth-1)/360, (255-sat)*(pHeight-1)/255 ); }
230int QColorPicker::huePt( const QPoint &pt )
231{ return 360 - pt.x()*360/(pWidth-1); }
232int QColorPicker::satPt( const QPoint &pt )
233{ return 255 - pt.y()*255/(pHeight-1) ; }
234void QColorPicker::setCol( const QPoint &pt )
235{ setCol( huePt(pt), satPt(pt) ); }
236
237QColorPicker::QColorPicker(QWidget* parent, const char* name )
238 : QFrame( parent, name )
239{
240 hue = 0; sat = 0;
241 setCol( 150, 255 );
242
243 QImage img( pWidth, pHeight, 32 );
244 int x,y;
245 for ( y = 0; y < pHeight; y++ )
246 for ( x = 0; x < pWidth; x++ ) {
247 QPoint p( x, y );
248 img.setPixel( x, y, QColor(huePt(p), satPt(p),
249 200, QColor::Hsv).rgb() );
250 }
251 pix = new QPixmap;
252 pix->convertFromImage(img);
253 setBackgroundMode( NoBackground );
254}
255
256QColorPicker::~QColorPicker()
257{
258 delete pix;
259}
260
261QSize QColorPicker::sizeHint() const
262{
263 return QSize( pWidth + 2*frameWidth(), pHeight + 2*frameWidth() );
264}
265
266QSizePolicy QColorPicker::sizePolicy() const
267{
268 return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
269}
270
271void QColorPicker::setCol( int h, int s )
272{
273 int nhue = QMIN( QMAX(0,h), 360 );
274 int nsat = QMIN( QMAX(0,s), 255);
275 if ( nhue == hue && nsat == sat )
276 return;
277 QRect r( colPt(), QSize(20,20) );
278 hue = nhue; sat = nsat;
279 r = r.unite( QRect( colPt(), QSize(20,20) ) );
280 r.moveBy( contentsRect().x()-9, contentsRect().y()-9 );
281 // update( r );
282 repaint( r, FALSE );
283}
284
285void QColorPicker::mouseMoveEvent( QMouseEvent *m )
286{
287 QPoint p = m->pos() - contentsRect().topLeft();
288 setCol( p );
289 emit newCol( hue, sat );
290}
291
292void QColorPicker::mousePressEvent( QMouseEvent *m )
293{
294 QPoint p = m->pos() - contentsRect().topLeft();
295 setCol( p );
296 emit newCol( hue, sat );
297}
298
299void QColorPicker::drawContents(QPainter* p)
300{
301 QRect r = contentsRect();
302
303 p->drawPixmap( r.topLeft(), *pix );
304 QPoint pt = colPt() + r.topLeft();
305 p->setPen( QPen(black) );
306
307 p->fillRect( pt.x()-9, pt.y(), 20, 2, black );
308 p->fillRect( pt.x(), pt.y()-9, 2, 20, black );
309
310}
311
312class QColorShowLabel;
313
314
315
316class QColIntValidator: public QIntValidator
317{
318public:
319 QColIntValidator( int bottom, int top,
320 QWidget * parent, const char *name = 0 )
321 :QIntValidator( bottom, top, parent, name ) {}
322
323 QValidator::State validate( QString &, int & ) const;
324};
325
326QValidator::State QColIntValidator::validate( QString &s, int &pos ) const
327{
328 State state = QIntValidator::validate(s,pos);
329 if ( state == Valid ) {
330 long int val = s.toLong();
331 // This is not a general solution, assumes that top() > 0 and
332 // bottom >= 0
333 if ( val < 0 ) {
334 s = "0";
335 pos = 1;
336 } else if ( val > top() ) {
337 s.setNum( top() );
338 pos = s.length();
339 }
340 }
341 return state;
342}
343
344
345
346class QColNumLineEdit : public QLineEdit
347{
348public:
349 QColNumLineEdit( QWidget *parent, const char* name = 0 )
350 : QLineEdit( parent, name ) { setMaxLength( 3 );}
351 QSize sizeHint() const {
352 return QSize( 30, //#####
353 QLineEdit::sizeHint().height() ); }
354 void setNum( int i ) {
355 QString s;
356 s.setNum(i);
357 bool block = signalsBlocked();
358 blockSignals(TRUE);
359 setText( s );
360 blockSignals(block);
361 }
362 int val() const { return text().toInt(); }
363};
364
365
366class QColorShower : public QWidget
367{
368 Q_OBJECT
369public:
370 QColorShower( QWidget *parent, const char *name = 0 );
371
372 //things that don't emit signals
373 void setHsv( int h, int s, int v );
374
375 int currentAlpha() const { return alphaEd->val(); }
376 void setCurrentAlpha( int a ) { alphaEd->setNum( a ); }
377 void showAlpha( bool b );
378
379
380 QRgb currentColor() const { return curCol; }
381
382public slots:
383 void setRgb( QRgb rgb );
384
385signals:
386 void newCol( QRgb rgb );
387private slots:
388 void rgbEd();
389 void hsvEd();
390private:
391 void showCurrentColor();
392 int hue, sat, val;
393 QRgb curCol;
394 QColNumLineEdit *hEd;
395 QColNumLineEdit *sEd;
396 QColNumLineEdit *vEd;
397 QColNumLineEdit *rEd;
398 QColNumLineEdit *gEd;
399 QColNumLineEdit *bEd;
400 QColNumLineEdit *alphaEd;
401 QLabel *alphaLab;
402 QColorShowLabel *lab;
403 bool rgbOriginal;
404};
405
406class QColorShowLabel : public QFrame
407{
408 Q_OBJECT
409
410public:
411 QColorShowLabel( QWidget *parent ) :QFrame( parent ) {
412 setFrameStyle( QFrame::Panel|QFrame::Sunken );
413 setBackgroundMode( PaletteBackground );
414 setAcceptDrops( TRUE );
415 mousePressed = FALSE;
416 }
417 void setColor( QColor c ) { col = c; }
418
419signals:
420 void colorDropped( QRgb );
421
422protected:
423 void drawContents( QPainter *p );
424 void mousePressEvent( QMouseEvent *e );
425 void mouseReleaseEvent( QMouseEvent *e );
426
427private:
428 QColor col;
429 bool mousePressed;
430 QPoint pressPos;
431
432};
433
434void QColorShowLabel::drawContents( QPainter *p )
435{
436 p->fillRect( contentsRect(), col );
437}
438
439void QColorShower::showAlpha( bool b )
440{
441 if ( b ) {
442 alphaLab->show();
443 alphaEd->show();
444 } else {
445 alphaLab->hide();
446 alphaEd->hide();
447 }
448}
449
450void QColorShowLabel::mousePressEvent( QMouseEvent *e )
451{
452 mousePressed = TRUE;
453 pressPos = e->pos();
454}
455
456void QColorShowLabel::mouseReleaseEvent( QMouseEvent * )
457{
458 if ( !mousePressed )
459 return;
460 mousePressed = FALSE;
461}
462
463QColorShower::QColorShower( QWidget *parent, const char *name )
464 :QWidget( parent, name)
465{
466 curCol = qRgb( -1, -1, -1 );
467 QColIntValidator *val256 = new QColIntValidator( 0, 255, this );
468 QColIntValidator *val360 = new QColIntValidator( 0, 360, this );
469
470 QGridLayout *gl = new QGridLayout( this, 1, 1, 2 );
471 gl->setMargin( 0 );
472 lab = new QColorShowLabel( this );
473 lab->setMinimumWidth( 60 ); //###
474 gl->addMultiCellWidget(lab, 0,-1,0,0);
475 connect( lab, SIGNAL( colorDropped(QRgb) ),
476 this, SIGNAL( newCol(QRgb) ) );
477 connect( lab, SIGNAL( colorDropped(QRgb) ),
478 this, SLOT( setRgb(QRgb) ) );
479
480 hEd = new QColNumLineEdit( this );
481 hEd->setValidator( val360 );
482 QLabel *l = new QLabel( hEd, OColorDialog::tr("Hue:"), this );
483 l->setAlignment( AlignRight|AlignVCenter );
484 gl->addWidget( l, 0, 1 );
485 gl->addWidget( hEd, 0, 2 );
486
487 sEd = new QColNumLineEdit( this );
488 sEd->setValidator( val256 );
489 l = new QLabel( sEd, OColorDialog::tr("Sat:"), this );
490 l->setAlignment( AlignRight|AlignVCenter );
491 gl->addWidget( l, 1, 1 );
492 gl->addWidget( sEd, 1, 2 );
493
494 vEd = new QColNumLineEdit( this );
495 vEd->setValidator( val256 );
496 l = new QLabel( vEd, OColorDialog::tr("Val:"), this );
497 l->setAlignment( AlignRight|AlignVCenter );
498 gl->addWidget( l, 2, 1 );
499 gl->addWidget( vEd, 2, 2 );
500
501 rEd = new QColNumLineEdit( this );
502 rEd->setValidator( val256 );
503 l = new QLabel( rEd, OColorDialog::tr("Red:"), this );
504 l->setAlignment( AlignRight|AlignVCenter );
505 gl->addWidget( l, 0, 3 );
506 gl->addWidget( rEd, 0, 4 );
507
508 gEd = new QColNumLineEdit( this );
509 gEd->setValidator( val256 );
510 l = new QLabel( gEd, OColorDialog::tr("Green:"), this );
511 l->setAlignment( AlignRight|AlignVCenter );
512 gl->addWidget( l, 1, 3 );
513 gl->addWidget( gEd, 1, 4 );
514
515 bEd = new QColNumLineEdit( this );
516 bEd->setValidator( val256 );
517 l = new QLabel( bEd, OColorDialog::tr("Blue:"), this );
518 l->setAlignment( AlignRight|AlignVCenter );
519 gl->addWidget( l, 2, 3 );
520 gl->addWidget( bEd, 2, 4 );
521
522 alphaEd = new QColNumLineEdit( this );
523 alphaEd->setValidator( val256 );
524 alphaLab = new QLabel( alphaEd, OColorDialog::tr("Alpha channel:"), this );
525 alphaLab->setAlignment( AlignRight|AlignVCenter );
526 gl->addMultiCellWidget( alphaLab, 3, 3, 1, 3 );
527 gl->addWidget( alphaEd, 3, 4 );
528 alphaEd->hide();
529 alphaLab->hide();
530
531 connect( hEd, SIGNAL(textChanged(const QString&)), this, SLOT(hsvEd()) );
532 connect( sEd, SIGNAL(textChanged(const QString&)), this, SLOT(hsvEd()) );
533 connect( vEd, SIGNAL(textChanged(const QString&)), this, SLOT(hsvEd()) );
534
535 connect( rEd, SIGNAL(textChanged(const QString&)), this, SLOT(rgbEd()) );
536 connect( gEd, SIGNAL(textChanged(const QString&)), this, SLOT(rgbEd()) );
537 connect( bEd, SIGNAL(textChanged(const QString&)), this, SLOT(rgbEd()) );
538}
539
540void QColorShower::showCurrentColor()
541{
542 lab->setColor( currentColor() );
543 lab->repaint(FALSE); //###
544}
545
546void QColorShower::rgbEd()
547{
548 rgbOriginal = TRUE;
549 curCol = qRgb( rEd->val(), gEd->val(), bEd->val() );
550 rgb2hsv(currentColor(), hue, sat, val );
551
552 hEd->setNum( hue );
553 sEd->setNum( sat );
554 vEd->setNum( val );
555
556 showCurrentColor();
557 emit newCol( currentColor() );
558}
559
560void QColorShower::hsvEd()
561{
562 rgbOriginal = FALSE;
563 hue = hEd->val();
564 sat = sEd->val();
565 val = vEd->val();
566
567 curCol = QColor( hue, sat, val, QColor::Hsv ).rgb();
568
569 rEd->setNum( qRed(currentColor()) );
570 gEd->setNum( qGreen(currentColor()) );
571 bEd->setNum( qBlue(currentColor()) );
572
573 showCurrentColor();
574 emit newCol( currentColor() );
575}
576
577void QColorShower::setRgb( QRgb rgb )
578{
579 rgbOriginal = TRUE;
580 curCol = rgb;
581
582 rgb2hsv( currentColor(), hue, sat, val );
583
584 hEd->setNum( hue );
585 sEd->setNum( sat );
586 vEd->setNum( val );
587
588 rEd->setNum( qRed(currentColor()) );
589 gEd->setNum( qGreen(currentColor()) );
590 bEd->setNum( qBlue(currentColor()) );
591
592 showCurrentColor();
593}
594
595void QColorShower::setHsv( int h, int s, int v )
596{
597 rgbOriginal = FALSE;
598 hue = h; val = v; sat = s; //Range check###
599 curCol = QColor( hue, sat, val, QColor::Hsv ).rgb();
600
601 hEd->setNum( hue );
602 sEd->setNum( sat );
603 vEd->setNum( val );
604
605 rEd->setNum( qRed(currentColor()) );
606 gEd->setNum( qGreen(currentColor()) );
607 bEd->setNum( qBlue(currentColor()) );
608
609
610 showCurrentColor();
611}
612
613}
614
615class OColorDialogPrivate : public QObject
616{
617Q_OBJECT
618public:
619 OColorDialogPrivate( OColorDialog *p );
620 QRgb currentColor() const { return cs->currentColor(); }
621 void setCurrentColor( const QRgb& rgb );
622
623 int currentAlpha() const { return cs->currentAlpha(); }
624 void setCurrentAlpha( int a ) { cs->setCurrentAlpha( a ); }
625 void showAlpha( bool b ) { cs->showAlpha( b ); }
626
627private slots:
628 void newHsv( int h, int s, int v );
629 void newColorTypedIn( QRgb rgb );
630private:
631 QColorPicker *cp;
632 QColorLuminancePicker *lp;
633 QColorShower *cs;
634};
635
636//sets all widgets to display h,s,v
637void OColorDialogPrivate::newHsv( int h, int s, int v )
638{
639 cs->setHsv( h, s, v );
640 cp->setCol( h, s );
641 lp->setCol( h, s, v );
642}
643
644//sets all widgets to display rgb
645void OColorDialogPrivate::setCurrentColor( const QRgb& rgb )
646{
647 cs->setRgb( rgb );
648 newColorTypedIn( rgb );
649}
650
651//sets all widgets exept cs to display rgb
652void OColorDialogPrivate::newColorTypedIn( QRgb rgb )
653{
654 int h, s, v;
655 rgb2hsv(rgb, h, s, v );
656 cp->setCol( h, s );
657 lp->setCol( h, s, v);
658}
659
660OColorDialogPrivate::OColorDialogPrivate( OColorDialog *dialog ) :
661 QObject(dialog)
662{
663 int border = 2;
664 QVBoxLayout *topLay = new QVBoxLayout( dialog, border, 2 );
665
666 QHBoxLayout *pickLay = new QHBoxLayout( topLay );
667
668
669 cp = new QColorPicker( dialog );
670 cp->setFrameStyle( QFrame::Panel + QFrame::Sunken );
671 pickLay->addWidget( cp );
672
673 pickLay->addStretch();
674
675 lp = new QColorLuminancePicker( dialog );
676 lp->setFixedWidth( 20 ); //###
677 pickLay->addWidget( lp );
678
679 connect( cp, SIGNAL(newCol(int,int)), lp, SLOT(setCol(int,int)) );
680 connect( lp, SIGNAL(newHsv(int,int,int)), this, SLOT(newHsv(int,int,int)) );
681
682 topLay->addStretch();
683
684 cs = new QColorShower( dialog );
685 connect( cs, SIGNAL(newCol(QRgb)), this, SLOT(newColorTypedIn(QRgb)));
686 topLay->addWidget( cs );
687
688}
689
690
691// BEING REVISED: jo
692/*!
693 \class ColorDialog ColorDialog.h
694 \brief The OColorDialog class provides a dialog widget for specifying colors.
695 \ingroup dialogs
696
697 The color dialog's function is to allow users to choose colors -
698 for instance, you might use this in a drawing program to allow the
699 user to set the brush color.
700
701 This version of Qt only provides modal color dialogs. The static
702 getColor() function shows the dialog and allows the user to specify a color,
703 while getRgba() does the same but allows the user to specify a color with an
704 alpha channel (transparency) value.
705
706 The user can store customCount() different custom colors. The custom
707 colors are shared by all color dialogs, and remembered during the
708 execution of the program. Use setCustomColor() to set the
709 custom colors, and customColor() to get them.
710
711 <img src=qcolordlg-m.png> <img src=qcolordlg-w.png>
712*/
713
714/*!
715 Constructs a default color dialog. Use setColor() for setting an initial value.
716
717 \sa getColor()
718*/
719
720OColorDialog::OColorDialog(QWidget* parent, const char* name, bool modal) :
721 QDialog(parent, name, modal )
722{
723 d = new OColorDialogPrivate( this );
724}
725
726
727/*!
728 Pops up a modal color dialog letting the user choose a color and returns
729 that color. The color is initially set to \a initial. Returns an \link QColor::isValid() invalid\endlink color if the user cancels
730 the dialog. All colors allocated by the dialog will be deallocated
731 before this function returns.
732*/
733
734QColor OColorDialog::getColor( const QColor& initial, QWidget *parent,
735 const char *name )
736{
737 int allocContext = QColor::enterAllocContext();
738 OColorDialog *dlg = new OColorDialog( parent, name, TRUE ); //modal
739 if ( parent && parent->icon() && !parent->icon()->isNull() )
740 dlg->setIcon( *parent->icon() );
741 else if ( qApp->mainWidget() && qApp->mainWidget()->icon() && !qApp->mainWidget()->icon()->isNull() )
742 dlg->setIcon( *qApp->mainWidget()->icon() );
743
744 dlg->setCaption( OColorDialog::tr( "Select color" ) );
745 dlg->setColor( initial );
746 dlg->showMaximized();
747 int resultCode = dlg->exec();
748 QColor::leaveAllocContext();
749 QColor result;
750 if ( resultCode == QDialog::Accepted ) {
751 result = dlg->color();
752 } else {
753 result = initial;
754 }
755 QColor::destroyAllocContext(allocContext);
756 delete dlg;
757 return result;
758}
759
760
761/*!
762 Pops up a modal color dialog, letting the user choose a color and an
763 alpha channel value. The color+alpha is initially set to \a initial.
764
765 If \a ok is non-null, \c *ok is set to TRUE if the user clicked OK,
766 and FALSE if the user clicked Cancel.
767
768 If the user clicks Cancel the \a initial value is returned.
769*/
770
771QRgb OColorDialog::getRgba( const QRgb& initial, bool *ok,
772 QWidget *parent, const char* name )
773{
774 int allocContext = QColor::enterAllocContext();
775 OColorDialog *dlg = new OColorDialog( parent, name, TRUE ); //modal
776 dlg->setColor( initial );
777 dlg->setSelectedAlpha( qAlpha(initial) );
778 dlg->showMaximized();
779 int resultCode = dlg->exec();
780 QColor::leaveAllocContext();
781 QRgb result = initial;
782 if ( resultCode == QDialog::Accepted ) {
783 QRgb c = dlg->color().rgb();
784 int alpha = dlg->selectedAlpha();
785 result = qRgba( qRed(c), qGreen(c), qBlue(c), alpha );
786 }
787 if ( ok )
788 *ok = resultCode == QDialog::Accepted;
789
790 QColor::destroyAllocContext(allocContext);
791 delete dlg;
792 return result;
793}
794
795
796
797
798
799/*!
800 Returns the color currently selected in the dialog.
801
802 \sa setColor()
803*/
804
805QColor OColorDialog::color() const
806{
807 return QColor(d->currentColor());
808}
809
810
811/*! Destructs the dialog and frees any memory it allocated.
812
813*/
814
815OColorDialog::~OColorDialog()
816{
817 //d inherits QObject, so it is deleted by Qt.
818}
819
820
821/*!
822 Sets the color shown in the dialog to \a c.
823
824 \sa color()
825*/
826
827void OColorDialog::setColor( const QColor& c )
828{
829 d->setCurrentColor( c.rgb() );
830}
831
832
833
834
835/*!
836 Sets the initial alpha channel value to \a a, and show the alpha channel
837 entry box.
838*/
839
840void OColorDialog::setSelectedAlpha( int a )
841{
842 d->showAlpha( TRUE );
843 d->setCurrentAlpha( a );
844}
845
846
847/*!
848 Returns the value selected for the alpha channel.
849*/
850
851int OColorDialog::selectedAlpha() const
852{
853 return d->currentAlpha();
854}
855
856#include "colordialog.moc"
diff --git a/noncore/unsupported/libopie/colordialog.h b/noncore/unsupported/libopie/colordialog.h
new file mode 100644
index 0000000..c825a83
--- a/dev/null
+++ b/noncore/unsupported/libopie/colordialog.h
@@ -0,0 +1,90 @@
1/****************************************************************************
2** $Id$
3**
4** Definition of OColorDialog class
5**
6** Created : 990222
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the dialogs module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#ifndef OColorDialog_H
39#define OColorDialog_H
40
41#ifndef QT_H
42#include <qdialog.h>
43#endif // QT_H
44
45class OColorDialogPrivate;
46
47/*
48 * @class OColorDialog
49 * @brief The OColorDialog class is a copy of QColorDialog for use in Opie.
50 *
51 * OColorDialog is a copy of TrollTech's QColorDialog for use in Opie. The default
52 * build of QT/Embedded used by Opie does not include QColorDialog, so it is provided
53 * here. It is renamed to prevent conflicts in the event the QColorDialog is included
54 * at a later date in QP/E.
55 *
56 * See http://doc.trolltech.com/2.3/qcolordialog.html for complete documentation of
57 * QColorDialog.
58 */
59class Q_EXPORT OColorDialog : public QDialog
60{
61 Q_OBJECT
62
63public:
64 static QColor getColor( const QColor&, QWidget *parent=0, const char* name=0 );
65 static QRgb getRgba( const QRgb&, bool* ok = 0,
66 QWidget *parent=0, const char* name=0 );
67
68private:
69 ~OColorDialog();
70
71 // FIXME add WFlags? -zecke
72 OColorDialog( QWidget* parent=0, const char* name=0, bool modal=FALSE );
73 void setColor( const QColor& );
74 QColor color() const;
75
76private:
77 void setSelectedAlpha( int );
78 int selectedAlpha() const;
79private:
80 OColorDialogPrivate *d;
81 friend class OColorDialogPrivate;
82
83 private:// Disabled copy constructor and operator=
84#if defined(Q_DISABLE_COPY)
85 OColorDialog( const OColorDialog & );
86 OColorDialog& operator=( const OColorDialog & );
87#endif
88};
89
90#endif
diff --git a/noncore/unsupported/libopie/colorpopupmenu.cpp b/noncore/unsupported/libopie/colorpopupmenu.cpp
new file mode 100644
index 0000000..03ad233
--- a/dev/null
+++ b/noncore/unsupported/libopie/colorpopupmenu.cpp
@@ -0,0 +1,172 @@
1/*
2                This file is part of the Opie Project
3
4              Copyright (c) 2002 S. Prud'homme <prudhomme@laposte.net>
5              Dan Williams <williamsdr@acm.org>
6 =.
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33#include "colorpopupmenu.h"
34#include "colordialog.h"
35
36#include <qlayout.h>
37#include <qpainter.h>
38
39OColorPanelButton::OColorPanelButton( const QColor& color, QWidget* parent, const char* name )
40 : QFrame( parent, name )
41{
42 m_color = color;
43
44 setFixedSize( 16, 16 );
45 setActive( FALSE );
46}
47
48OColorPanelButton::~OColorPanelButton()
49{
50}
51
52void OColorPanelButton::setActive( bool active )
53{
54 m_active = active;
55
56 if ( m_active ) {
57 setFrameStyle( Panel | Sunken );
58 } else {
59 setFrameStyle( NoFrame );
60 }
61}
62
63void OColorPanelButton::enterEvent( QEvent* )
64{
65 if ( !m_active ) {
66 setFrameStyle( Panel | Sunken );
67 }
68}
69
70void OColorPanelButton::leaveEvent( QEvent* )
71{
72 if ( !m_active ) {
73 setFrameStyle( NoFrame );
74 }
75}
76
77void OColorPanelButton::paintEvent( QPaintEvent* e )
78{
79 QFrame::paintEvent( e );
80
81 QPainter painter;
82 painter.begin( this );
83 painter.fillRect( 2, 2, 12, 12, m_color );
84 painter.setPen( Qt::black );
85 painter.drawRect( 2, 2, 12, 12 );
86 painter.end();
87}
88
89void OColorPanelButton::mouseReleaseEvent( QMouseEvent* )
90{
91 emit selected( m_color );
92}
93
94OColorPopupMenu::OColorPopupMenu( const QColor& color, QWidget* parent, const char* name )
95 : QPopupMenu( parent, name )
96{
97 m_color = color;
98
99 colorPanel = new QWidget( this );
100
101 colorLayout = new QGridLayout(colorPanel, 5, 6);
102
103 addColor(QColor(255, 255, 255), 0, 1);
104 addColor(QColor(192, 192, 192), 0, 2);
105 addColor(QColor(128, 128, 128), 0, 3);
106 addColor(QColor(64, 64, 64), 0, 4);
107 addColor(QColor(0, 0, 0), 0, 5);
108
109 addColor(QColor(255, 0, 0), 1, 0);
110 addColor(QColor(255, 128, 0), 1, 1);
111 addColor(QColor(255, 255, 0), 1, 2);
112 addColor(QColor(128, 255, 0), 1, 3);
113 addColor(QColor(0, 255, 0), 1, 4);
114 addColor(QColor(0, 255, 128), 1, 5);
115
116 addColor(QColor(128, 0, 0), 2, 0);
117 addColor(QColor(128, 64, 0), 2, 1);
118 addColor(QColor(128, 128, 0), 2, 2);
119 addColor(QColor(64, 128, 0), 2, 3);
120 addColor(QColor(0, 128, 0), 2, 4);
121 addColor(QColor(0, 128, 64), 2, 5);
122
123 addColor(QColor(0, 255, 255), 3, 0);
124 addColor(QColor(0, 128, 255), 3, 1);
125 addColor(QColor(0, 0, 255), 3, 2);
126 addColor(QColor(128, 0, 255), 3, 3);
127 addColor(QColor(255, 0, 255), 3, 4);
128 addColor(QColor(255, 0, 128), 3, 5);
129
130 addColor(QColor(0, 128, 128), 4, 0);
131 addColor(QColor(0, 64, 128), 4, 1);
132 addColor(QColor(0, 0, 128), 4, 2);
133 addColor(QColor(64, 0, 128), 4, 3);
134 addColor(QColor(128, 0, 128), 4, 4);
135 addColor(QColor(128, 0, 64), 4, 5);
136
137 insertItem( colorPanel );
138 insertSeparator();
139 insertItem(tr("More"),this,SLOT( moreColorClicked()));
140 /*
141 QAction* chooseColorAction = new QAction( tr( "More" ), tr( "More..." ), 0, colorPanel, "More" );
142 connect( chooseColorAction, SIGNAL( activated() ), this, SLOT( moreColorClicked() ) );
143 chooseColorAction->addTo( this );
144 */
145 activateItemAt( 0 );
146}
147
148OColorPopupMenu::~OColorPopupMenu()
149{
150}
151
152void OColorPopupMenu::addColor( const QColor& color, int row, int col )
153{
154 OColorPanelButton* panelButton = new OColorPanelButton( color, colorPanel );
155 connect( panelButton, SIGNAL( selected(const QColor&) ), this, SLOT( buttonSelected(const QColor&) ) );
156 colorLayout->addWidget( panelButton, row, col );
157}
158
159void OColorPopupMenu::buttonSelected( const QColor& color )
160{
161 m_color = color;
162 emit colorSelected( color );
163 hide();
164}
165
166void OColorPopupMenu::moreColorClicked()
167{
168 QColor color = OColorDialog::getColor( m_color );
169 m_color = color;
170 emit colorSelected( color );
171 hide();
172}
diff --git a/noncore/unsupported/libopie/colorpopupmenu.h b/noncore/unsupported/libopie/colorpopupmenu.h
new file mode 100644
index 0000000..98d67cc
--- a/dev/null
+++ b/noncore/unsupported/libopie/colorpopupmenu.h
@@ -0,0 +1,255 @@
1/*
2                This file is part of the Opie Project
3
4              Copyright (c) 2002 S. Prud'homme <prudhomme@laposte.net>
5              Dan Williams <williamsdr@acm.org>
6 =.
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; Library General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = Library General Public License along with
26    --        :-=` this library; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33#ifndef COLORPOPUPMENU_H
34#define COLORPOPUPMENU_H
35
36#include <qframe.h>
37#include <qpopupmenu.h>
38
39class QWidget;
40class QGridLayout;
41
42/**
43 * @class OColorPanelButton
44 * @brief The OColorPanelButton class provides a button for color selection.
45 *
46 * @see OColorPopupMenu
47 *
48 * The OColorPanelButton class provides a button for color selection. The button
49 * is drawn with the desired color and no border. This class is used internally
50 * by the OColorPopupMenu class to displaying colors in its menu.
51 */
52class OColorPanelButton : public QFrame
53{
54 Q_OBJECT
55
56public:
57
58/**
59 * @fn OColorPanelButton( const QColor& color, QWidget* parent = 0, const char* name = 0 )
60 * @brief Object constructor.
61 *
62 * @param color Desired color.
63 * @param parent Pointer to parent of this control.
64 * @param name Name of control.
65 *
66 * Constructs a new ColorPanelButton control with parent, name and desired color.
67 */
68 OColorPanelButton(const QColor& color, QWidget* parent = 0, const char* name = 0);
69
70/**
71 * @fn ~OColorPanelButton()
72 * @brief Object destructor.
73 */
74 ~OColorPanelButton();
75
76/**
77 * @fn setActive( bool active )
78 * @brief Sets button selection state.
79 *
80 * @param active Boolean indicator of new button state.
81 *
82 * Changes button selection state. If button is selected, a highlighted border
83 * is drawn.
84 */
85 void setActive(bool active);
86
87/**
88 * @fn enterEvent( QEvent* e )
89 * @brief Reimplemented for internal reasons.
90 *
91 * @param e Event currently being processed.
92 *
93 * Reimplemented to ensure correct display of button based on whether it is
94 * active or not.
95 */
96 void enterEvent(QEvent* e);
97
98/**
99 * @fn leaveEvent( QEvent* e )
100 * @brief Reimplemented for internal reasons.
101 *
102 * @param e Event currently being processed.
103 *
104 * Reimplemented to ensure correct display of button based on whether it is
105 * active or not.
106 */
107 void leaveEvent(QEvent* e);
108
109/**
110 * @fn paintEvent( QPaintEvent* e )
111 * @brief Reimplemented for internal reasons.
112 *
113 * @param e Event currently being processed.
114 * @reimp
115 * Reimplemented to ensure correct display of button.
116 */
117 void paintEvent(QPaintEvent* e);
118
119/**
120 * @fn mouseReleaseEvent( QMouseEvent* e )
121 * @brief Slot executed when button is pressed.
122 *
123 * @param e Mouse event currently being processed.
124 *
125 * @see selected()
126 *
127 * This slot executes when the button has been pressed. It emits the selected
128 * signal as notification that it has been pressed.
129 */
130 void mouseReleaseEvent(QMouseEvent* e);
131
132signals:
133
134/**
135 * @fn selected( const QColor& color )
136 * @brief Signal to indicate button has been pressed.
137 *
138 * @param color Button color.
139 *
140 * This signal is emitted when the button is pressed. It provides the color
141 * associated to this button.
142 */
143 void selected(const QColor&);
144
145private:
146 QColor m_color;
147 bool m_active : 1;
148 class ColorPanelButtonPrivate;
149 ColorPanelButtonPrivate *d;
150};
151
152/**
153 * @class OColorPopupMenu
154 * @brief The OColorPopupMenu class provides a small color selection
155 * popup menu.
156 *
157 * OColorPopupMenu is a derivation of TrollTech's QPopupMenu and provides
158 * a small color selection popup menu which can be attached to another control
159 * such as a toolbar button of menu item.
160 *
161 * The popup menu displays 30 default colors available in a grid, and also
162 * includes an option at the bottom to display a color selection dialog box for
163 * finer color control.
164 */
165class OColorPopupMenu : public QPopupMenu
166{
167 Q_OBJECT
168
169public:
170
171/**
172 * @fn OColorPopupMenu( const QColor& color, QWidget* parent = 0, const char* name = 0 )
173 * @brief Object constructor.
174 *
175 * @param color Initial color selected in menu.
176 * @param parent Pointer to parent of this control.
177 * @param name Name of control.
178 *
179 * Constructs a new OColorPopupMenu control with parent, name and initial color selected.
180 */
181 // FIXME add Wflags? -zecke
182 OColorPopupMenu( const QColor& color, QWidget* parent = 0, const char* name = 0 );
183
184/**
185 * @fn ~OColorPopupMenu()
186 * @brief Object destructor.
187 */
188 ~OColorPopupMenu();
189
190private:
191 class ColorPopupMenuPrivate;
192 ColorPopupMenuPrivate *d;
193 QColor m_color;
194 QWidget* colorPanel;
195 QGridLayout* colorLayout;
196
197/**
198 * @fn addColor( const QColor& color, int row, int col )
199 * @brief Adds color selection option to popup menu.
200 *
201 * @param color Color to be displayed in menu.
202 * @param row Row where color is to appear in menu.
203 * @param col Column where color is to appear in menu.
204 *
205 * Adds a color selection option to popup menu. Used internally when
206 * initially constructing the menu control.
207 */
208 void addColor( const QColor& color, int row, int col );
209
210signals:
211
212/**
213 * @fn colorSelected( const QColor& color )
214 * @brief Signal to indicate color chosen from the menu.
215 *
216 * @param color Color selected from the menu.
217 *
218 * This signal is emitted when a color has been selected either directly from
219 * the menu, or chosen from the color selection dialog.
220 */
221 void colorSelected( const QColor& color );
222
223protected slots:
224
225/**
226 * @fn buttonSelected( const QColor& color )
227 * @brief Slot to process selected color.
228 *
229 * @param color Color selected from the menu.
230 *
231 * @see colorSelected()
232 *
233 * This slot executes when a color has been selected from the menu. It performs
234 * two functions:
235 * - Emit the colorSelected signal with the color selected.
236 * - Hide the menu.
237 */
238 void buttonSelected( const QColor& color );
239
240/**
241 * @fn moreColorClicked()
242 * @brief Slot to process display color selection dialog.
243 *
244 * @see colorSelected()
245 *
246 * This slot executes when the 'More...' option is selected at the bottom of the menu.
247 * It performs the following functions:
248 * - Constructs and executes a OColorDialog to allow finer color selection.
249 * - Emit the colorSelected signal with the color selected.
250 * - Hide the menu.
251 */
252 void moreColorClicked();
253};
254
255#endif // COLORPOPUPMENUANEL_H
diff --git a/noncore/unsupported/libopie/config.in b/noncore/unsupported/libopie/config.in
new file mode 100644
index 0000000..e8bc2e2
--- a/dev/null
+++ b/noncore/unsupported/libopie/config.in
@@ -0,0 +1,4 @@
1 config LIBOPIE
2 boolean "libopie1 (compatibility only, use libopie2* for new applications)"
3 default "n"
4 depends ( LIBQPE || LIBQPE-X11 )
diff --git a/noncore/unsupported/libopie/libopie.pro b/noncore/unsupported/libopie/libopie.pro
new file mode 100644
index 0000000..783c11d
--- a/dev/null
+++ b/noncore/unsupported/libopie/libopie.pro
@@ -0,0 +1,102 @@
1TEMPLATE = lib
2CONFIG += qte warn_on
3HEADERS = ofontmenu.h \
4 ocolorbutton.h \
5 ofiledialog.h ofileselector.h \
6 ofileselector_p.h \
7 ocheckitem.h \
8 xmltree.h \
9 colordialog.h colorpopupmenu.h \
10 oclickablelabel.h oprocctrl.h \
11 oprocess.h odevice.h odevicebutton.h \
12 otimepicker.h otabwidget.h \
13 otabbar.h otabinfo.h \
14 ofontselector.h \
15 pim/opimrecord.h \
16 pim/otodo.h \
17 pim/orecordlist.h \
18 pim/opimaccesstemplate.h \
19 pim/opimaccessbackend.h \
20 pim/otodoaccess.h \
21 pim/otodoaccessbackend.h \
22 pim/oconversion.h \
23 pim/ocontact.h \
24 pim/ocontactfields.h \
25 pim/ocontactaccess.h \
26 pim/ocontactaccessbackend.h \
27 pim/ocontactaccessbackend_xml.h \
28 pim/ocontactaccessbackend_vcard.h \
29 pim/obackendfactory.h \
30 pim/opimcache.h \
31 pim/otodoaccessvcal.h \
32 pim/orecur.h \
33 pim/opimstate.h \
34 pim/opimxrefpartner.h \
35 pim/opimxref.h \
36 pim/opimxrefmanager.h \
37 pim/opimmaintainer.h \
38 pim/opimnotify.h \
39 pim/opimnotifymanager.h \
40 pim/opimmainwindow.h \
41 pim/opimresolver.h \
42 pim/oevent.h \
43 pim/otimezone.h \
44 pim/odatebookaccess.h \
45 pim/odatebookaccessbackend.h \
46 pim/odatebookaccessbackend_xml.h \
47 orecurrancewidget.h \
48 oticker.h owait.h
49
50SOURCES = ofontmenu.cc \
51 ocolorbutton.cpp \
52 sharp_compat.cpp \
53 xmltree.cc \
54 ofiledialog.cc ofileselector.cpp \
55 ocheckitem.cpp \
56 colordialog.cpp \
57 colorpopupmenu.cpp oclickablelabel.cpp \
58 oprocctrl.cpp oprocess.cpp \
59 odevice.cpp odevicebutton.cpp otimepicker.cpp \
60 otabwidget.cpp otabbar.cpp \
61 ofontselector.cpp \
62 pim/otodo.cpp \
63 pim/opimrecord.cpp \
64 pim/otodoaccess.cpp \
65 pim/otodoaccessbackend.cpp \
66 pim/otodoaccessxml.cpp \
67 pim/oconversion.cpp \
68 pim/ocontact.cpp \
69 pim/ocontactfields.cpp \
70 pim/ocontactaccess.cpp \
71 pim/ocontactaccessbackend_vcard.cpp \
72 pim/ocontactaccessbackend_xml.cpp \
73 pim/otodoaccessvcal.cpp \
74 pim/orecur.cpp \
75 pim/opimstate.cpp \
76 pim/opimxrefpartner.cpp \
77 pim/opimxref.cpp \
78 pim/opimxrefmanager.cpp \
79 pim/opimmaintainer.cpp \
80 pim/opimnotify.cpp \
81 pim/opimnotifymanager.cpp \
82 pim/opimmainwindow.cpp \
83 pim/opimresolver.cpp \
84 pim/oevent.cpp \
85 pim/otimezone.cpp \
86 pim/odatebookaccess.cpp \
87 pim/odatebookaccessbackend.cpp \
88 pim/odatebookaccessbackend_xml.cpp \
89 orecurrancewidget.cpp \
90 oticker.cpp owait.cpp
91
92TARGET = opie
93INCLUDEPATH += $(OPIEDIR)/include
94DESTDIR = $(OPIEDIR)/lib$(PROJMAK)
95
96LIBS += -lqpe
97
98INTERFACES = otimepickerbase.ui orecurrancebase.ui
99TARGET = opie
100
101
102include ( $(OPIEDIR)/include.pro )
diff --git a/noncore/unsupported/libopie/libopie1.control b/noncore/unsupported/libopie/libopie1.control
new file mode 100644
index 0000000..5b6825e
--- a/dev/null
+++ b/noncore/unsupported/libopie/libopie1.control
@@ -0,0 +1,11 @@
1Package: libopie1
2Files: lib/libopie.so.1.0.0 lib/libopie.so.1.0 lib/libopie.so.1
3Priority: optional
4Section: opie/system
5Maintainer: Opie Team <opie@handhelds.org>
6Architecture: arm
7Depends: libqte2 (>=$QTE_VERSION), libqpe1, opie-pics
8Provides: libopie
9Replaces: libopie
10Description: Opie library
11Version: $QPE_VERSION$EXTRAVERSION
diff --git a/noncore/unsupported/libopie/libopie1.postinst b/noncore/unsupported/libopie/libopie1.postinst
new file mode 100755
index 0000000..0c37b3d
--- a/dev/null
+++ b/noncore/unsupported/libopie/libopie1.postinst
@@ -0,0 +1,4 @@
1#!/bin/sh
2
3[ -x /sbin/ldconfig ] && /sbin/ldconfig
4exit 0
diff --git a/noncore/unsupported/libopie/oapplicationfactory.h b/noncore/unsupported/libopie/oapplicationfactory.h
new file mode 100644
index 0000000..ab88d80
--- a/dev/null
+++ b/noncore/unsupported/libopie/oapplicationfactory.h
@@ -0,0 +1,264 @@
1/*
2 This work is derived from:
3 ----
4 The Loki Library
5 Copyright (c) 2001 by Andrei Alexandrescu
6 This code accompanies the book:
7 Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
8 Patterns Applied". Copyright (c) 2001. Addison-Wesley.
9 Permission to use, copy, modify, distribute and sell this software for any
10 purpose is hereby granted without fee, provided that the above copyright
11 notice appear in all copies and that both that copyright notice and this
12 permission notice appear in supporting documentation.
13 The author or Addison-Welsey Longman make no representations about the
14 suitability of this software for any purpose. It is provided "as is"
15 without express or implied warranty.
16 ----
17
18 And KGenericFactor et all from Simon Hausmann <tronical@kde.org>
19
20*/
21
22#include <qstring.h>
23#include <qmetaobject.h>
24
25#include <qtopia/qcom.h>
26#include <qtopia/applicationinterface.h>
27
28namespace Opie {
29 struct NullType;
30
31 template <class T, class U>
32 struct Typelist
33 {
34 typedef T Head;
35 typedef U Tail;
36 };
37 template<
38 typename T1 = NullType, typename T2 = NullType, typename T3 = NullType,
39 typename T4 = NullType, typename T5 = NullType, typename T6 = NullType,
40 typename T7 = NullType, typename T8 = NullType, typename T9 = NullType,
41 typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
42 typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
43 typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
44 >
45 struct MakeTypelist{
46 private:
47 typedef typename MakeTypelist
48 <
49 T2 , T3 , T4 ,
50 T5 , T6 , T7 ,
51 T8 , T9 , T10,
52 T11, T12, T13,
53 T14, T15, T16,
54 T17, T18
55 >
56 ::Result TailResult;
57
58public:
59 typedef Typelist<T1, TailResult> Result;
60};
61
62template<>
63struct MakeTypelist<>
64{
65 typedef NullType Result;
66};
67
68}
69
70/**
71 * To allow your application to be quick launched some one needs
72 * to create the QWidget.
73 * This is this factory. Make surce your widget has static QString Widget::appName()
74 * as one of its functions.
75 *
76 * This template takes one QWidget and initialized it in the form of
77 * MyWidget::MyWidget( QWidget* parent, const char* name, WFlags f );
78 *
79 * To use it on your app do that:
80 * typedef OApplicationFactory<MyWidget> MyFactory;
81 * OPIE_EXPORT_APP( MyFactory )
82 *
83 */
84template <class Product>
85struct OApplicationFactory : public ApplicationInterface {
86 QRESULT queryInterface( const QUuid &uuid, QUnknownInterface **iface ) {
87 *iface = 0;
88 if ( uuid == IID_QUnknown ) *iface = this;
89 else if ( uuid == IID_QtopiaApplication ) *iface = this;
90 else return QS_FALSE;
91 (*iface)->addRef();
92 return QS_OK;
93 }
94
95 /*
96 *
97 */
98 virtual QWidget *createMainWindow( const QString& appName, QWidget* parent,
99 const char* name, Qt::WFlags f ) {
100 if (appName == Product::appName() )
101 return new Product(parent, name, f );
102 else
103 return 0l;
104 }
105
106 virtual QStringList applications()const {
107 QStringList list;
108 list << Product::appName() ;
109
110 return list;
111 }
112 Q_REFCOUNT
113
114};
115
116
117/* Internal */
118
119template< class Product >
120struct OPrivate {
121 inline static QWidget *multiFactory( const QString& appName, QWidget* parent,
122 const char* name, Qt::WFlags fl ) {
123 if ( appName == Product::appName() )
124 return new Product( parent, name, fl );
125 else
126 return 0;
127 }
128
129 inline static QStringList multiString( const QStringList& _list ) {
130 QStringList list = _list;
131 list << Product::appName();
132 return list;
133 }
134};
135
136template <>
137struct OPrivate<Opie::NullType > {
138 inline static QWidget* multiFactory ( const QString& , QWidget* ,
139 const char* , Qt::WFlags ) {
140 return 0l;
141 }
142 inline static QStringList multiString( const QStringList& _list ) {
143 return _list;
144 }
145};
146
147/*
148template <>
149struct OPrivate <Opie::NullType, Opie::NullType > {
150 inline static QWidget* multiFactory( const QString& , QWidget* ,
151 const char* , Qt::WFlags ) {
152 return 0l;
153 }
154
155 inline static QStringList multiString( const QStringList& _list ) {
156 return _list;
157 }
158};
159*/
160
161template <class Product, class ProductListTail>
162struct OPrivate< Opie::Typelist<Product, ProductListTail> > {
163 inline static QWidget* multiFactory( const QString& appName, QWidget* parent,
164 const char* name, Qt::WFlags fl) {
165 QWidget* wid = OPrivate<Product>::multiFactory( appName, parent, name, fl );
166
167 if (!wid )
168 wid = OPrivate<ProductListTail>::multiFactory( appName, parent, name, fl );
169
170 return wid;
171 }
172
173 inline static QStringList multiString( const QStringList& _list ) {
174 QStringList list = _list;
175
176 list = OPrivate<Product>::multiString( list );
177 list = OPrivate<ProductListTail>::multiString( list );
178
179 return list;
180 }
181};
182
183
184
185
186
187
188
189
190/* Internal END */
191
192/*
193 * If you want to export more than one Widget use that function
194 * Make sure all your Widgets provide the appName() static method
195 * otherwise you'll get a compiler error
196 *
197 * typedef Opie::MakeTypeList<MyWidget, MyDialog, MyMediaPlayer >::Result MyTypes;
198 * OPIE_EXPORT_APP( OApplicationFactory<MyTypes> )
199 */
200
201template<class Product, class ProductListTail>
202struct OApplicationFactory< Opie::Typelist<Product, ProductListTail > >
203 : ApplicationInterface {
204 QRESULT queryInterface( const QUuid &uuid, QUnknownInterface **iface ) {
205 *iface = 0;
206 if ( uuid == IID_QUnknown ) *iface = this;
207 else if ( uuid ==IID_QtopiaApplication ) *iface = this;
208 else return QS_FALSE;
209 (*iface)->addRef();
210 return QS_OK;
211 }
212
213 QWidget* createMainWindow ( const QString& appName, QWidget* parent,
214 const char* name, Qt::WFlags fl ) {
215 qWarning("StringList is %s", applications().join(":").latin1() );
216 return OPrivate< Opie::Typelist<Product, ProductListTail > >::multiFactory( appName, parent, name, fl );
217 }
218
219 QStringList applications()const {
220 QStringList _list;
221 return OPrivate< Opie::Typelist<Product, ProductListTail> >::multiString( _list );
222 }
223
224 Q_REFCOUNT
225};
226
227
228/* If the library version should be build */
229#ifdef OPIE_APP_INTERFACE
230#define OPIE_EXPORT_APP( factory ) Q_EXPORT_INTERFACE() { Q_CREATE_INSTANCE( factory ) }
231#else
232
233#include <qpe/qpeapplication.h>
234
235#define OPIE_EXPORT_APP( Factory ) \
236int main( int argc, char **argv ) { \
237 QPEApplication a(argc, argv ); \
238 QWidget *mw = 0;\
239\
240 /* method from TT */ \
241 QString executableName = QString::fromLatin1( argv[0] ); \
242 executableName = executableName.right(executableName.length() \
243 - executableName.findRev('/') - 1); \
244 \
245 Factory f; \
246 QStringList list = f.applications(); \
247 if (list.contains(executableName) ) \
248 mw = f.createMainWindow(executableName, 0, 0, 0 ); \
249 else \
250 mw = f.createMainWindow( list[0], 0, 0, 0 ); \
251\
252 if( mw ) { \
253 if ( mw->metaObject()->slotNames().contains("setDocument(const QString&)" ) ) \
254 a.showMainDocumentWidget( mw ); \
255 else \
256 a.showMainWidget( mw ); \
257\
258 int rv = a.exec(); \
259 delete mw; \
260 return rv; \
261 }else \
262 return -1; \
263}
264#endif
diff --git a/noncore/unsupported/libopie/ocheckitem.cpp b/noncore/unsupported/libopie/ocheckitem.cpp
new file mode 100644
index 0000000..cd763c1
--- a/dev/null
+++ b/noncore/unsupported/libopie/ocheckitem.cpp
@@ -0,0 +1,105 @@
1/**********************************************************************
2** Copyright (C) 2002 Stefan Eilers (se, eilers.stefan@epost.de
3**
4** This file may be distributed and/or modified under the terms of the
5** GNU Library General Public License version 2 as published by the
6** Free Software Foundation and appearing in the file LICENSE.GPL
7** included in the packaging of this file.
8**
9** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11**********************************************************************/
12
13
14#include "ocheckitem.h"
15
16/**
17 * Constructs an CheckItem with a QTable as parent
18 * and a sort key for.
19 * The sort key will be used by QTable to sort the table later
20 * @param t The parent QTable where the check item belongs
21 * @param key A sort key
22 */
23OCheckItem::OCheckItem( QTable *t, const QString &key )
24 : QTableItem( t, Never, "" ), m_checked( FALSE ), m_sortKey( key )
25{
26}
27
28/**
29 * reimplemted for internal reasons
30 * @return Returns the sort key of the Item
31 * @see QTableItem
32 */
33QString OCheckItem::key() const
34{
35 return m_sortKey;
36}
37
38/**
39 * This method can check or uncheck the item. It will
40 * call QTable to update the cell.
41 *
42 * @param b Whether to check or uncheck the item
43 */
44void OCheckItem::setChecked( bool b )
45{
46 m_checked = b;
47 table()->updateCell( row(), col() );
48}
49
50/**
51 * This will toggle the item. If it is checked it'll get
52 * unchecked by this method or vice versa.
53 */
54void OCheckItem::toggle()
55{
56 m_checked = !m_checked;
57}
58
59/**
60 * This will return the state of the item.
61 *
62 * @return Returns true if the item is checked
63 */
64bool OCheckItem::isChecked() const
65{
66 return m_checked;
67}
68
69/**
70 * @internal
71 * This paints the item
72 */
73void OCheckItem::paint( QPainter *p, const QColorGroup &cg, const QRect &cr,
74 bool )
75{
76 p->fillRect( 0, 0, cr.width(), cr.height(), cg.brush( QColorGroup::Base ) );
77
78 int marg = ( cr.width() - BoxSize ) / 2;
79 int x = 0;
80 int y = ( cr.height() - BoxSize ) / 2;
81 p->setPen( QPen( cg.text() ) );
82 p->drawRect( x + marg, y, BoxSize, BoxSize );
83 p->drawRect( x + marg+1, y+1, BoxSize-2, BoxSize-2 );
84 p->setPen( darkGreen );
85 x += 1;
86 y += 1;
87 if ( m_checked ) {
88 QPointArray a( 7*2 );
89 int i, xx, yy;
90 xx = x+1+marg;
91 yy = y+2;
92 for ( i=0; i<3; i++ ) {
93 a.setPoint( 2*i, xx, yy );
94 a.setPoint( 2*i+1, xx, yy+2 );
95 xx++; yy++;
96 }
97 yy -= 2;
98 for ( i=3; i<7; i++ ) {
99 a.setPoint( 2*i, xx, yy );
100 a.setPoint( 2*i+1, xx, yy+2 );
101 xx++; yy--;
102 }
103 p->drawLineSegments( a );
104 }
105}
diff --git a/noncore/unsupported/libopie/ocheckitem.h b/noncore/unsupported/libopie/ocheckitem.h
new file mode 100644
index 0000000..82ee3d0
--- a/dev/null
+++ b/noncore/unsupported/libopie/ocheckitem.h
@@ -0,0 +1,62 @@
1/**********************************************************************
2** Copyright (C) 2002 Stefan Eilers (se, eilers.stefan@epost.de)
3**
4** This file may be distributed and/or modified under the terms of the
5** GNU Library General Public License version 2 as published by the
6** Free Software Foundation and appearing in the file LICENSE.GPL
7** included in the packaging of this file.
8**
9** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11**********************************************************************/
12#include <qtable.h>
13
14#ifndef CHECKITEM_H__
15#define CHECKITEM_H__
16
17/**
18 * This class represents a checkable QTableItem. This can
19 * be added to any QTable.
20 *
21 *
22 * @see QTable
23 * @see QTableItem
24 * @short An checkable QTableItem
25 * @version 1.0
26 * @author Stefan Eilers ( eilers@handhelds.org )
27 */
28
29class OCheckItem : public QTableItem
30{
31public:
32 /** The size of a box currently unused */
33 enum Size { BoxSize = 10 };
34 OCheckItem( QTable *t, const QString &sortkey );
35
36 virtual void setChecked( bool b );
37 virtual void toggle();
38 bool isChecked() const;
39 /**
40 * @short Set the sort key
41 * @reimp
42 */
43 void setKey( const QString &key ) { m_sortKey = key; }
44 virtual QString key() const;
45
46 /**
47 * foo
48 * @internal
49 */
50 void paint( QPainter *p, const QColorGroup &cg, const QRect &cr, bool selected );
51
52 //static const int BoxSize = 10;
53
54private:
55 class OCheckItemPrivate;
56 OCheckItemPrivate *d;
57 bool m_checked: 1;
58 QString m_sortKey;
59
60};
61
62#endif
diff --git a/noncore/unsupported/libopie/oclickablelabel.cpp b/noncore/unsupported/libopie/oclickablelabel.cpp
new file mode 100644
index 0000000..bc7037b
--- a/dev/null
+++ b/noncore/unsupported/libopie/oclickablelabel.cpp
@@ -0,0 +1,117 @@
1#include "oclickablelabel.h"
2#include <stdio.h>
3
4/**
5 * This constructs the clickable ButtonLabel
6 *
7 * @param parent The parent of this label
8 * @param name A name of this label @see QObject
9 * @param fl The windowing flags
10 */
11OClickableLabel::OClickableLabel(QWidget* parent,
12 const char* name,
13 WFlags fl) :
14 QLabel(parent,name,fl)
15{
16 textInverted=false;
17 isToggle=false;
18 isDown=false;
19 showState(false);
20 setFrameShadow(Sunken);
21}
22
23/**
24 * This method makes the label behave as a toggle button
25 *
26 * @param t Whether or not to behave like a toggle button
27 */
28void OClickableLabel::setToggleButton(bool t) {
29 isToggle=t;
30}
31
32/**
33 * @internal
34 */
35void OClickableLabel::mousePressEvent( QMouseEvent * /*e*/ ) {
36 if (isToggle && isDown) {
37 showState(false);
38 } else {
39 showState(true);
40 }
41}
42
43/**
44 * @internal
45 */
46void OClickableLabel::mouseReleaseEvent( QMouseEvent *e ) {
47 if (rect().contains(e->pos()) && isToggle) isDown=!isDown;
48
49 if (isToggle && isDown) {
50 showState(true);
51 } else {
52 showState(false);
53 }
54
55 if (rect().contains(e->pos())) {
56 if (isToggle) {
57 emit toggled(isDown);
58 }
59 emit clicked();
60 }
61}
62
63/**
64 * @internal
65 */
66void OClickableLabel::mouseMoveEvent( QMouseEvent *e ) {
67 if (rect().contains(e->pos())) {
68 if (isToggle && isDown) {
69 showState(false);
70 } else {
71 showState(true);
72 }
73 } else {
74 if (isToggle && isDown) {
75 showState(true);
76 } else {
77 showState(false);
78 }
79 }
80}
81
82/**
83 * this toggles the label and inverts the color of
84 * the label
85 * @param on
86 */
87void OClickableLabel::showState(bool on) {
88 if (on) {
89 //setFrameShape(Panel);
90 setInverted(true);
91 setBackgroundMode(PaletteHighlight);
92 } else {
93 //setFrameShape(NoFrame);
94 setInverted(false);
95 setBackgroundMode(PaletteBackground);
96 }
97 repaint();
98}
99
100void OClickableLabel::setInverted(bool on) {
101 if ( (!textInverted && on) || (textInverted && !on) ) {
102 QPalette pal=palette();
103 QColor col=pal.color(QPalette::Normal, QColorGroup::Foreground);
104 col.setRgb(255-col.red(),255-col.green(),255-col.blue());
105 pal.setColor(QPalette::Normal, QColorGroup::Foreground, col);
106 setPalette(pal);
107 textInverted=!textInverted;
108 }
109}
110
111/**
112 * @param on if the Label is down or up
113 */
114void OClickableLabel::setOn(bool on) {
115 isDown=on;
116 showState(isDown);
117}
diff --git a/noncore/unsupported/libopie/oclickablelabel.h b/noncore/unsupported/libopie/oclickablelabel.h
new file mode 100644
index 0000000..f93ade0
--- a/dev/null
+++ b/noncore/unsupported/libopie/oclickablelabel.h
@@ -0,0 +1,68 @@
1#ifndef CLICKABLELABEL
2#define CLICKABLELABEL
3
4#include <qlabel.h>
5
6/**
7 * This class is a special QLabel which can behave
8 * as a QPushButton or QToggleButton.
9 * The reason to use a clickable is if you want to save space
10 * or you want to skip the border of a normal button
11 *
12 * <pre>
13 * QLabel* lbl = new OClickableLabel( parent, "PushLabel" );
14 * lbl->setPixmap( "config" );
15 * QWhatsThis::add( lbl, tr("Click here to do something") );
16 * </pre>
17 *
18 * @short A Label behaving as button
19 * @author Hakan Ardo, Maximillian Reiß ( harlekin@handhelds.org )
20 * @see QLabel
21 * @see QPushButton
22 * @see QToggleButton
23 * @version 1.0
24 */
25
26class OClickableLabel: public QLabel
27{
28 Q_OBJECT
29public:
30 OClickableLabel(QWidget* parent = 0, const char* name = 0,
31 WFlags fl = 0);
32 void setToggleButton(bool t);
33
34 protected:
35 /** @internal */
36 void mousePressEvent( QMouseEvent *e );
37 /** @internal */
38 void mouseReleaseEvent( QMouseEvent *e );
39 /** @internal */
40 void mouseMoveEvent( QMouseEvent *e );
41
42 public slots:
43 void setOn(bool on);
44 signals:
45 /**
46 * emitted when the labels gets clicked
47 */
48 void clicked();
49
50 /**
51 * emitted when the labels gets toggled
52 * @param on the new new state of the label
53 */
54 void toggled(bool on);
55 private:
56 bool isToggle : 1;
57 bool isDown : 1;
58 bool textInverted : 1;
59
60 void showState(bool on);
61 void setInverted(bool on);
62
63 private:
64 class Private;
65 Private *d; // private d pointer
66};
67
68#endif
diff --git a/noncore/unsupported/libopie/ocolorbutton.cpp b/noncore/unsupported/libopie/ocolorbutton.cpp
new file mode 100644
index 0000000..298dba2
--- a/dev/null
+++ b/noncore/unsupported/libopie/ocolorbutton.cpp
@@ -0,0 +1,139 @@
1/*
2               =. This file is part of the OPIE Project
3             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
4           .>+-=
5 _;:,     .>    :=|. This library is free software; you can
6.> <`_,   >  .   <= redistribute it and/or modify it under
7:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
8.="- .-=="i,     .._ License as published by the Free Software
9 - .   .-<_>     .<> Foundation; either version 2 of the License,
10     ._= =}       : or (at your option) any later version.
11    .%`+i>       _;_.
12    .i_,=:_.      -<s. This library is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
17..}^=.=       =       ; Library General Public License for more
18++=   -.     .`     .: details.
19 :     =  ...= . :.=-
20 -.   .:....=;==+<; You should have received a copy of the GNU
21  -_. . .   )=.  = Library General Public License along with
22    --        :-=` this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation,
24 Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
26
27*/
28
29#include <opie/colorpopupmenu.h>
30#include <opie/ocolorbutton.h>
31
32#include <qpe/resource.h>
33
34struct OColorButtonPrivate {
35 QPopupMenu *m_menu;
36 QColor m_color;
37};
38
39
40/**
41 * This concstructs a Color Button with @param color as the start color
42 * It'll use a OColorPopupMenu internally
43 *
44 * @param parent The parent of the Color Button
45 * @param color The color from where to start on
46 * @param name @see QObject
47 */
48OColorButton::OColorButton ( QWidget *parent, const QColor &color, const char *name )
49 : QPushButton ( parent, name )
50{
51 d = new OColorButtonPrivate;
52
53 d-> m_menu = new OColorPopupMenu ( color, 0, 0 );
54 setPopup ( d-> m_menu );
55 //setPopupDelay ( 0 );
56 connect ( d-> m_menu, SIGNAL( colorSelected(const QColor&)), this, SLOT( updateColor(const QColor&)));
57
58 updateColor ( color );
59
60 QSize s = sizeHint ( ) + QSize ( 12, 0 );
61 setMinimumSize ( s );
62 setMaximumSize ( s. width ( ) * 2, s. height ( ));
63}
64
65/**
66 * This destructs the object
67 */
68OColorButton::~OColorButton ( )
69{
70 delete d;
71}
72
73/**
74 * @return Returns the current color of the button
75 */
76QColor OColorButton::color ( ) const
77{
78 return d-> m_color;
79}
80
81/**
82 * This method sets the color of the button
83 * @param c The color to be set.
84 */
85void OColorButton::setColor ( const QColor &c )
86{
87 updateColor ( c );
88}
89
90/**
91 * @internal
92 */
93void OColorButton::updateColor ( const QColor &c )
94{
95 d-> m_color = c;
96
97 QImage img ( 16, 16, 32 );
98 img. fill ( 0 );
99
100 int r, g, b;
101 c. rgb ( &r, &g, &b );
102
103 int w = img. width ( );
104 int h = img. height ( );
105
106 int dx = w * 20 / 100; // 15%
107 int dy = h * 20 / 100;
108
109 for ( int y = 0; y < h; y++ ) {
110 for ( int x = 0; x < w; x++ ) {
111 double alpha = 1.0;
112
113 if ( x < dx )
114 alpha *= ( double ( x + 1 ) / dx );
115 else if ( x >= w - dx )
116 alpha *= ( double ( w - x ) / dx );
117 if ( y < dy )
118 alpha *= ( double ( y + 1 ) / dy );
119 else if ( y >= h - dy )
120 alpha *= ( double ( h - y ) / dy );
121
122 int a = int ( alpha * 255.0 );
123 if ( a < 0 )
124 a = 0;
125 if ( a > 255 )
126 a = 255;
127
128 img. setPixel ( x, y, qRgba ( r, g, b, a ));
129 }
130 }
131 img. setAlphaBuffer ( true );
132
133 QPixmap pix;
134 pix. convertFromImage ( img );
135 setPixmap ( pix );
136
137 emit colorSelected ( c );
138}
139
diff --git a/noncore/unsupported/libopie/ocolorbutton.h b/noncore/unsupported/libopie/ocolorbutton.h
new file mode 100644
index 0000000..6196c83
--- a/dev/null
+++ b/noncore/unsupported/libopie/ocolorbutton.h
@@ -0,0 +1,73 @@
1/*
2               =. This file is part of the OPIE Project
3             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
4           .>+-=
5 _;:,     .>    :=|. This library is free software; you can
6.> <`_,   >  .   <= redistribute it and/or modify it under
7:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
8.="- .-=="i,     .._ License as published by the Free Software
9 - .   .-<_>     .<> Foundation; either version 2 of the License,
10     ._= =}       : or (at your option) any later version.
11    .%`+i>       _;_.
12    .i_,=:_.      -<s. This library is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
17..}^=.=       =       ; Library General Public License for more
18++=   -.     .`     .: details.
19 :     =  ...= . :.=-
20 -.   .:....=;==+<; You should have received a copy of the GNU
21  -_. . .   )=.  = Library General Public License along with
22    --        :-=` this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation,
24 Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
26
27*/
28
29#ifndef __OPIE_OCOLORBUTTON_H__
30#define __OPIE_OCOLORBUTTON_H__
31
32#include <qpushbutton.h>
33
34class OColorButtonPrivate;
35class QColor;
36
37/**
38 *
39 * @short A Button which will show a OColorPopupMenu
40 * @author Robert Griebl ( sandman@handhelds.org )
41 * @version 1.0
42 * @see QPushButton
43 */
44class OColorButton : public QPushButton {
45 Q_OBJECT
46public:
47 // FIXME Wflags? -zecke
48 OColorButton ( QWidget *parent = 0, const QColor & = black, const char *name = 0 );
49 virtual ~OColorButton ( );
50
51 QColor color ( ) const;
52
53signals:
54 /**
55 * emitted when a color gets selected
56 */
57 void colorSelected ( const QColor & );
58
59public slots:
60 virtual void setColor ( const QColor & );
61
62protected slots:
63 /**
64 * @internal
65 */
66 virtual void updateColor ( const QColor & );
67
68private:
69 OColorButtonPrivate *d;
70};
71
72#endif
73
diff --git a/noncore/unsupported/libopie/odevice.cpp b/noncore/unsupported/libopie/odevice.cpp
new file mode 100644
index 0000000..9d0bbbf
--- a/dev/null
+++ b/noncore/unsupported/libopie/odevice.cpp
@@ -0,0 +1,2827 @@
1/* This file is part of the OPIE libraries
2 Copyright (C) 2002 Robert Griebl (sandman@handhelds.org)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20#include <stdlib.h>
21#include <unistd.h>
22#include <fcntl.h>
23#include <sys/ioctl.h>
24#include <signal.h>
25#include <sys/time.h>
26#ifndef QT_NO_SOUND
27#include <linux/soundcard.h>
28#endif
29#include <math.h>
30
31
32#include <qfile.h>
33#include <qtextstream.h>
34#include <qpe/sound.h>
35#include <qpe/resource.h>
36#include <qpe/config.h>
37#include <qpe/qcopenvelope_qws.h>
38
39#include "odevice.h"
40
41#include <qwindowsystem_qws.h>
42
43#ifndef ARRAY_SIZE
44#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
45#endif
46
47// _IO and friends are only defined in kernel headers ...
48
49#define OD_IOC(dir,type,number,size) (( dir << 30 ) | ( type << 8 ) | ( number ) | ( size << 16 ))
50
51#define OD_IO(type,number) OD_IOC(0,type,number,0)
52#define OD_IOW(type,number,size) OD_IOC(1,type,number,sizeof(size))
53#define OD_IOR(type,number,size) OD_IOC(2,type,number,sizeof(size))
54#define OD_IORW(type,number,size) OD_IOC(3,type,number,sizeof(size))
55
56using namespace Opie;
57
58class ODeviceData {
59public:
60 QString m_vendorstr;
61 OVendor m_vendor;
62
63 QString m_modelstr;
64 OModel m_model;
65
66 QString m_systemstr;
67 OSystem m_system;
68
69 QString m_sysverstr;
70
71 Transformation m_rotation;
72 ODirection m_direction;
73
74 QValueList <ODeviceButton> *m_buttons;
75 uint m_holdtime;
76 QStrList *m_cpu_frequencies;
77
78};
79
80class iPAQ : public ODevice, public QWSServer::KeyboardFilter {
81protected:
82 virtual void init ( );
83 virtual void initButtons ( );
84
85public:
86 virtual bool setSoftSuspend ( bool soft );
87
88 virtual bool setDisplayBrightness ( int b );
89 virtual int displayBrightnessResolution ( ) const;
90
91 virtual void alarmSound ( );
92
93 virtual QValueList <OLed> ledList ( ) const;
94 virtual QValueList <OLedState> ledStateList ( OLed led ) const;
95 virtual OLedState ledState ( OLed led ) const;
96 virtual bool setLedState ( OLed led, OLedState st );
97
98 virtual bool hasLightSensor ( ) const;
99 virtual int readLightSensor ( );
100 virtual int lightSensorResolution ( ) const;
101
102protected:
103 virtual bool filter ( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat );
104 virtual void timerEvent ( QTimerEvent *te );
105
106 int m_power_timer;
107
108 OLedState m_leds [2];
109};
110
111class Jornada : public ODevice {
112protected:
113 virtual void init ( );
114 //virtual void initButtons ( );
115public:
116 virtual bool setSoftSuspend ( bool soft );
117 virtual bool setDisplayBrightness ( int b );
118 virtual int displayBrightnessResolution ( ) const;
119 static bool isJornada();
120
121};
122
123class Zaurus : public ODevice {
124protected:
125 virtual void init ( );
126 virtual void initButtons ( );
127
128public:
129 virtual bool setSoftSuspend ( bool soft );
130
131 virtual bool setDisplayBrightness ( int b );
132 virtual int displayBrightnessResolution ( ) const;
133
134 virtual void alarmSound ( );
135 virtual void keySound ( );
136 virtual void touchSound ( );
137
138 virtual QValueList <OLed> ledList ( ) const;
139 virtual QValueList <OLedState> ledStateList ( OLed led ) const;
140 virtual OLedState ledState ( OLed led ) const;
141 virtual bool setLedState ( OLed led, OLedState st );
142
143 bool hasHingeSensor() const;
144 OHingeStatus readHingeSensor();
145
146 static bool isZaurus();
147
148 // Does this break BC?
149 virtual bool suspend ( );
150 Transformation rotation ( ) const;
151 ODirection direction ( ) const;
152
153protected:
154 virtual void buzzer ( int snd );
155
156 OLedState m_leds [1];
157 bool m_embedix;
158 void virtual_hook( int id, void *data );
159};
160
161class SIMpad : public ODevice, public QWSServer::KeyboardFilter {
162protected:
163 virtual void init ( );
164 virtual void initButtons ( );
165
166public:
167 virtual bool setSoftSuspend ( bool soft );
168 virtual bool suspend();
169
170 virtual bool setDisplayStatus( bool on );
171 virtual bool setDisplayBrightness ( int b );
172 virtual int displayBrightnessResolution ( ) const;
173
174 virtual void alarmSound ( );
175
176 virtual QValueList <OLed> ledList ( ) const;
177 virtual QValueList <OLedState> ledStateList ( OLed led ) const;
178 virtual OLedState ledState ( OLed led ) const;
179 virtual bool setLedState ( OLed led, OLedState st );
180
181protected:
182 virtual bool filter ( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat );
183 virtual void timerEvent ( QTimerEvent *te );
184
185 int m_power_timer;
186
187 OLedState m_leds [1]; //FIXME check if really only one
188};
189
190class Ramses : public ODevice, public QWSServer::KeyboardFilter {
191protected:
192 virtual void init ( );
193
194public:
195 virtual bool setSoftSuspend ( bool soft );
196 virtual bool suspend ( );
197
198 virtual bool setDisplayStatus( bool on );
199 virtual bool setDisplayBrightness ( int b );
200 virtual int displayBrightnessResolution ( ) const;
201 virtual bool setDisplayContrast ( int b );
202 virtual int displayContrastResolution ( ) const;
203
204protected:
205 virtual bool filter ( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat );
206 virtual void timerEvent ( QTimerEvent *te );
207
208 int m_power_timer;
209};
210
211struct i_button {
212 uint model;
213 Qt::Key code;
214 char *utext;
215 char *pix;
216 char *fpressedservice;
217 char *fpressedaction;
218 char *fheldservice;
219 char *fheldaction;
220} ipaq_buttons [] = {
221 { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
222 Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
223 "devicebuttons/ipaq_calendar",
224 "datebook", "nextView()",
225 "today", "raise()" },
226 { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
227 Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
228 "devicebuttons/ipaq_contact",
229 "addressbook", "raise()",
230 "addressbook", "beamBusinessCard()" },
231 { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx,
232 Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
233 "devicebuttons/ipaq_menu",
234 "QPE/TaskBar", "toggleMenu()",
235 "QPE/TaskBar", "toggleStartMenu()" },
236 { Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
237 Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
238 "devicebuttons/ipaq_mail",
239 "mail", "raise()",
240 "mail", "newMail()" },
241 { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
242 Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
243 "devicebuttons/ipaq_home",
244 "QPE/Launcher", "home()",
245 "buttonsettings", "raise()" },
246 { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
247 Qt::Key_F24, QT_TRANSLATE_NOOP("Button", "Record Button"),
248 "devicebuttons/ipaq_record",
249 "QPE/VMemo", "toggleRecord()",
250 "sound", "raise()" },
251};
252
253struct z_button {
254 Qt::Key code;
255 char *utext;
256 char *pix;
257 char *fpressedservice;
258 char *fpressedaction;
259 char *fheldservice;
260 char *fheldaction;
261} z_buttons [] = {
262 { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
263 "devicebuttons/z_calendar",
264 "datebook", "nextView()",
265 "today", "raise()" },
266 { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
267 "devicebuttons/z_contact",
268 "addressbook", "raise()",
269 "addressbook", "beamBusinessCard()" },
270 { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
271 "devicebuttons/z_home",
272 "QPE/Launcher", "home()",
273 "buttonsettings", "raise()" },
274 { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
275 "devicebuttons/z_menu",
276 "QPE/TaskBar", "toggleMenu()",
277 "QPE/TaskBar", "toggleStartMenu()" },
278 { Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
279 "devicebuttons/z_mail",
280 "mail", "raise()",
281 "mail", "newMail()" },
282};
283
284struct z_button z_buttons_c700 [] = {
285 { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
286 "devicebuttons/z_calendar",
287 "datebook", "nextView()",
288 "today", "raise()" },
289 { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
290 "devicebuttons/z_contact",
291 "addressbook", "raise()",
292 "addressbook", "beamBusinessCard()" },
293 { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
294 "devicebuttons/z_home",
295 "QPE/Launcher", "home()",
296 "buttonsettings", "raise()" },
297 { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
298 "devicebuttons/z_menu",
299 "QPE/TaskBar", "toggleMenu()",
300 "QPE/TaskBar", "toggleStartMenu()" },
301 { Qt::Key_F14, QT_TRANSLATE_NOOP("Button", "Display Rotate"),
302 "devicebuttons/z_hinge",
303 "QPE/Rotation", "rotateDefault()",
304 "QPE/Dummy", "doNothing()" },
305};
306
307struct s_button {
308 uint model;
309 Qt::Key code;
310 char *utext;
311 char *pix;
312 char *fpressedservice;
313 char *fpressedaction;
314 char *fheldservice;
315 char *fheldaction;
316} simpad_buttons [] = {
317 { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
318 Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Lower+Up"),
319 "devicebuttons/simpad_lower_up",
320 "datebook", "nextView()",
321 "today", "raise()" },
322 { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
323 Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Lower+Down"),
324 "devicebuttons/simpad_lower_down",
325 "addressbook", "raise()",
326 "addressbook", "beamBusinessCard()" },
327 { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
328 Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Lower+Right"),
329 "devicebuttons/simpad_lower_right",
330 "QPE/TaskBar", "toggleMenu()",
331 "QPE/TaskBar", "toggleStartMenu()" },
332 { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
333 Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Lower+Left"),
334 "devicebuttons/simpad_lower_left",
335 "mail", "raise()",
336 "mail", "newMail()" },
337
338 { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
339 Qt::Key_F5, QT_TRANSLATE_NOOP("Button", "Upper+Up"),
340 "devicebuttons/simpad_upper_up",
341 "QPE/Launcher", "home()",
342 "buttonsettings", "raise()" },
343 { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
344 Qt::Key_F6, QT_TRANSLATE_NOOP("Button", "Upper+Down"),
345 "devicebuttons/simpad_upper_down",
346 "addressbook", "raise()",
347 "addressbook", "beamBusinessCard()" },
348 { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
349 Qt::Key_F7, QT_TRANSLATE_NOOP("Button", "Upper+Right"),
350 "devicebuttons/simpad_upper_right",
351 "QPE/TaskBar", "toggleMenu()",
352 "QPE/TaskBar", "toggleStartMenu()" },
353 { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
354 Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Upper+Left"),
355 "devicebuttons/simpad_upper_left",
356 "QPE/Rotation", "flip()",
357 "QPE/Rotation", "flip()" },
358 /*
359 { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
360 Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Lower+Upper"),
361 "devicebuttons/simpad_lower_upper",
362 "QPE/Launcher", "home()",
363 "buttonsettings", "raise()" },
364 { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
365 Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Lower+Upper"),
366 "devicebuttons/simpad_upper_lower",
367 "QPE/Launcher", "home()",
368 "buttonsettings", "raise()" },
369 */
370};
371
372class Yopy : public ODevice {
373protected:
374 virtual void init ( );
375 virtual void initButtons ( );
376
377public:
378 virtual bool suspend ( );
379
380 virtual bool setDisplayBrightness ( int b );
381 virtual int displayBrightnessResolution ( ) const;
382
383 static bool isYopy ( );
384};
385
386struct yopy_button {
387 Qt::Key code;
388 char *utext;
389 char *pix;
390 char *fpressedservice;
391 char *fpressedaction;
392 char *fheldservice;
393 char *fheldaction;
394} yopy_buttons [] = {
395 { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Action Button"),
396 "devicebuttons/yopy_action",
397 "datebook", "nextView()",
398 "today", "raise()" },
399 { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "OK Button"),
400 "devicebuttons/yopy_ok",
401 "addressbook", "raise()",
402 "addressbook", "beamBusinessCard()" },
403 { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "End Button"),
404 "devicebuttons/yopy_end",
405 "QPE/Launcher", "home()",
406 "buttonsettings", "raise()" },
407};
408
409static QCString makeChannel ( const char *str )
410{
411 if ( str && !::strchr ( str, '/' ))
412 return QCString ( "QPE/Application/" ) + str;
413 else
414 return str;
415}
416
417static inline bool isQWS()
418{
419 return qApp ? ( qApp-> type ( ) == QApplication::GuiServer ) : false;
420}
421
422ODevice *ODevice::inst ( )
423{
424 static ODevice *dev = 0;
425
426 if ( !dev ) {
427 if ( QFile::exists ( "/proc/hal/model" ))
428 dev = new iPAQ ( );
429 else if ( Zaurus::isZaurus() )
430 dev = new Zaurus ( );
431 else if ( QFile::exists ( "/proc/ucb1x00" ) && QFile::exists ( "/proc/cs3" ))
432 dev = new SIMpad ( );
433 else if ( Yopy::isYopy() )
434 dev = new Yopy ( );
435 else if ( Jornada::isJornada() )
436 dev = new Jornada ( );
437 else if ( QFile::exists ( "/proc/sys/board/sys_name" ))
438 dev = new Ramses ( );
439 else
440 dev = new ODevice ( );
441 dev-> init ( );
442 }
443 return dev;
444}
445
446
447/**************************************************
448 *
449 * common
450 *
451 **************************************************/
452
453
454ODevice::ODevice ( )
455{
456 d = new ODeviceData;
457
458 d-> m_modelstr = "Unknown";
459 d-> m_model = Model_Unknown;
460 d-> m_vendorstr = "Unknown";
461 d-> m_vendor = Vendor_Unknown;
462 d-> m_systemstr = "Unknown";
463 d-> m_system = System_Unknown;
464 d-> m_sysverstr = "0.0";
465 d-> m_rotation = Rot0;
466 d-> m_direction = CW;
467
468 d-> m_holdtime = 1000; // 1000ms
469 d-> m_buttons = 0;
470 d-> m_cpu_frequencies = new QStrList;
471}
472
473void ODevice::systemMessage ( const QCString &msg, const QByteArray & )
474{
475 if ( msg == "deviceButtonMappingChanged()" ) {
476 reloadButtonMapping ( );
477 }
478}
479
480void ODevice::init ( )
481{
482}
483
484/**
485 * This method initialises the button mapping
486 */
487void ODevice::initButtons ( )
488{
489 if ( d-> m_buttons )
490 return;
491
492 // Simulation uses iPAQ 3660 device buttons
493
494 qDebug ( "init Buttons" );
495 d-> m_buttons = new QValueList <ODeviceButton>;
496
497 for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) {
498 i_button *ib = ipaq_buttons + i;
499 ODeviceButton b;
500
501 if (( ib-> model & Model_iPAQ_H36xx ) == Model_iPAQ_H36xx ) {
502 b. setKeycode ( ib-> code );
503 b. setUserText ( QObject::tr ( "Button", ib-> utext ));
504 b. setPixmap ( Resource::loadPixmap ( ib-> pix ));
505 b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib-> fpressedservice ), ib-> fpressedaction ));
506 b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib-> fheldservice ), ib-> fheldaction ));
507 d-> m_buttons-> append ( b );
508 }
509 }
510 reloadButtonMapping ( );
511
512 QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
513 connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( systemMessage(const QCString&,const QByteArray&)));
514}
515
516ODevice::~ODevice ( )
517{
518// we leak m_devicebuttons and m_cpu_frequency
519// but it's a singleton and it is not so importantant
520// -zecke
521 delete d;
522}
523
524bool ODevice::setSoftSuspend ( bool /*soft*/ )
525{
526 return false;
527}
528
529//#include <linux/apm_bios.h>
530
531#define APM_IOC_SUSPEND OD_IO( 'A', 2 )
532
533/**
534 * This method will try to suspend the device
535 * It only works if the user is the QWS Server and the apm application
536 * is installed.
537 * It tries to suspend and then waits some time cause some distributions
538 * do have asynchronus apm implementations.
539 * This method will either fail and return false or it'll suspend the
540 * device and return once the device got woken up
541 *
542 * @return if the device got suspended
543 */
544bool ODevice::suspend ( )
545{
546 qDebug("ODevice::suspend");
547 if ( !isQWS( ) ) // only qwsserver is allowed to suspend
548 return false;
549
550 if ( d-> m_model == Model_Unknown ) // better don't suspend in qvfb / on unkown devices
551 return false;
552
553 bool res = false;
554
555 struct timeval tvs, tvn;
556 ::gettimeofday ( &tvs, 0 );
557
558 ::sync ( ); // flush fs caches
559 res = ( ::system ( "apm --suspend" ) == 0 );
560
561 // This is needed because the iPAQ apm implementation is asynchronous and we
562 // can not be sure when exactly the device is really suspended
563 // This can be deleted as soon as a stable familiar with a synchronous apm implementation exists.
564
565 if ( res ) {
566 do { // wait at most 1.5 sec: either suspend didn't work or the device resumed
567 ::usleep ( 200 * 1000 );
568 ::gettimeofday ( &tvn, 0 );
569 } while ((( tvn. tv_sec - tvs. tv_sec ) * 1000 + ( tvn. tv_usec - tvs. tv_usec ) / 1000 ) < 1500 );
570 }
571
572 return res;
573}
574
575//#include <linux/fb.h> better not rely on kernel headers in userspace ...
576
577#define FBIOBLANK OD_IO( 'F', 0x11 ) // 0x4611
578
579/* VESA Blanking Levels */
580#define VESA_NO_BLANKING 0
581#define VESA_VSYNC_SUSPEND 1
582#define VESA_HSYNC_SUSPEND 2
583#define VESA_POWERDOWN 3
584
585/**
586 * This sets the display on or off
587 */
588bool ODevice::setDisplayStatus ( bool on )
589{
590 qDebug("ODevice::setDisplayStatus(%d)", on);
591
592 if ( d-> m_model == Model_Unknown )
593 return false;
594
595 bool res = false;
596 int fd;
597
598#ifdef QT_QWS_DEVFS
599 if (( fd = ::open ( "/dev/fb/0", O_RDWR )) >= 0 ) {
600#else
601 if (( fd = ::open ( "/dev/fb0", O_RDWR )) >= 0 ) {
602#endif
603 res = ( ::ioctl ( fd, FBIOBLANK, on ? VESA_NO_BLANKING : VESA_POWERDOWN ) == 0 );
604 ::close ( fd );
605 }
606 return res;
607}
608
609/**
610 * This sets the display brightness
611 *
612 * @param p The brightness to be set on a scale from 0 to 255
613 * @return success or failure
614 */
615bool ODevice::setDisplayBrightness ( int p)
616{
617 Q_UNUSED( p )
618 return false;
619}
620
621/**
622 * @return returns the number of steppings on the brightness slider
623 * in the Light-'n-Power settings.
624 */
625int ODevice::displayBrightnessResolution ( ) const
626{
627 return 16;
628}
629
630/**
631 * This sets the display contrast
632 * @param p The contrast to be set on a scale from 0 to 255
633 * @return success or failure
634 */
635bool ODevice::setDisplayContrast ( int p)
636{
637 Q_UNUSED( p )
638 return false;
639}
640
641/**
642 * @return return the max value for the brightness settings slider
643 * or 0 if the device doesn't support setting of a contrast
644 */
645int ODevice::displayContrastResolution ( ) const
646{
647 return 0;
648}
649
650/**
651 * This returns the vendor as string
652 * @return Vendor as QString
653 */
654QString ODevice::vendorString ( ) const
655{
656 return d-> m_vendorstr;
657}
658
659/**
660 * This returns the vendor as one of the values of OVendor
661 * @return OVendor
662 */
663OVendor ODevice::vendor ( ) const
664{
665 return d-> m_vendor;
666}
667
668/**
669 * This returns the model as a string
670 * @return A string representing the model
671 */
672QString ODevice::modelString ( ) const
673{
674 return d-> m_modelstr;
675}
676
677/**
678 * This does return the OModel used
679 */
680OModel ODevice::model ( ) const
681{
682 return d-> m_model;
683}
684
685/**
686 * This does return the systen name
687 */
688QString ODevice::systemString ( ) const
689{
690 return d-> m_systemstr;
691}
692
693/**
694 * Return System as OSystem value
695 */
696OSystem ODevice::system ( ) const
697{
698 return d-> m_system;
699}
700
701/**
702 * @return the version string of the base system
703 */
704QString ODevice::systemVersionString ( ) const
705{
706 return d-> m_sysverstr;
707}
708
709/**
710 * @return the current Transformation
711 */
712Transformation ODevice::rotation ( ) const
713{
714 VirtRotation rot;
715 ODevice* that =(ODevice* )this;
716 that->virtual_hook( VIRTUAL_ROTATION, &rot );
717 return rot.trans;
718}
719
720/**
721 * @return the current rotation direction
722 */
723ODirection ODevice::direction ( ) const
724{
725 VirtDirection dir;
726 ODevice* that =(ODevice* )this;
727 that->virtual_hook( VIRTUAL_DIRECTION, &dir );
728 return dir.direct;
729}
730
731/**
732 * This plays an alarmSound
733 */
734void ODevice::alarmSound ( )
735{
736#ifndef QT_NO_SOUND
737 static Sound snd ( "alarm" );
738
739 if ( snd. isFinished ( ))
740 snd. play ( );
741#endif
742}
743
744/**
745 * This plays a key sound
746 */
747void ODevice::keySound ( )
748{
749#ifndef QT_NO_SOUND
750 static Sound snd ( "keysound" );
751
752 if ( snd. isFinished ( ))
753 snd. play ( );
754#endif
755}
756
757/**
758 * This plays a touch sound
759 */
760void ODevice::touchSound ( )
761{
762#ifndef QT_NO_SOUND
763 static Sound snd ( "touchsound" );
764
765 if ( snd. isFinished ( ))
766 snd. play ( );
767#endif
768}
769
770/**
771 * This method will return a list of leds
772 * available on this device
773 * @return a list of LEDs.
774 */
775QValueList <OLed> ODevice::ledList ( ) const
776{
777 return QValueList <OLed> ( );
778}
779
780/**
781 * This does return the state of the LEDs
782 */
783QValueList <OLedState> ODevice::ledStateList ( OLed /*which*/ ) const
784{
785 return QValueList <OLedState> ( );
786}
787
788/**
789 * @return the state for a given OLed
790 */
791OLedState ODevice::ledState ( OLed /*which*/ ) const
792{
793 return Led_Off;
794}
795
796/**
797 * Set the state for a LED
798 * @param which Which OLed to use
799 * @param st The state to set
800 * @return success or failure
801 */
802bool ODevice::setLedState ( OLed which, OLedState st )
803{
804 Q_UNUSED( which )
805 Q_UNUSED( st )
806 return false;
807}
808
809/**
810 * @return if the device has a light sensor
811 */
812bool ODevice::hasLightSensor ( ) const
813{
814 return false;
815}
816
817/**
818 * @return a value from the light sensor
819 */
820int ODevice::readLightSensor ( )
821{
822 return -1;
823}
824
825/**
826 * @return the light sensor resolution
827 */
828int ODevice::lightSensorResolution ( ) const
829{
830 return 0;
831}
832
833/**
834 * @return if the device has a hinge sensor
835 */
836bool ODevice::hasHingeSensor ( ) const
837{
838 VirtHasHinge hing;
839 ODevice* that =(ODevice* )this;
840 that->virtual_hook( VIRTUAL_HAS_HINGE, &hing );
841 return hing.hasHinge;
842}
843
844/**
845 * @return a value from the hinge sensor
846 */
847OHingeStatus ODevice::readHingeSensor ( )
848{
849 VirtHingeStatus hing;
850 virtual_hook( VIRTUAL_HINGE, &hing );
851 return hing.hingeStat;
852}
853
854/**
855 * @return a list with CPU frequencies supported by the hardware
856 */
857const QStrList &ODevice::allowedCpuFrequencies ( ) const
858{
859 return *d->m_cpu_frequencies;
860}
861
862
863/**
864 * Set desired CPU frequency
865 *
866 * @param index index into d->m_cpu_frequencies of the frequency to be set
867 */
868bool ODevice::setCurrentCpuFrequency(uint index)
869{
870 if (index >= d->m_cpu_frequencies->count())
871 return false;
872
873 char *freq = d->m_cpu_frequencies->at(index);
874 qWarning("set freq to %s", freq);
875
876 int fd;
877
878 if ((fd = ::open("/proc/sys/cpu/0/speed", O_WRONLY)) >= 0) {
879 char writeCommand[50];
880 const int count = sprintf(writeCommand, "%s\n", freq);
881 int res = (::write(fd, writeCommand, count) != -1);
882 ::close(fd);
883 return res;
884 }
885
886 return false;
887}
888
889
890/**
891 * @return a list of hardware buttons
892 */
893const QValueList <ODeviceButton> &ODevice::buttons ( )
894{
895 initButtons ( );
896
897 return *d-> m_buttons;
898}
899
900/**
901 * @return The amount of time that would count as a hold
902 */
903uint ODevice::buttonHoldTime ( ) const
904{
905 return d-> m_holdtime;
906}
907
908/**
909 * This method return a ODeviceButton for a key code
910 * or 0 if no special hardware button is available for the device
911 *
912 * @return The devicebutton or 0l
913 * @see ODeviceButton
914 */
915const ODeviceButton *ODevice::buttonForKeycode ( ushort code )
916{
917 initButtons ( );
918
919 for ( QValueListConstIterator<ODeviceButton> it = d-> m_buttons-> begin ( ); it != d-> m_buttons-> end ( ); ++it ) {
920 if ( (*it). keycode ( ) == code )
921 return &(*it);
922 }
923 return 0;
924}
925
926void ODevice::reloadButtonMapping ( )
927{
928 initButtons ( );
929
930 Config cfg ( "ButtonSettings" );
931
932 for ( uint i = 0; i < d-> m_buttons-> count ( ); i++ ) {
933 ODeviceButton &b = ( *d-> m_buttons ) [i];
934 QString group = "Button" + QString::number ( i );
935
936 QCString pch, hch;
937 QCString pm, hm;
938 QByteArray pdata, hdata;
939
940 if ( cfg. hasGroup ( group )) {
941 cfg. setGroup ( group );
942 pch = cfg. readEntry ( "PressedActionChannel" ). latin1 ( );
943 pm = cfg. readEntry ( "PressedActionMessage" ). latin1 ( );
944 // pdata = decodeBase64 ( buttonFile. readEntry ( "PressedActionArgs" ));
945
946 hch = cfg. readEntry ( "HeldActionChannel" ). latin1 ( );
947 hm = cfg. readEntry ( "HeldActionMessage" ). latin1 ( );
948 // hdata = decodeBase64 ( buttonFile. readEntry ( "HeldActionArgs" ));
949 }
950
951 b. setPressedAction ( OQCopMessage ( pch, pm, pdata ));
952
953 b. setHeldAction ( OQCopMessage ( hch, hm, hdata ));
954 }
955}
956
957void ODevice::remapPressedAction ( int button, const OQCopMessage &action )
958{
959 initButtons ( );
960
961 QString mb_chan;
962
963 if ( button >= (int) d-> m_buttons-> count ( ))
964 return;
965
966 ODeviceButton &b = ( *d-> m_buttons ) [button];
967 b. setPressedAction ( action );
968
969 mb_chan=b. pressedAction ( ). channel ( );
970
971 Config buttonFile ( "ButtonSettings" );
972 buttonFile. setGroup ( "Button" + QString::number ( button ));
973 buttonFile. writeEntry ( "PressedActionChannel", (const char*) mb_chan);
974 buttonFile. writeEntry ( "PressedActionMessage", (const char*) b. pressedAction ( ). message ( ));
975
976 //buttonFile. writeEntry ( "PressedActionArgs", encodeBase64 ( b. pressedAction ( ). data ( )));
977
978 QCopEnvelope ( "QPE/System", "deviceButtonMappingChanged()" );
979}
980
981void ODevice::remapHeldAction ( int button, const OQCopMessage &action )
982{
983 initButtons ( );
984
985 if ( button >= (int) d-> m_buttons-> count ( ))
986 return;
987
988 ODeviceButton &b = ( *d-> m_buttons ) [button];
989 b. setHeldAction ( action );
990
991 Config buttonFile ( "ButtonSettings" );
992 buttonFile. setGroup ( "Button" + QString::number ( button ));
993 buttonFile. writeEntry ( "HeldActionChannel", (const char *) b. heldAction ( ). channel ( ));
994 buttonFile. writeEntry ( "HeldActionMessage", (const char *) b. heldAction ( ). message ( ));
995
996 //buttonFile. writeEntry ( "HeldActionArgs", decodeBase64 ( b. heldAction ( ). data ( )));
997
998 QCopEnvelope ( "QPE/System", "deviceButtonMappingChanged()" );
999}
1000void ODevice::virtual_hook(int id, void* data){
1001 switch( id ) {
1002 case VIRTUAL_ROTATION:{
1003 VirtRotation* rot = reinterpret_cast<VirtRotation*>( data );
1004 rot->trans = d->m_rotation;
1005 break;
1006 }
1007 case VIRTUAL_DIRECTION:{
1008 VirtDirection *dir = reinterpret_cast<VirtDirection*>( data );
1009 dir->direct = d->m_direction;
1010 break;
1011 }
1012 case VIRTUAL_HAS_HINGE:{
1013 VirtHasHinge *hin = reinterpret_cast<VirtHasHinge*>( data );
1014 hin->hasHinge = false;
1015 break;
1016 }
1017 case VIRTUAL_HINGE:{
1018 VirtHingeStatus *hin = reinterpret_cast<VirtHingeStatus*>( data );
1019 hin->hingeStat = CASE_UNKNOWN;
1020 break;
1021 }
1022 }
1023}
1024
1025/**************************************************
1026 *
1027 * Yopy 3500/3700
1028 *
1029 **************************************************/
1030
1031bool Yopy::isYopy ( )
1032{
1033 QFile f( "/proc/cpuinfo" );
1034 if ( f. open ( IO_ReadOnly ) ) {
1035 QTextStream ts ( &f );
1036 QString line;
1037 while( line = ts. readLine ( ) ) {
1038 if ( line. left ( 8 ) == "Hardware" ) {
1039 int loc = line. find ( ":" );
1040 if ( loc != -1 ) {
1041 QString model =
1042 line. mid ( loc + 2 ). simplifyWhiteSpace( );
1043 return ( model == "Yopy" );
1044 }
1045 }
1046 }
1047 }
1048 return false;
1049}
1050
1051void Yopy::init ( )
1052{
1053 d-> m_vendorstr = "G.Mate";
1054 d-> m_vendor = Vendor_GMate;
1055 d-> m_modelstr = "Yopy3700";
1056 d-> m_model = Model_Yopy_3700;
1057 d-> m_rotation = Rot0;
1058
1059 d-> m_systemstr = "Linupy";
1060 d-> m_system = System_Linupy;
1061
1062 QFile f ( "/etc/issue" );
1063 if ( f. open ( IO_ReadOnly )) {
1064 QTextStream ts ( &f );
1065 ts.readLine();
1066 d-> m_sysverstr = ts. readLine ( );
1067 f. close ( );
1068 }
1069}
1070
1071void Yopy::initButtons ( )
1072{
1073 if ( d-> m_buttons )
1074 return;
1075
1076 d-> m_buttons = new QValueList <ODeviceButton>;
1077
1078 for (uint i = 0; i < ( sizeof( yopy_buttons ) / sizeof(yopy_button)); i++) {
1079
1080 yopy_button *ib = yopy_buttons + i;
1081
1082 ODeviceButton b;
1083
1084 b. setKeycode ( ib-> code );
1085 b. setUserText ( QObject::tr ( "Button", ib-> utext ));
1086 b. setPixmap ( Resource::loadPixmap ( ib-> pix ));
1087 b. setFactoryPresetPressedAction
1088 (OQCopMessage(makeChannel(ib->fpressedservice), ib->fpressedaction));
1089 b. setFactoryPresetHeldAction
1090 (OQCopMessage(makeChannel(ib->fheldservice), ib->fheldaction));
1091
1092 d-> m_buttons-> append ( b );
1093 }
1094 reloadButtonMapping ( );
1095
1096 QCopChannel *sysch = new QCopChannel("QPE/System", this);
1097 connect(sysch, SIGNAL(received(const QCString&,const QByteArray&)),
1098 this, SLOT(systemMessage(const QCString&,const QByteArray&)));
1099}
1100
1101bool Yopy::suspend()
1102{
1103 /* Opie for Yopy does not implement its own power management at the
1104 moment. The public version runs parallel to X, and relies on the
1105 existing power management features. */
1106 return false;
1107}
1108
1109bool Yopy::setDisplayBrightness(int /*bright*/)
1110{
1111 /* The code here works, but is disabled as the current version runs
1112 parallel to X, and relies on the existing backlight demon. */
1113#if 0
1114 if ( QFile::exists("/proc/sys/pm/light") ) {
1115 int fd = ::open("/proc/sys/pm/light", O_WRONLY);
1116 if (fd >= 0 ) {
1117 if (bright)
1118 ::write(fd, "1\n", 2);
1119 else
1120 ::write(fd, "0\n", 2);
1121 ::close(fd);
1122 return true;
1123 }
1124 }
1125#endif
1126 return false;
1127}
1128
1129int Yopy::displayBrightnessResolution() const
1130{
1131 return 2;
1132}
1133
1134/**************************************************
1135 *
1136 * iPAQ
1137 *
1138 **************************************************/
1139
1140void iPAQ::init ( )
1141{
1142 d-> m_vendorstr = "HP";
1143 d-> m_vendor = Vendor_HP;
1144
1145 QFile f ( "/proc/hal/model" );
1146
1147 if ( f. open ( IO_ReadOnly )) {
1148 QTextStream ts ( &f );
1149
1150 d-> m_modelstr = "H" + ts. readLine ( );
1151
1152 if ( d-> m_modelstr == "H3100" )
1153 d-> m_model = Model_iPAQ_H31xx;
1154 else if ( d-> m_modelstr == "H3600" )
1155 d-> m_model = Model_iPAQ_H36xx;
1156 else if ( d-> m_modelstr == "H3700" )
1157 d-> m_model = Model_iPAQ_H37xx;
1158 else if ( d-> m_modelstr == "H3800" )
1159 d-> m_model = Model_iPAQ_H38xx;
1160 else if ( d-> m_modelstr == "H3900" )
1161 d-> m_model = Model_iPAQ_H39xx;
1162 else if ( d-> m_modelstr == "H5400" )
1163 d-> m_model = Model_iPAQ_H5xxx;
1164 else
1165 d-> m_model = Model_Unknown;
1166
1167 f. close ( );
1168 }
1169
1170 switch ( d-> m_model ) {
1171 case Model_iPAQ_H31xx:
1172 case Model_iPAQ_H38xx:
1173 d-> m_rotation = Rot90;
1174 break;
1175 case Model_iPAQ_H36xx:
1176 case Model_iPAQ_H37xx:
1177 case Model_iPAQ_H39xx:
1178
1179 default:
1180 d-> m_rotation = Rot270;
1181 break;
1182 case Model_iPAQ_H5xxx:
1183 d-> m_rotation = Rot0;
1184 }
1185
1186 f. setName ( "/etc/familiar-version" );
1187 if ( f. open ( IO_ReadOnly )) {
1188 d-> m_systemstr = "Familiar";
1189 d-> m_system = System_Familiar;
1190
1191 QTextStream ts ( &f );
1192 d-> m_sysverstr = ts. readLine ( ). mid ( 10 );
1193
1194 f. close ( );
1195 } else {
1196 f. setName ( "/etc/oz_version" );
1197
1198 if ( f. open ( IO_ReadOnly )) {
1199 d-> m_systemstr = "OpenEmbedded/iPaq";
1200 d-> m_system = System_Familiar;
1201
1202 QTextStream ts ( &f );
1203 ts.setDevice ( &f );
1204 d-> m_sysverstr = ts. readLine ( );
1205 f. close ( );
1206 }
1207 }
1208
1209
1210
1211
1212
1213 m_leds [0] = m_leds [1] = Led_Off;
1214
1215 m_power_timer = 0;
1216
1217}
1218
1219void iPAQ::initButtons ( )
1220{
1221 if ( d-> m_buttons )
1222 return;
1223
1224 if ( isQWS( ) )
1225 QWSServer::setKeyboardFilter ( this );
1226
1227 d-> m_buttons = new QValueList <ODeviceButton>;
1228
1229 for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) {
1230 i_button *ib = ipaq_buttons + i;
1231 ODeviceButton b;
1232
1233 if (( ib-> model & d-> m_model ) == d-> m_model ) {
1234 b. setKeycode ( ib-> code );
1235 b. setUserText ( QObject::tr ( "Button", ib-> utext ));
1236 b. setPixmap ( Resource::loadPixmap ( ib-> pix ));
1237 b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib-> fpressedservice ), ib-> fpressedaction ));
1238 b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib-> fheldservice ), ib-> fheldaction ));
1239
1240 d-> m_buttons-> append ( b );
1241 }
1242 }
1243 reloadButtonMapping ( );
1244
1245 QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
1246 connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( systemMessage(const QCString&,const QByteArray&)));
1247}
1248
1249
1250//#include <linux/h3600_ts.h> // including kernel headers is evil ...
1251
1252typedef struct {
1253 unsigned char OffOnBlink; /* 0=off 1=on 2=Blink */
1254 unsigned char TotalTime; /* Units of 5 seconds */
1255 unsigned char OnTime; /* units of 100m/s */
1256 unsigned char OffTime; /* units of 100m/s */
1257} LED_IN;
1258
1259typedef struct {
1260 unsigned char mode;
1261 unsigned char pwr;
1262 unsigned char brightness;
1263} FLITE_IN;
1264
1265#define LED_ON OD_IOW( 'f', 5, LED_IN )
1266#define FLITE_ON OD_IOW( 'f', 7, FLITE_IN )
1267
1268
1269QValueList <OLed> iPAQ::ledList ( ) const
1270{
1271 QValueList <OLed> vl;
1272 vl << Led_Power;
1273
1274 if ( d-> m_model == Model_iPAQ_H38xx )
1275 vl << Led_BlueTooth;
1276 return vl;
1277}
1278
1279QValueList <OLedState> iPAQ::ledStateList ( OLed l ) const
1280{
1281 QValueList <OLedState> vl;
1282
1283 if ( l == Led_Power )
1284 vl << Led_Off << Led_On << Led_BlinkSlow << Led_BlinkFast;
1285 else if ( l == Led_BlueTooth && d-> m_model == Model_iPAQ_H38xx )
1286 vl << Led_Off; // << Led_On << ???
1287
1288 return vl;
1289}
1290
1291OLedState iPAQ::ledState ( OLed l ) const
1292{
1293 switch ( l ) {
1294 case Led_Power:
1295 return m_leds [0];
1296 case Led_BlueTooth:
1297 return m_leds [1];
1298 default:
1299 return Led_Off;
1300 }
1301}
1302
1303bool iPAQ::setLedState ( OLed l, OLedState st )
1304{
1305 static int fd = ::open ( "/dev/touchscreen/0", O_RDWR | O_NONBLOCK );
1306
1307 if ( l == Led_Power ) {
1308 if ( fd >= 0 ) {
1309 LED_IN leds;
1310 ::memset ( &leds, 0, sizeof( leds ));
1311 leds. TotalTime = 0;
1312 leds. OnTime = 0;
1313 leds. OffTime = 1;
1314 leds. OffOnBlink = 2;
1315
1316 switch ( st ) {
1317 case Led_Off : leds. OffOnBlink = 0; break;
1318 case Led_On : leds. OffOnBlink = 1; break;
1319 case Led_BlinkSlow: leds. OnTime = 10; leds. OffTime = 10; break;
1320 case Led_BlinkFast: leds. OnTime = 5; leds. OffTime = 5; break;
1321 }
1322
1323 if ( ::ioctl ( fd, LED_ON, &leds ) >= 0 ) {
1324 m_leds [0] = st;
1325 return true;
1326 }
1327 }
1328 }
1329 return false;
1330}
1331
1332
1333bool iPAQ::filter ( int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat )
1334{
1335 int newkeycode = keycode;
1336
1337 switch ( keycode ) {
1338 // H38xx/H39xx have no "Q" key anymore - this is now the Mail key
1339 case HardKey_Menu: {
1340 if (( d-> m_model == Model_iPAQ_H38xx ) ||
1341 ( d-> m_model == Model_iPAQ_H39xx ) ||
1342 ( d-> m_model == Model_iPAQ_H5xxx)) {
1343 newkeycode = HardKey_Mail;
1344 }
1345 break;
1346 }
1347
1348 // Rotate cursor keys 180° or 270°
1349 case Key_Left :
1350 case Key_Right:
1351 case Key_Up :
1352 case Key_Down : {
1353
1354 if (( d-> m_model == Model_iPAQ_H31xx ) ||
1355 ( d-> m_model == Model_iPAQ_H38xx )) {
1356 newkeycode = Key_Left + ( keycode - Key_Left + 2 ) % 4;
1357 }
1358 // Rotate the cursor keys by 270°
1359 // keycode - Key_Left = position of the button starting from left clockwise
1360 // add the rotation to it and modolo. No we've the original offset
1361 // add the offset to the Key_Left key
1362 if ( d-> m_model == Model_iPAQ_H5xxx )
1363 newkeycode = Key_Left + ( keycode - Key_Left + 3 ) % 4;
1364 break;
1365 }
1366
1367 // map Power Button short/long press to F34/F35
1368 case Key_SysReq: {
1369 if ( isPress ) {
1370 if ( m_power_timer )
1371 killTimer ( m_power_timer );
1372 m_power_timer = startTimer ( 500 );
1373 }
1374 else if ( m_power_timer ) {
1375 killTimer ( m_power_timer );
1376 m_power_timer = 0;
1377 QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, true, false );
1378 QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, false, false );
1379 }
1380 newkeycode = Key_unknown;
1381 break;
1382 }
1383 }
1384
1385 if ( newkeycode != keycode ) {
1386 if ( newkeycode != Key_unknown )
1387 QWSServer::sendKeyEvent ( -1, newkeycode, modifiers, isPress, autoRepeat );
1388 return true;
1389 }
1390 else
1391 return false;
1392}
1393
1394void iPAQ::timerEvent ( QTimerEvent * )
1395{
1396 killTimer ( m_power_timer );
1397 m_power_timer = 0;
1398 QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, true, false );
1399 QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, false, false );
1400}
1401
1402
1403void iPAQ::alarmSound ( )
1404{
1405#ifndef QT_NO_SOUND
1406 static Sound snd ( "alarm" );
1407 int fd;
1408 int vol;
1409 bool vol_reset = false;
1410
1411 if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) {
1412 if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) {
1413 Config cfg ( "qpe" );
1414 cfg. setGroup ( "Volume" );
1415
1416 int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 );
1417 if ( volalarm < 0 )
1418 volalarm = 0;
1419 else if ( volalarm > 100 )
1420 volalarm = 100;
1421 volalarm |= ( volalarm << 8 );
1422
1423 if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 )
1424 vol_reset = true;
1425 }
1426 }
1427
1428 snd. play ( );
1429 while ( !snd. isFinished ( ))
1430 qApp-> processEvents ( );
1431
1432 if ( fd >= 0 ) {
1433 if ( vol_reset )
1434 ::ioctl ( fd, MIXER_WRITE( 0 ), &vol );
1435 ::close ( fd );
1436 }
1437#endif
1438}
1439
1440
1441bool iPAQ::setSoftSuspend ( bool soft )
1442{
1443 bool res = false;
1444 int fd;
1445
1446 if (( fd = ::open ( "/proc/sys/ts/suspend_button_mode", O_WRONLY )) >= 0 ) {
1447 if ( ::write ( fd, soft ? "1" : "0", 1 ) == 1 )
1448 res = true;
1449 else
1450 ::perror ( "write to /proc/sys/ts/suspend_button_mode" );
1451
1452 ::close ( fd );
1453 }
1454 else
1455 ::perror ( "/proc/sys/ts/suspend_button_mode" );
1456
1457 return res;
1458}
1459
1460
1461bool iPAQ::setDisplayBrightness ( int bright )
1462{
1463 bool res = false;
1464 int fd;
1465
1466 if ( bright > 255 )
1467 bright = 255;
1468 if ( bright < 0 )
1469 bright = 0;
1470
1471 if (( fd = ::open ( "/dev/touchscreen/0", O_WRONLY )) >= 0 ) {
1472 FLITE_IN bl;
1473 bl. mode = 1;
1474 bl. pwr = bright ? 1 : 0;
1475 bl. brightness = ( bright * ( displayBrightnessResolution ( ) - 1 ) + 127 ) / 255;
1476 res = ( ::ioctl ( fd, FLITE_ON, &bl ) == 0 );
1477 ::close ( fd );
1478 }
1479 return res;
1480}
1481
1482int iPAQ::displayBrightnessResolution ( ) const
1483{
1484 switch ( model ( )) {
1485 case Model_iPAQ_H31xx:
1486 case Model_iPAQ_H36xx:
1487 case Model_iPAQ_H37xx:
1488 return 128; // really 256, but >128 could damage the LCD
1489
1490 case Model_iPAQ_H38xx:
1491 case Model_iPAQ_H39xx:
1492 return 64;
1493 case Model_iPAQ_H5xxx:
1494 return 255;
1495
1496 default:
1497 return 2;
1498 }
1499}
1500
1501
1502bool iPAQ::hasLightSensor ( ) const
1503{
1504 return true;
1505}
1506
1507int iPAQ::readLightSensor ( )
1508{
1509 int fd;
1510 int val = -1;
1511
1512 if (( fd = ::open ( "/proc/hal/light_sensor", O_RDONLY )) >= 0 ) {
1513 char buffer [8];
1514
1515 if ( ::read ( fd, buffer, 5 ) == 5 ) {
1516 char *endptr;
1517
1518 buffer [4] = 0;
1519 val = ::strtol ( buffer + 2, &endptr, 16 );
1520
1521 if ( *endptr != 0 )
1522 val = -1;
1523 }
1524 ::close ( fd );
1525 }
1526
1527 return val;
1528}
1529
1530int iPAQ::lightSensorResolution ( ) const
1531{
1532 return 256;
1533}
1534
1535/**************************************************
1536 *
1537 * Zaurus
1538 *
1539 **************************************************/
1540
1541// Check whether this device is the sharp zaurus..
1542// FIXME This gets unnecessary complicated. We should think about splitting the Zaurus
1543// class up into individual classes. We need three classes
1544//
1545// Zaurus-Collie (SA-model w/ 320x240 lcd, for SL5500 and SL5000)
1546// Zaurus-Poodle (PXA-model w/ 320x240 lcd, for SL5600)
1547// Zaurus-Corgi (PXA-model w/ 640x480 lcd, for C700, C750, C760, and C860)
1548//
1549// Only question right now is: Do we really need to do it? Because as soon
1550// as the OpenZaurus kernel is ready, there will be a unified interface for all
1551// Zaurus models (concerning apm, backlight, buttons, etc.)
1552//
1553// Comments? - mickeyl.
1554
1555bool Zaurus::isZaurus()
1556{
1557
1558 // If the special devices by embedix exist, it is quite simple: it is a Zaurus !
1559 if ( QFile::exists ( "/dev/sharp_buz" ) || QFile::exists ( "/dev/sharp_led" ) ){
1560 return true;
1561 }
1562
1563 // On non-embedix kernels, we have to look closer.
1564 bool is_zaurus = false;
1565 QFile f ( "/proc/cpuinfo" );
1566 if ( f. open ( IO_ReadOnly ) ) {
1567 QString model;
1568 QFile f ( "/proc/cpuinfo" );
1569
1570 QTextStream ts ( &f );
1571 QString line;
1572 while( line = ts. readLine ( ) ) {
1573 if ( line. left ( 8 ) == "Hardware" )
1574 break;
1575 }
1576 int loc = line. find ( ":" );
1577 if ( loc != -1 )
1578 model = line. mid ( loc + 2 ). simplifyWhiteSpace( );
1579
1580 if ( model == "Sharp-Collie"
1581 || model == "Collie"
1582 || model == "SHARP Corgi"
1583 || model == "SHARP Shepherd"
1584 || model == "SHARP Poodle"
1585 || model == "SHARP Husky"
1586 )
1587 is_zaurus = true;
1588
1589 }
1590 return is_zaurus;
1591}
1592
1593
1594void Zaurus::init ( )
1595{
1596 d-> m_vendorstr = "Sharp";
1597 d-> m_vendor = Vendor_Sharp;
1598 m_embedix = true; // Not openzaurus means: It has an embedix kernel !
1599
1600 // QFile f ( "/proc/filesystems" );
1601 QString model;
1602
1603 // It isn't a good idea to check the system configuration to
1604 // detect the distribution !
1605 // Otherwise it may happen that any other distribution is detected as openzaurus, just
1606 // because it uses a jffs2 filesystem..
1607 // (eilers)
1608 // if ( f. open ( IO_ReadOnly ) && ( QTextStream ( &f ). read ( ). find ( "\tjffs2\n" ) >= 0 )) {
1609 QFile f ("/etc/oz_version");
1610 if ( f.exists() ){
1611 d-> m_vendorstr = "OpenZaurus Team";
1612 d-> m_systemstr = "OpenZaurus";
1613 d-> m_system = System_OpenZaurus;
1614
1615 if ( f. open ( IO_ReadOnly )) {
1616 QTextStream ts ( &f );
1617 d-> m_sysverstr = ts. readLine ( );//. mid ( 10 );
1618 f. close ( );
1619 }
1620
1621 // Openzaurus sometimes uses the embedix kernel!
1622 // => Check whether this is an embedix kernel
1623 FILE *uname = popen("uname -r", "r");
1624 QString line;
1625 if ( f.open(IO_ReadOnly, uname) ) {
1626 QTextStream ts ( &f );
1627 line = ts. readLine ( );
1628 int loc = line. find ( "embedix" );
1629 if ( loc != -1 )
1630 m_embedix = true;
1631 else
1632 m_embedix = false;
1633 f. close ( );
1634 }
1635 pclose(uname);
1636 }
1637 else {
1638 d-> m_systemstr = "Zaurus";
1639 d-> m_system = System_Zaurus;
1640 }
1641
1642 f. setName ( "/proc/cpuinfo" );
1643 if ( f. open ( IO_ReadOnly ) ) {
1644 QTextStream ts ( &f );
1645 QString line;
1646 while( line = ts. readLine ( ) ) {
1647 if ( line. left ( 8 ) == "Hardware" )
1648 break;
1649 }
1650 int loc = line. find ( ":" );
1651 if ( loc != -1 )
1652 model = line. mid ( loc + 2 ). simplifyWhiteSpace( );
1653 }
1654
1655 if ( model == "SHARP Corgi" ) {
1656 d-> m_model = Model_Zaurus_SLC7x0;
1657 d-> m_modelstr = "Zaurus SL-C700";
1658 } else if ( model == "SHARP Shepherd" ) {
1659 d-> m_model = Model_Zaurus_SLC7x0;
1660 d-> m_modelstr = "Zaurus SL-C750";
1661 } else if ( model == "SHARP Husky" ) {
1662 d-> m_model = Model_Zaurus_SLC7x0;
1663 d-> m_modelstr = "Zaurus SL-C760";
1664 } else if ( model == "SHARP Poodle" ) {
1665 d-> m_model = Model_Zaurus_SLB600;
1666 d-> m_modelstr = "Zaurus SL-B500 or SL-5600";
1667 } else if ( model == "Sharp-Collie" || model == "Collie" ) {
1668 d-> m_model = Model_Zaurus_SL5500;
1669 d-> m_modelstr = "Zaurus SL-5500 or SL-5000d";
1670 } else {
1671 d-> m_model = Model_Zaurus_SL5500;
1672 d-> m_modelstr = "Zaurus (Model unknown)";
1673 }
1674
1675 switch ( d-> m_model ) {
1676 case Model_Zaurus_SLA300:
1677 d-> m_rotation = Rot0;
1678 break;
1679 case Model_Zaurus_SLC7x0:
1680 d-> m_rotation = rotation();
1681 d-> m_direction = direction();
1682 break;
1683 case Model_Zaurus_SLB600:
1684 case Model_Zaurus_SL5500:
1685 case Model_Zaurus_SL5000:
1686 default:
1687 d-> m_rotation = Rot270;
1688 break;
1689 }
1690 m_leds [0] = Led_Off;
1691}
1692
1693void Zaurus::initButtons ( )
1694{
1695 if ( d-> m_buttons )
1696 return;
1697
1698 d-> m_buttons = new QValueList <ODeviceButton>;
1699
1700 struct z_button * pz_buttons;
1701 int buttoncount;
1702 switch ( d-> m_model ) {
1703 case Model_Zaurus_SLC7x0:
1704 pz_buttons = z_buttons_c700;
1705 buttoncount = ARRAY_SIZE(z_buttons_c700);
1706 break;
1707 default:
1708 pz_buttons = z_buttons;
1709 buttoncount = ARRAY_SIZE(z_buttons);
1710 break;
1711 }
1712
1713 for ( int i = 0; i < buttoncount; i++ ) {
1714 struct z_button *zb = pz_buttons + i;
1715 ODeviceButton b;
1716
1717 b. setKeycode ( zb-> code );
1718 b. setUserText ( QObject::tr ( "Button", zb-> utext ));
1719 b. setPixmap ( Resource::loadPixmap ( zb-> pix ));
1720 b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( zb-> fpressedservice ),
1721 zb-> fpressedaction ));
1722 b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( zb-> fheldservice ),
1723 zb-> fheldaction ));
1724
1725 d-> m_buttons-> append ( b );
1726 }
1727
1728 reloadButtonMapping ( );
1729
1730 QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
1731 connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)),
1732 this, SLOT( systemMessage(const QCString&,const QByteArray&)));
1733}
1734
1735#include <unistd.h>
1736#include <fcntl.h>
1737#include <sys/ioctl.h>
1738
1739//#include <asm/sharp_char.h> // including kernel headers is evil ...
1740
1741#define SHARP_DEV_IOCTL_COMMAND_START 0x5680
1742
1743 #defineSHARP_BUZZER_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START)
1744#define SHARP_BUZZER_MAKESOUND (SHARP_BUZZER_IOCTL_START)
1745
1746#define SHARP_BUZ_TOUCHSOUND 1 /* touch panel sound */
1747#define SHARP_BUZ_KEYSOUND 2 /* key sound */
1748#define SHARP_BUZ_SCHEDULE_ALARM 11 /* schedule alarm */
1749
1750/* --- for SHARP_BUZZER device --- */
1751
1752 //#defineSHARP_BUZZER_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START)
1753//#define SHARP_BUZZER_MAKESOUND (SHARP_BUZZER_IOCTL_START)
1754
1755#define SHARP_BUZZER_SETVOLUME (SHARP_BUZZER_IOCTL_START+1)
1756#define SHARP_BUZZER_GETVOLUME (SHARP_BUZZER_IOCTL_START+2)
1757#define SHARP_BUZZER_ISSUPPORTED (SHARP_BUZZER_IOCTL_START+3)
1758#define SHARP_BUZZER_SETMUTE (SHARP_BUZZER_IOCTL_START+4)
1759#define SHARP_BUZZER_STOPSOUND (SHARP_BUZZER_IOCTL_START+5)
1760
1761//#define SHARP_BUZ_TOUCHSOUND 1 /* touch panel sound */
1762//#define SHARP_BUZ_KEYSOUND 2 /* key sound */
1763
1764//#define SHARP_PDA_ILLCLICKSOUND 3 /* illegal click */
1765//#define SHARP_PDA_WARNSOUND 4 /* warning occurred */
1766//#define SHARP_PDA_ERRORSOUND 5 /* error occurred */
1767//#define SHARP_PDA_CRITICALSOUND 6 /* critical error occurred */
1768//#define SHARP_PDA_SYSSTARTSOUND 7 /* system start */
1769//#define SHARP_PDA_SYSTEMENDSOUND 8 /* system shutdown */
1770//#define SHARP_PDA_APPSTART 9 /* application start */
1771//#define SHARP_PDA_APPQUIT 10 /* application ends */
1772
1773//#define SHARP_BUZ_SCHEDULE_ALARM 11 /* schedule alarm */
1774//#define SHARP_BUZ_DAILY_ALARM 12 /* daily alarm */
1775//#define SHARP_BUZ_GOT_PHONE_CALL 13 /* phone call sound */
1776//#define SHARP_BUZ_GOT_MAIL 14 /* mail sound */
1777//
1778
1779 #defineSHARP_LED_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START)
1780#define SHARP_LED_SETSTATUS (SHARP_LED_IOCTL_START+1)
1781
1782#define SHARP_IOCTL_GET_ROTATION 0x413c
1783
1784typedef struct sharp_led_status {
1785 int which; /* select which LED status is wanted. */
1786 int status; /* set new led status if you call SHARP_LED_SETSTATUS */
1787} sharp_led_status;
1788
1789#define SHARP_LED_MAIL_EXISTS 9 /* mail status (exists or not) */
1790
1791#define LED_MAIL_NO_UNREAD_MAIL 0 /* for SHARP_LED_MAIL_EXISTS */
1792#define LED_MAIL_NEWMAIL_EXISTS 1 /* for SHARP_LED_MAIL_EXISTS */
1793#define LED_MAIL_UNREAD_MAIL_EX 2 /* for SHARP_LED_MAIL_EXISTS */
1794
1795// #include <asm/sharp_apm.h> // including kernel headers is evil ...
1796
1797#define APM_IOCGEVTSRC OD_IOR( 'A', 203, int )
1798#define APM_IOCSEVTSRC OD_IORW( 'A', 204, int )
1799#define APM_EVT_POWER_BUTTON (1 << 0)
1800
1801#define FL_IOCTL_STEP_CONTRAST 100
1802
1803
1804void Zaurus::buzzer ( int sound )
1805{
1806#ifndef QT_NO_SOUND
1807 QString soundname;
1808
1809 // Not all devices have real sound
1810 if ( d->m_model == Model_Zaurus_SLC7x0
1811 || d->m_model == Model_Zaurus_SLB600 ){
1812
1813 switch ( sound ){
1814 case SHARP_BUZ_SCHEDULE_ALARM:
1815 soundname = "alarm";
1816 break;
1817 case SHARP_BUZ_TOUCHSOUND:
1818 soundname = "touchsound";
1819 break;
1820 case SHARP_BUZ_KEYSOUND:
1821 soundname = "keysound";
1822 break;
1823 default:
1824 soundname = "alarm";
1825
1826 }
1827 }
1828
1829 // If a soundname is defined, we expect that this device has
1830 // sound capabilities.. Otherwise we expect to have the buzzer
1831 // device..
1832 if ( !soundname.isEmpty() ){
1833 int fd;
1834 int vol;
1835 bool vol_reset = false;
1836
1837 Sound snd ( soundname );
1838
1839 if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) {
1840 if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) {
1841 Config cfg ( "qpe" );
1842 cfg. setGroup ( "Volume" );
1843
1844 int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 );
1845 if ( volalarm < 0 )
1846 volalarm = 0;
1847 else if ( volalarm > 100 )
1848 volalarm = 100;
1849 volalarm |= ( volalarm << 8 );
1850
1851 if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 )
1852 vol_reset = true;
1853 }
1854 }
1855
1856 snd. play ( );
1857 while ( !snd. isFinished ( ))
1858 qApp-> processEvents ( );
1859
1860 if ( fd >= 0 ) {
1861 if ( vol_reset )
1862 ::ioctl ( fd, MIXER_WRITE( 0 ), &vol );
1863 ::close ( fd );
1864 }
1865 } else {
1866 int fd = ::open ( "/dev/sharp_buz", O_WRONLY|O_NONBLOCK );
1867
1868 if ( fd >= 0 ) {
1869 ::ioctl ( fd, SHARP_BUZZER_MAKESOUND, sound );
1870 ::close ( fd );
1871 }
1872
1873 }
1874#endif
1875}
1876
1877
1878void Zaurus::alarmSound ( )
1879{
1880 buzzer ( SHARP_BUZ_SCHEDULE_ALARM );
1881}
1882
1883void Zaurus::touchSound ( )
1884{
1885 buzzer ( SHARP_BUZ_TOUCHSOUND );
1886}
1887
1888void Zaurus::keySound ( )
1889{
1890 buzzer ( SHARP_BUZ_KEYSOUND );
1891}
1892
1893
1894QValueList <OLed> Zaurus::ledList ( ) const
1895{
1896 QValueList <OLed> vl;
1897 vl << Led_Mail;
1898 return vl;
1899}
1900
1901QValueList <OLedState> Zaurus::ledStateList ( OLed l ) const
1902{
1903 QValueList <OLedState> vl;
1904
1905 if ( l == Led_Mail )
1906 vl << Led_Off << Led_On << Led_BlinkSlow;
1907 return vl;
1908}
1909
1910OLedState Zaurus::ledState ( OLed which ) const
1911{
1912 if ( which == Led_Mail )
1913 return m_leds [0];
1914 else
1915 return Led_Off;
1916}
1917
1918bool Zaurus::setLedState ( OLed which, OLedState st )
1919{
1920 if (!m_embedix) // Currently not supported on non_embedix kernels
1921 return false;
1922
1923 static int fd = ::open ( "/dev/sharp_led", O_RDWR|O_NONBLOCK );
1924
1925 if ( which == Led_Mail ) {
1926 if ( fd >= 0 ) {
1927 struct sharp_led_status leds;
1928 ::memset ( &leds, 0, sizeof( leds ));
1929 leds. which = SHARP_LED_MAIL_EXISTS;
1930 bool ok = true;
1931
1932 switch ( st ) {
1933 case Led_Off : leds. status = LED_MAIL_NO_UNREAD_MAIL; break;
1934 case Led_On : leds. status = LED_MAIL_NEWMAIL_EXISTS; break;
1935 case Led_BlinkSlow: leds. status = LED_MAIL_UNREAD_MAIL_EX; break;
1936 default : ok = false;
1937 }
1938
1939 if ( ok && ( ::ioctl ( fd, SHARP_LED_SETSTATUS, &leds ) >= 0 )) {
1940 m_leds [0] = st;
1941 return true;
1942 }
1943 }
1944 }
1945 return false;
1946}
1947
1948bool Zaurus::setSoftSuspend ( bool soft )
1949{
1950 if (!m_embedix) {
1951 /* non-Embedix kernels dont have kernel autosuspend */
1952 return ODevice::setSoftSuspend( soft );
1953 }
1954
1955 bool res = false;
1956 int fd;
1957
1958 if ((( fd = ::open ( "/dev/apm_bios", O_RDWR )) >= 0 ) ||
1959 (( fd = ::open ( "/dev/misc/apm_bios",O_RDWR )) >= 0 )) {
1960
1961 int sources = ::ioctl ( fd, APM_IOCGEVTSRC, 0 ); // get current event sources
1962
1963 if ( sources >= 0 ) {
1964 if ( soft )
1965 sources &= ~APM_EVT_POWER_BUTTON;
1966 else
1967 sources |= APM_EVT_POWER_BUTTON;
1968
1969 if ( ::ioctl ( fd, APM_IOCSEVTSRC, sources ) >= 0 ) // set new event sources
1970 res = true;
1971 else
1972 perror ( "APM_IOCGEVTSRC" );
1973 }
1974 else
1975 perror ( "APM_IOCGEVTSRC" );
1976
1977 ::close ( fd );
1978 }
1979 else
1980 perror ( "/dev/apm_bios or /dev/misc/apm_bios" );
1981
1982 return res;
1983}
1984
1985
1986bool Zaurus::setDisplayBrightness ( int bright )
1987{
1988 //qDebug( "Zaurus::setDisplayBrightness( %d )", bright );
1989 bool res = false;
1990 int fd;
1991
1992 if ( bright > 255 ) bright = 255;
1993 if ( bright < 0 ) bright = 0;
1994
1995 if ( m_embedix )
1996 {
1997 if ( d->m_model == Model_Zaurus_SLC7x0 )
1998 {
1999 //qDebug( "using special treatment for devices with the corgi backlight interface" );
2000 // special treatment for devices with the corgi backlight interface
2001 if (( fd = ::open ( "/proc/driver/fl/corgi-bl", O_WRONLY )) >= 0 )
2002 {
2003 int value = ( bright == 1 ) ? 1 : bright * ( 17.0 / 255.0 );
2004 char writeCommand[100];
2005 const int count = sprintf( writeCommand, "0x%x\n", value );
2006 res = ( ::write ( fd, writeCommand, count ) != -1 );
2007 ::close ( fd );
2008 }
2009 return res;
2010 }
2011 else
2012 {
2013 // standard treatment for devices with the dumb embedix frontlight interface
2014 if (( fd = ::open ( "/dev/fl", O_WRONLY )) >= 0 ) {
2015 int bl = ( bright * 4 + 127 ) / 255; // only 4 steps on zaurus
2016 if ( bright && !bl )
2017 bl = 1;
2018 res = ( ::ioctl ( fd, FL_IOCTL_STEP_CONTRAST, bl ) == 0 );
2019 ::close ( fd );
2020 }
2021 }
2022 }
2023 else
2024 {
2025 // special treatment for the OpenZaurus unified interface
2026 #define FB_BACKLIGHT_SET_BRIGHTNESS _IOW('F', 1, u_int) /* set brightness */
2027 if (( fd = ::open ( "/dev/fb0", O_WRONLY )) >= 0 ) {
2028 res = ( ::ioctl ( fd , FB_BACKLIGHT_SET_BRIGHTNESS, bright ) == 0 );
2029 ::close ( fd );
2030 }
2031 }
2032 return res;
2033}
2034
2035bool Zaurus::suspend ( )
2036{
2037 qDebug("ODevice::suspend");
2038 if ( !isQWS( ) ) // only qwsserver is allowed to suspend
2039 return false;
2040
2041 if ( d-> m_model == Model_Unknown ) // better don't suspend in qvfb / on unkown devices
2042 return false;
2043
2044 bool res = false;
2045
2046 struct timeval tvs, tvn;
2047 ::gettimeofday ( &tvs, 0 );
2048
2049 ::sync ( ); // flush fs caches
2050 res = ( ::system ( "apm --suspend" ) == 0 );
2051
2052 // This is needed because the iPAQ apm implementation is asynchronous and we
2053 // can not be sure when exactly the device is really suspended
2054 // This can be deleted as soon as a stable familiar with a synchronous apm implementation exists.
2055
2056 if ( res ) {
2057 do { // Yes, wait 15 seconds. This APM bug sucks big time.
2058 ::usleep ( 200 * 1000 );
2059 ::gettimeofday ( &tvn, 0 );
2060 } while ((( tvn. tv_sec - tvs. tv_sec ) * 1000 + ( tvn. tv_usec - tvs. tv_usec ) / 1000 ) < 15000 );
2061 }
2062
2063 QCopEnvelope ( "QPE/Rotation", "rotateDefault()" );
2064 return res;
2065}
2066
2067
2068Transformation Zaurus::rotation ( ) const
2069{
2070 Transformation rot;
2071 int handle = 0;
2072 int retval = 0;
2073
2074 switch ( d-> m_model ) {
2075 case Model_Zaurus_SLC7x0:
2076 handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK);
2077 if (handle == -1) {
2078 return Rot270;
2079 } else {
2080 retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION);
2081 ::close (handle);
2082
2083 if (retval == 2 )
2084 rot = Rot0;
2085 else
2086 rot = Rot270;
2087 }
2088 break;
2089 case Model_Zaurus_SLA300:
2090 case Model_Zaurus_SLB600:
2091 case Model_Zaurus_SL5500:
2092 case Model_Zaurus_SL5000:
2093 default:
2094 rot = d-> m_rotation;
2095 break;
2096 }
2097
2098 return rot;
2099}
2100ODirection Zaurus::direction ( ) const
2101{
2102 ODirection dir;
2103 int handle = 0;
2104 int retval = 0;
2105 switch ( d-> m_model ) {
2106 case Model_Zaurus_SLC7x0:
2107 handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK);
2108 if (handle == -1) {
2109 dir = CW;
2110 } else {
2111 retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION);
2112 ::close (handle);
2113 if (retval == 2 )
2114 dir = CCW;
2115 else
2116 dir = CW;
2117 }
2118 break;
2119 case Model_Zaurus_SLA300:
2120 case Model_Zaurus_SLB600:
2121 case Model_Zaurus_SL5500:
2122 case Model_Zaurus_SL5000:
2123 default:
2124 dir = d-> m_direction;
2125 break;
2126 }
2127 return dir;
2128
2129}
2130
2131int Zaurus::displayBrightnessResolution ( ) const
2132{
2133 if (m_embedix)
2134 return d->m_model == Model_Zaurus_SLC7x0 ? 18 : 5;
2135 else
2136 return 256;
2137}
2138
2139bool Zaurus::hasHingeSensor() const
2140{
2141 return d->m_model == Model_Zaurus_SLC7x0;
2142}
2143
2144OHingeStatus Zaurus::readHingeSensor()
2145{
2146 int handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK);
2147 if (handle == -1)
2148 {
2149 qWarning("Zaurus::readHingeSensor() - failed (%s)", "unknown reason" ); //FIXME: use strerror
2150 return CASE_UNKNOWN;
2151 }
2152 else
2153 {
2154 int retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION);
2155 ::close (handle);
2156 if ( retval == CASE_CLOSED || retval == CASE_PORTRAIT || retval == CASE_LANDSCAPE )
2157 {
2158 qDebug( "Zaurus::readHingeSensor() - result = %d", retval );
2159 return static_cast<OHingeStatus>( retval );
2160 }
2161 else
2162 {
2163 qWarning("Zaurus::readHingeSensor() - couldn't compute hinge status!" );
2164 return CASE_UNKNOWN;
2165 }
2166 }
2167}
2168
2169
2170void Zaurus::virtual_hook( int id, void *data ) {
2171 switch( id ) {
2172 case VIRTUAL_ROTATION:{
2173 VirtRotation* rot = reinterpret_cast<VirtRotation*>( data );
2174 rot->trans = rotation();
2175 break;
2176 }
2177 case VIRTUAL_DIRECTION:{
2178 VirtDirection *dir = reinterpret_cast<VirtDirection*>( data );
2179 dir->direct = direction();
2180 break;
2181 }
2182 case VIRTUAL_HAS_HINGE:{
2183 VirtHasHinge *hin = reinterpret_cast<VirtHasHinge*>( data );
2184 hin->hasHinge = hasHingeSensor();
2185 break;
2186 }
2187 case VIRTUAL_HINGE:{
2188 VirtHingeStatus *hin = reinterpret_cast<VirtHingeStatus*>( data );
2189 hin->hingeStat = readHingeSensor();
2190 break;
2191 }
2192 default:
2193 ODevice::virtual_hook( id, data );
2194 break;
2195 }
2196}
2197
2198/**************************************************
2199 *
2200 * SIMpad
2201 *
2202 **************************************************/
2203
2204void SIMpad::init ( )
2205{
2206 d-> m_vendorstr = "SIEMENS";
2207 d-> m_vendor = Vendor_SIEMENS;
2208
2209 QFile f ( "/proc/hal/model" );
2210
2211 //TODO Implement model checking
2212 //FIXME For now we assume an SL4
2213
2214 d-> m_modelstr = "SL4";
2215 d-> m_model = Model_SIMpad_SL4;
2216
2217 switch ( d-> m_model ) {
2218 default:
2219 d-> m_rotation = Rot0;
2220 d-> m_direction = CCW;
2221 d-> m_holdtime = 1000; // 1000ms
2222
2223 break;
2224 }
2225
2226 f. setName ( "/etc/familiar-version" );
2227 if ( f. open ( IO_ReadOnly )) {
2228 d-> m_systemstr = "Familiar";
2229 d-> m_system = System_Familiar;
2230
2231 QTextStream ts ( &f );
2232 d-> m_sysverstr = ts. readLine ( ). mid ( 10 );
2233
2234 f. close ( );
2235 } else {
2236 f. setName ( "/etc/oz_version" );
2237
2238 if ( f. open ( IO_ReadOnly )) {
2239 d-> m_systemstr = "OpenEmbedded/SIMpad";
2240 d-> m_system = System_OpenZaurus;
2241
2242 QTextStream ts ( &f );
2243 ts.setDevice ( &f );
2244 d-> m_sysverstr = ts. readLine ( );
2245 f. close ( );
2246 }
2247 }
2248
2249 m_leds [0] = m_leds [1] = Led_Off;
2250
2251 m_power_timer = 0;
2252
2253}
2254
2255void SIMpad::initButtons ( )
2256{
2257 if ( d-> m_buttons )
2258 return;
2259
2260 if ( isQWS( ) )
2261 QWSServer::setKeyboardFilter ( this );
2262
2263 d-> m_buttons = new QValueList <ODeviceButton>;
2264
2265 for ( uint i = 0; i < ( sizeof( simpad_buttons ) / sizeof( s_button )); i++ ) {
2266 s_button *sb = simpad_buttons + i;
2267 ODeviceButton b;
2268
2269 if (( sb-> model & d-> m_model ) == d-> m_model ) {
2270 b. setKeycode ( sb-> code );
2271 b. setUserText ( QObject::tr ( "Button", sb-> utext ));
2272 b. setPixmap ( Resource::loadPixmap ( sb-> pix ));
2273 b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( sb-> fpressedservice ), sb-> fpressedaction ));
2274 b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( sb-> fheldservice ), sb-> fheldaction ));
2275
2276 d-> m_buttons-> append ( b );
2277 }
2278 }
2279 reloadButtonMapping ( );
2280
2281 QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
2282 connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( systemMessage(const QCString&,const QByteArray&)));
2283}
2284
2285// SIMpad boardcontrol register CS3
2286#define SIMPAD_BOARDCONTROL "/proc/cs3"
2287#define SIMPAD_VCC_5V_EN 0x0001 // For 5V PCMCIA
2288#define SIMPAD_VCC_3V_EN 0x0002 // FOR 3.3V PCMCIA
2289#define SIMPAD_EN1 0x0004 // This is only for EPROM's
2290#define SIMPAD_EN0 0x0008 // Both should be enable for 3.3V or 5V
2291#define SIMPAD_DISPLAY_ON 0x0010
2292#define SIMPAD_PCMCIA_BUFF_DIS 0x0020
2293#define SIMPAD_MQ_RESET 0x0040
2294#define SIMPAD_PCMCIA_RESET 0x0080
2295#define SIMPAD_DECT_POWER_ON 0x0100
2296#define SIMPAD_IRDA_SD 0x0200 // Shutdown for powersave
2297#define SIMPAD_RS232_ON 0x0400
2298#define SIMPAD_SD_MEDIAQ 0x0800 // Shutdown for powersave
2299#define SIMPAD_LED2_ON 0x1000
2300#define SIMPAD_IRDA_MODE 0x2000 // Fast/Slow IrDA mode
2301#define SIMPAD_ENABLE_5V 0x4000 // Enable 5V circuit
2302#define SIMPAD_RESET_SIMCARD 0x8000
2303
2304//SIMpad touchscreen backlight strength control
2305#define SIMPAD_BACKLIGHT_CONTROL "/proc/driver/mq200/registers/PWM_CONTROL"
2306#define SIMPAD_BACKLIGHT_MASK 0x00a10044
2307
2308QValueList <OLed> SIMpad::ledList ( ) const
2309{
2310 QValueList <OLed> vl;
2311 vl << Led_Power; //FIXME which LED is LED2 ? The green one or the amber one?
2312 //vl << Led_Mail; //TODO find out if LED1 is accessible anyway
2313 return vl;
2314}
2315
2316QValueList <OLedState> SIMpad::ledStateList ( OLed l ) const
2317{
2318 QValueList <OLedState> vl;
2319
2320 if ( l == Led_Power ) //FIXME which LED is LED2 ? The green one or the amber one?
2321 vl << Led_Off << Led_On;
2322 //else if ( l == Led_Mail ) //TODO find out if LED1 is accessible anyway
2323 //vl << Led_Off;
2324 return vl;
2325}
2326
2327OLedState SIMpad::ledState ( OLed l ) const
2328{
2329 switch ( l ) {
2330 case Led_Power:
2331 return m_leds [0];
2332 //case Led_Mail:
2333 //return m_leds [1];
2334 default:
2335 return Led_Off;
2336 }
2337}
2338
2339bool SIMpad::setLedState ( OLed l, OLedState st )
2340{
2341 static int fd = ::open ( SIMPAD_BOARDCONTROL, O_RDWR | O_NONBLOCK );
2342
2343 if ( l == Led_Power ) {
2344 if ( fd >= 0 ) {
2345 LED_IN leds;
2346 ::memset ( &leds, 0, sizeof( leds ));
2347 leds. TotalTime = 0;
2348 leds. OnTime = 0;
2349 leds. OffTime = 1;
2350 leds. OffOnBlink = 2;
2351
2352 switch ( st ) {
2353 case Led_Off : leds. OffOnBlink = 0; break;
2354 case Led_On : leds. OffOnBlink = 1; break;
2355 case Led_BlinkSlow: leds. OnTime = 10; leds. OffTime = 10; break;
2356 case Led_BlinkFast: leds. OnTime = 5; leds. OffTime = 5; break;
2357 }
2358
2359 {
2360 /*TODO Implement this like that:
2361 read from cs3
2362 && with SIMPAD_LED2_ON
2363 write to cs3 */
2364 m_leds [0] = st;
2365 return true;
2366 }
2367 }
2368 }
2369 return false;
2370}
2371
2372
2373bool SIMpad::filter ( int /*unicode*/, int /*keycode*/, int /*modifiers*/, bool /*isPress*/, bool /*autoRepeat*/ )
2374{
2375 //TODO
2376 return false;
2377}
2378
2379void SIMpad::timerEvent ( QTimerEvent * )
2380{
2381 killTimer ( m_power_timer );
2382 m_power_timer = 0;
2383 QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, true, false );
2384 QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, false, false );
2385}
2386
2387
2388void SIMpad::alarmSound ( )
2389{
2390#ifndef QT_NO_SOUND
2391 static Sound snd ( "alarm" );
2392 int fd;
2393 int vol;
2394 bool vol_reset = false;
2395
2396 if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) {
2397 if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) {
2398 Config cfg ( "qpe" );
2399 cfg. setGroup ( "Volume" );
2400
2401 int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 );
2402 if ( volalarm < 0 )
2403 volalarm = 0;
2404 else if ( volalarm > 100 )
2405 volalarm = 100;
2406 volalarm |= ( volalarm << 8 );
2407
2408 if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 )
2409 vol_reset = true;
2410 }
2411 }
2412
2413 snd. play ( );
2414 while ( !snd. isFinished ( ))
2415 qApp-> processEvents ( );
2416
2417 if ( fd >= 0 ) {
2418 if ( vol_reset )
2419 ::ioctl ( fd, MIXER_WRITE( 0 ), &vol );
2420 ::close ( fd );
2421 }
2422#endif
2423}
2424
2425
2426bool SIMpad::suspend ( ) // Must override because SIMpad does NOT have apm
2427{
2428 qDebug( "ODevice for SIMpad: suspend()" );
2429 if ( !isQWS( ) ) // only qwsserver is allowed to suspend
2430 return false;
2431
2432 bool res = false;
2433
2434 struct timeval tvs;
2435 ::gettimeofday ( &tvs, 0 );
2436
2437 ::sync ( ); // flush fs caches
2438 res = ( ::system ( "cat /dev/fb/0 >/tmp/.buffer; echo > /proc/sys/pm/suspend; cat /tmp/.buffer >/dev/fb/0" ) == 0 ); //TODO make better :)
2439
2440 return res;
2441}
2442
2443
2444bool SIMpad::setSoftSuspend ( bool soft )
2445{
2446 qDebug( "ODevice for SIMpad: UNHANDLED setSoftSuspend(%s)", soft? "on" : "off" );
2447 return false;
2448}
2449
2450
2451bool SIMpad::setDisplayStatus ( bool on )
2452{
2453 qDebug( "ODevice for SIMpad: setDisplayStatus(%s)", on? "on" : "off" );
2454
2455 bool res = false;
2456
2457 QString cmdline = QString().sprintf( "echo %s > /proc/cs3", on ? "0xd41a" : "0xd40a" ); //TODO make better :)
2458
2459 res = ( ::system( (const char*) cmdline ) == 0 );
2460
2461 return res;
2462}
2463
2464
2465bool SIMpad::setDisplayBrightness ( int bright )
2466{
2467 qDebug( "ODevice for SIMpad: setDisplayBrightness( %d )", bright );
2468 bool res = false;
2469 int fd;
2470
2471 if ( bright > 255 )
2472 bright = 255;
2473 if ( bright < 1 )
2474 bright = 0;
2475
2476 if (( fd = ::open ( SIMPAD_BACKLIGHT_CONTROL, O_WRONLY )) >= 0 ) {
2477 int value = 255 - bright;
2478 const int mask = SIMPAD_BACKLIGHT_MASK;
2479 value = value << 8;
2480 value += mask;
2481 char writeCommand[100];
2482 const int count = sprintf( writeCommand, "0x%x\n", value );
2483 res = ( ::write ( fd, writeCommand, count ) != -1 );
2484 ::close ( fd );
2485 }
2486 return res;
2487}
2488
2489
2490int SIMpad::displayBrightnessResolution ( ) const
2491{
2492 return 255; // All SIMpad models share the same display
2493}
2494
2495/**************************************************
2496 *
2497 * Ramses
2498 *
2499 **************************************************/
2500
2501void Ramses::init()
2502{
2503 d->m_vendorstr = "M und N";
2504 d->m_vendor = Vendor_MundN;
2505
2506 QFile f("/proc/sys/board/ramses");
2507
2508 d->m_modelstr = "Ramses";
2509 d->m_model = Model_Ramses_MNCI;
2510
2511 d->m_rotation = Rot90;
2512 d->m_holdtime = 1000;
2513
2514 f.setName("/etc/oz_version");
2515
2516 if (f.open(IO_ReadOnly)) {
2517 d->m_systemstr = "OpenEmbedded/Ramses";
2518 d->m_system = System_OpenZaurus;
2519
2520 QTextStream ts(&f);
2521 ts.setDevice(&f);
2522 d->m_sysverstr = ts.readLine();
2523 f.close();
2524 }
2525
2526 m_power_timer = 0;
2527
2528#ifdef QT_QWS_ALLOW_OVERCLOCK
2529#warning *** Overclocking enabled - this may fry your hardware - you have been warned ***
2530#define OC(x...) x
2531#else
2532#define OC(x...)
2533#endif
2534
2535
2536 // This table is true for a Intel XScale PXA 255
2537
2538 d->m_cpu_frequencies->append("99000"); // mem= 99, run= 99, turbo= 99, PXbus= 50
2539 OC(d->m_cpu_frequencies->append("118000"); ) // mem=118, run=118, turbo=118, PXbus= 59 OC'd mem
2540 d->m_cpu_frequencies->append("199100"); // mem= 99, run=199, turbo=199, PXbus= 99
2541 OC(d->m_cpu_frequencies->append("236000"); ) // mem=118, run=236, turbo=236, PXbus=118 OC'd mem
2542 d->m_cpu_frequencies->append("298600"); // mem= 99, run=199, turbo=298, PXbus= 99
2543 OC(d->m_cpu_frequencies->append("354000"); ) // mem=118, run=236, turbo=354, PXbus=118 OC'd mem
2544 d->m_cpu_frequencies->append("398099"); // mem= 99, run=199, turbo=398, PXbus= 99
2545 d->m_cpu_frequencies->append("398100"); // mem= 99, run=398, turbo=398, PXbus=196
2546 OC(d->m_cpu_frequencies->append("471000"); ) // mem=118, run=471, turbo=471, PXbus=236 OC'd mem/core/bus
2547
2548}
2549
2550bool Ramses::filter(int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat)
2551{
2552 Q_UNUSED( keycode );
2553 Q_UNUSED( modifiers );
2554 Q_UNUSED( isPress );
2555 Q_UNUSED( autoRepeat );
2556 return false;
2557}
2558
2559void Ramses::timerEvent(QTimerEvent *)
2560{
2561 killTimer(m_power_timer);
2562 m_power_timer = 0;
2563 QWSServer::sendKeyEvent(-1, HardKey_Backlight, 0, true, false);
2564 QWSServer::sendKeyEvent(-1, HardKey_Backlight, 0, false, false);
2565}
2566
2567
2568bool Ramses::setSoftSuspend(bool soft)
2569{
2570 qDebug("Ramses::setSoftSuspend(%d)", soft);
2571#if 0
2572 bool res = false;
2573 int fd;
2574
2575 if (((fd = ::open("/dev/apm_bios", O_RDWR)) >= 0) ||
2576 ((fd = ::open("/dev/misc/apm_bios",O_RDWR)) >= 0)) {
2577
2578 int sources = ::ioctl(fd, APM_IOCGEVTSRC, 0); // get current event sources
2579
2580 if (sources >= 0) {
2581 if (soft)
2582 sources &= ~APM_EVT_POWER_BUTTON;
2583 else
2584 sources |= APM_EVT_POWER_BUTTON;
2585
2586 if (::ioctl(fd, APM_IOCSEVTSRC, sources) >= 0) // set new event sources
2587 res = true;
2588 else
2589 perror("APM_IOCGEVTSRC");
2590 }
2591 else
2592 perror("APM_IOCGEVTSRC");
2593
2594 ::close(fd);
2595 }
2596 else
2597 perror("/dev/apm_bios or /dev/misc/apm_bios");
2598
2599 return res;
2600#else
2601 return true;
2602#endif
2603}
2604
2605bool Ramses::suspend ( )
2606{
2607 qDebug("Ramses::suspend");
2608 return false;
2609}
2610
2611/**
2612 * This sets the display on or off
2613 */
2614bool Ramses::setDisplayStatus(bool on)
2615{
2616 qDebug("Ramses::setDisplayStatus(%d)", on);
2617#if 0
2618 bool res = false;
2619 int fd;
2620
2621 if ((fd = ::open ("/dev/fb/0", O_RDWR)) >= 0) {
2622 res = (::ioctl(fd, FBIOBLANK, on ? VESA_NO_BLANKING : VESA_POWERDOWN) == 0);
2623 ::close(fd);
2624 }
2625 return res;
2626#else
2627 return true;
2628#endif
2629}
2630
2631
2632/*
2633 * We get something between 0..255 into us
2634*/
2635bool Ramses::setDisplayBrightness(int bright)
2636{
2637 qDebug("Ramses::setDisplayBrightness(%d)", bright);
2638 bool res = false;
2639 int fd;
2640
2641 // pwm1 brighness: 20 steps 500..0 (dunkel->hell)
2642
2643 if (bright > 255 )
2644 bright = 255;
2645 if (bright < 0)
2646 bright = 0;
2647
2648 // Turn backlight completely off
2649 if ((fd = ::open("/proc/sys/board/lcd_backlight", O_WRONLY)) >= 0) {
2650 char writeCommand[10];
2651 const int count = sprintf(writeCommand, "%d\n", bright ? 1 : 0);
2652 res = (::write(fd, writeCommand, count) != -1);
2653 ::close(fd);
2654 }
2655
2656 // scale backlight brightness to hardware
2657 bright = 500-(bright * 500 / 255);
2658 if ((fd = ::open("/proc/sys/board/pwm1", O_WRONLY)) >= 0) {
2659 qDebug(" %d -> pwm1", bright);
2660 char writeCommand[100];
2661 const int count = sprintf(writeCommand, "%d\n", bright);
2662 res = (::write(fd, writeCommand, count) != -1);
2663 ::close(fd);
2664 }
2665 return res;
2666}
2667
2668
2669int Ramses::displayBrightnessResolution() const
2670{
2671 return 32;
2672}
2673
2674bool Ramses::setDisplayContrast(int contr)
2675{
2676 qDebug("Ramses::setDisplayContrast(%d)", contr);
2677 bool res = false;
2678 int fd;
2679
2680 // pwm0 contrast: 20 steps 79..90 (dunkel->hell)
2681
2682 if (contr > 255 )
2683 contr = 255;
2684 if (contr < 0)
2685 contr = 0;
2686 contr = 90 - (contr * 20 / 255);
2687
2688 if ((fd = ::open("/proc/sys/board/pwm0", O_WRONLY)) >= 0) {
2689 qDebug(" %d -> pwm0", contr);
2690 char writeCommand[100];
2691 const int count = sprintf(writeCommand, "%d\n", contr);
2692 res = (::write(fd, writeCommand, count) != -1);
2693 res = true;
2694 ::close(fd);
2695 }
2696 return res;
2697}
2698
2699
2700int Ramses::displayContrastResolution() const
2701{
2702 return 20;
2703}
2704
2705
2706/**************************************************
2707 * *
2708 * Jornada *
2709 * *
2710 **************************************************/
2711
2712
2713bool Jornada::isJornada ( )
2714{
2715 QFile f( "/proc/cpuinfo" );
2716 if ( f. open ( IO_ReadOnly ) ) {
2717 QTextStream ts ( &f );
2718 QString line;
2719 while( line = ts. readLine ( ) ) {
2720 if ( line. left ( 8 ) == "Hardware" ) {
2721 int loc = line. find ( ":" );
2722 if ( loc != -1 ) {
2723 QString model =
2724 line. mid ( loc + 2 ). simplifyWhiteSpace( );
2725 return ( model == "HP Jornada 56x" );
2726 }
2727 }
2728 }
2729 }
2730 return false;
2731}
2732
2733void Jornada::init ( )
2734{
2735 d-> m_vendorstr = "HP";
2736 d-> m_vendor = Vendor_HP;
2737 d-> m_modelstr = "Jornada 56x";
2738 d-> m_model = Model_Jornada_56x;
2739 d-> m_systemstr = "Familiar";
2740 d-> m_system = System_Familiar;
2741 d-> m_rotation = Rot0;
2742
2743 QFile f ( "/etc/familiar-version" );
2744 f. setName ( "/etc/familiar-version" );
2745 if ( f. open ( IO_ReadOnly )) {
2746
2747 QTextStream ts ( &f );
2748 d-> m_sysverstr = ts. readLine ( ). mid ( 10 );
2749
2750 f. close ( );
2751 }
2752}
2753
2754#if 0
2755void Jornada::initButtons ( )
2756{
2757 if ( d-> m_buttons )
2758 return;
2759
2760 // Simulation uses iPAQ 3660 device buttons
2761
2762 qDebug ( "init Buttons" );
2763 d-> m_buttons = new QValueList <ODeviceButton>;
2764
2765 for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) {
2766 i_button *ib = ipaq_buttons + i;
2767 ODeviceButton b;
2768
2769 if (( ib-> model & Model_iPAQ_H36xx ) == Model_iPAQ_H36xx ) {
2770 b. setKeycode ( ib-> code );
2771 b. setUserText ( QObject::tr ( "Button", ib-> utext ));
2772 b. setPixmap ( Resource::loadPixmap ( ib-> pix ));
2773 b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib-> fpressedservice ), ib-> fpressedaction ));
2774 b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib-> fheldservice ), ib-> fheldaction ));
2775 d-> m_buttons-> append ( b );
2776 }
2777 }
2778 reloadButtonMapping ( );
2779
2780 QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
2781 connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( systemMessage(const QCString&,const QByteArray&)));
2782}
2783#endif
2784int Jornada::displayBrightnessResolution ( ) const
2785{
2786 return 255;
2787}
2788
2789bool Jornada::setDisplayBrightness ( int bright )
2790{
2791 bool res = false;
2792 int fd;
2793
2794 if ( bright > 255 )
2795 bright = 255;
2796 if ( bright < 0 )
2797 bright = 0;
2798
2799 if (( fd = ::open ( "/dev/touchscreen/0", O_WRONLY )) >= 0 ) {
2800 FLITE_IN bl;
2801 bl. mode = 1;
2802 bl. pwr = bright ? 1 : 0;
2803 bl. brightness = ( bright * ( displayBrightnessResolution ( ) - 1 ) + 127 ) / 255;
2804 res = ( ::ioctl ( fd, FLITE_ON, &bl ) == 0 );
2805 ::close ( fd );
2806 }
2807 return res;
2808}
2809
2810bool Jornada::setSoftSuspend ( bool soft )
2811{
2812 bool res = false;
2813 int fd;
2814
2815 if (( fd = ::open ( "/proc/sys/ts/suspend_button_mode", O_WRONLY )) >= 0 ) {
2816 if ( ::write ( fd, soft ? "1" : "0", 1 ) == 1 )
2817 res = true;
2818 else
2819 ::perror ( "write to /proc/sys/ts/suspend_button_mode" );
2820
2821 ::close ( fd );
2822 }
2823 else
2824 ::perror ( "/proc/sys/ts/suspend_button_mode" );
2825
2826 return res;
2827}
diff --git a/noncore/unsupported/libopie/odevice.h b/noncore/unsupported/libopie/odevice.h
new file mode 100644
index 0000000..fc41079
--- a/dev/null
+++ b/noncore/unsupported/libopie/odevice.h
@@ -0,0 +1,302 @@
1/* This file is part of the OPIE libraries
2 Copyright (C) 2002 Robert Griebl (sandman@handhelds.org)
3 Copyright (C) 2003 Holger 'zecke' Freyther (zecke@handhelds.org)
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21#ifndef _LIBOPIE_ODEVICE_H_
22#define _LIBOPIE_ODEVICE_H_
23
24#include <qobject.h>
25#include <qstring.h>
26#include <qnamespace.h>
27#include <qstrlist.h>
28
29#include <opie/odevicebutton.h>
30
31#include <qpe/qpeapplication.h> /* for Transformation enum.. */
32
33class ODeviceData;
34
35namespace Opie {
36
37/**
38 * The available devices
39 */
40enum OModel {
41 Model_Unknown, // = 0
42
43 Model_Series_Mask = 0xff000000,
44
45 Model_iPAQ = ( 1 << 24 ),
46
47 Model_iPAQ_All = ( Model_iPAQ | 0xffffff ),
48 Model_iPAQ_H31xx = ( Model_iPAQ | 0x000001 ),
49 Model_iPAQ_H36xx = ( Model_iPAQ | 0x000002 ),
50 Model_iPAQ_H37xx = ( Model_iPAQ | 0x000004 ),
51 Model_iPAQ_H38xx = ( Model_iPAQ | 0x000008 ),
52 Model_iPAQ_H39xx = ( Model_iPAQ | 0x000010 ),
53 Model_iPAQ_H5xxx = ( Model_iPAQ | 0x000011 ),
54
55 Model_Jornada = ( 6 << 24 ),
56 Model_Jornada_56x = ( Model_Jornada | 0x000001 ),
57
58 Model_Zaurus = ( 2 << 24 ),
59
60 Model_Zaurus_SL5000 = ( Model_Zaurus | 0x000001 ),
61 Model_Zaurus_SL5500 = ( Model_Zaurus | 0x000002 ),
62 Model_Zaurus_SLA300 = ( Model_Zaurus | 0x000003 ),
63 Model_Zaurus_SLB600 = ( Model_Zaurus | 0x000004 ),
64 Model_Zaurus_SLC7x0 = ( Model_Zaurus | 0x000005 ),
65
66 Model_SIMpad = ( 3 << 24 ),
67
68 Model_SIMpad_All = ( Model_SIMpad | 0xffffff ),
69 Model_SIMpad_CL4 = ( Model_SIMpad | 0x000001 ),
70 Model_SIMpad_SL4 = ( Model_SIMpad | 0x000002 ),
71 Model_SIMpad_SLC = ( Model_SIMpad | 0x000004 ),
72 Model_SIMpad_TSinus = ( Model_SIMpad | 0x000008 ),
73
74 Model_Ramses = ( 4 << 24 ),
75
76 Model_Ramses_All = ( Model_Ramses | 0xffffff ),
77 Model_Ramses_MNCI = ( Model_Ramses | 0x000001 ),
78
79 Model_Yopy = ( 5 << 24 ),
80
81 Model_Yopy_All = ( Model_Yopy | 0xffffff ),
82 Model_Yopy_3000 = ( Model_Yopy | 0x000001 ),
83 Model_Yopy_3500 = ( Model_Yopy | 0x000002 ),
84 Model_Yopy_3700 = ( Model_Yopy | 0x000003 ),
85
86};
87
88/**
89 * The vendor of the device
90 */
91enum OVendor {
92 Vendor_Unknown,
93
94 Vendor_HP,
95 Vendor_Sharp,
96 Vendor_SIEMENS,
97 Vendor_MundN,
98 Vendor_GMate,
99};
100
101/**
102 * The System used
103 */
104enum OSystem {
105 System_Unknown,
106
107 System_Familiar,
108 System_Zaurus,
109 System_OpenZaurus,
110 System_Linupy,
111};
112
113enum OLedState {
114 Led_Off,
115 Led_On,
116 Led_BlinkSlow,
117 Led_BlinkFast
118};
119
120enum OLed {
121 Led_Mail,
122 Led_Power,
123 Led_BlueTooth
124};
125
126enum OHardKey {
127 HardKey_Datebook = Qt::Key_F9,
128 HardKey_Contacts = Qt::Key_F10,
129 HardKey_Menu = Qt::Key_F11,
130 HardKey_Home = Qt::Key_F12,
131 HardKey_Mail = Qt::Key_F13,
132 HardKey_Record = Qt::Key_F24,
133 HardKey_Suspend = Qt::Key_F34,
134 HardKey_Backlight = Qt::Key_F35,
135 HardKey_Action = Qt::Key_F10,
136 HardKey_OK = Qt::Key_F11,
137 HardKey_End = Qt::Key_F12,
138};
139
140enum ODirection {
141 CW = 0,
142 CCW = 1,
143 Flip = 2,
144};
145
146enum OHingeStatus {
147 CASE_CLOSED = 3,
148 CASE_PORTRAIT = 2,
149 CASE_LANDSCAPE = 0,
150 CASE_UNKNOWN = 1,
151};
152
153/**
154 * A singleton which gives informations about device specefic option
155 * like the Hardware used, LEDs, the Base Distribution and
156 * hardware key mappings.
157 *
158 * @short A small class for device specefic options
159 * @see QObject
160 * @author Robert Griebl
161 * @version 1.0
162 */
163class ODevice : public QObject {
164 Q_OBJECT
165
166private:
167 /* disable copy */
168 ODevice ( const ODevice & );
169
170protected:
171 ODevice ( );
172 virtual void init ( );
173 virtual void initButtons ( );
174
175 ODeviceData *d;
176
177public:
178 // sandman do we want to allow destructions? -zecke?
179 virtual ~ODevice ( );
180
181 static ODevice *inst ( );
182
183 // information
184
185 QString modelString ( ) const;
186 OModel model ( ) const;
187 inline OModel series ( ) const { return (OModel) ( model ( ) & Model_Series_Mask ); }
188
189 QString vendorString ( ) const;
190 OVendor vendor ( ) const;
191
192 QString systemString ( ) const;
193 OSystem system ( ) const;
194
195 QString systemVersionString ( ) const;
196
197 /*virtual*/ Transformation rotation ( ) const;
198 /*virtual*/ ODirection direction ( ) const;
199
200// system
201
202 virtual bool setSoftSuspend ( bool on );
203 virtual bool suspend ( );
204
205 virtual bool setDisplayStatus ( bool on );
206 virtual bool setDisplayBrightness ( int brightness );
207 virtual int displayBrightnessResolution ( ) const;
208 virtual bool setDisplayContrast ( int contrast );
209 virtual int displayContrastResolution ( ) const;
210
211 // don't add new virtual methods, use this:
212 ///*virtual */ void boo(int i ) { return virtual_hook(1,&i); };
213 // and in your subclass do do overwrite
214 //protected virtual int virtual_hook(int, void *)
215 // which is defined below
216
217 // input / output
218 //FIXME playAlarmSound and al might be better -zecke
219 virtual void alarmSound ( );
220 virtual void keySound ( );
221 virtual void touchSound ( );
222
223 virtual QValueList <OLed> ledList ( ) const;
224 virtual QValueList <OLedState> ledStateList ( OLed led ) const;
225 virtual OLedState ledState ( OLed led ) const;
226 virtual bool setLedState ( OLed led, OLedState st );
227
228 virtual bool hasLightSensor ( ) const;
229 virtual int readLightSensor ( );
230 virtual int lightSensorResolution ( ) const;
231
232 /*virtual*/ bool hasHingeSensor ( ) const;
233 /*virtual*/ OHingeStatus readHingeSensor ( );
234
235 const QStrList &allowedCpuFrequencies() const;
236 bool setCurrentCpuFrequency(uint index);
237
238 /**
239 * Returns the available buttons on this device. The number and location
240 * of buttons will vary depending on the device. Button numbers will be assigned
241 * by the device manufacturer and will be from most preferred button to least preffered
242 * button. Note that this list only contains "user mappable" buttons.
243 *
244 * @todo ### make const
245 */
246 const QValueList<ODeviceButton> &buttons ( ) /** /todo ### make const */;
247
248 /**
249 * Returns the DeviceButton for the \a keyCode. If \a keyCode is not found, it
250 * returns 0L
251 */
252 const ODeviceButton *buttonForKeycode ( ushort keyCode );
253
254 /**
255 * Reassigns the pressed action for \a button. To return to the factory
256 * default pass an empty string as \a qcopMessage.
257 */
258 void remapPressedAction ( int button, const OQCopMessage &qcopMessage );
259
260 /**
261 * Reassigns the held action for \a button. To return to the factory
262 * default pass an empty string as \a qcopMessage.
263 */
264 void remapHeldAction ( int button, const OQCopMessage &qcopMessage );
265
266 /**
267 * How long (in ms) you have to press a button for a "hold" action
268 */
269 uint buttonHoldTime ( ) const;
270
271signals:
272 void buttonMappingChanged ( );
273
274private slots:
275 void systemMessage ( const QCString &, const QByteArray & );
276
277protected:
278 void reloadButtonMapping ( );
279 /* ugly virtual hook */
280 virtual void virtual_hook( int id, void* data );
281
282protected:
283 enum { VIRTUAL_ROTATION = 0x200, VIRTUAL_DIRECTION,
284 VIRTUAL_HAS_HINGE, VIRTUAL_HINGE };
285 struct VirtRotation {
286 Transformation trans;
287 };
288 struct VirtDirection {
289 ODirection direct;
290 };
291 struct VirtHasHinge {
292 bool hasHinge;
293 };
294 struct VirtHingeStatus {
295 OHingeStatus hingeStat;
296 };
297};
298
299}
300
301#endif
302
diff --git a/noncore/unsupported/libopie/odevicebutton.cpp b/noncore/unsupported/libopie/odevicebutton.cpp
new file mode 100644
index 0000000..647ac4b
--- a/dev/null
+++ b/noncore/unsupported/libopie/odevicebutton.cpp
@@ -0,0 +1,237 @@
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3**
4** This file is part of the 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
22#include <qpe/qcopenvelope_qws.h>
23#include <opie/odevicebutton.h>
24
25using namespace Opie;
26
27
28class OQCopMessageData {
29public:
30 QCString m_channel;
31 QCString m_message;
32 QByteArray m_data;
33};
34
35
36OQCopMessage::OQCopMessage ( )
37 : d ( 0 )
38{
39 init ( QCString ( ), QCString ( ), QByteArray ( ));
40}
41
42OQCopMessage::OQCopMessage ( const OQCopMessage &copy )
43 : d ( 0 )
44{
45 init ( copy. channel ( ), copy. message ( ), copy. data ( ));
46}
47
48OQCopMessage &OQCopMessage::operator = ( const OQCopMessage &assign )
49{
50 init ( assign. channel ( ), assign. message ( ), assign. data ( ));
51 return *this;
52}
53
54OQCopMessage::OQCopMessage ( const QCString &ch, const QCString &m, const QByteArray &arg )
55 : d ( 0 )
56{
57 init ( ch, m, arg );
58}
59
60void OQCopMessage::init ( const QCString &ch, const QCString &m, const QByteArray &arg )
61{
62 if ( !d )
63 d = new OQCopMessageData ( );
64 d-> m_channel = ch;
65 d-> m_message = m;
66 d-> m_data = arg;
67}
68
69bool OQCopMessage::send ( )
70{
71 if ( d-> m_channel. isEmpty ( ) || d-> m_message. isEmpty ( ) )
72 return false;
73
74 QCopEnvelope e ( d-> m_channel, d-> m_message );
75
76 if ( d-> m_data. size ( ))
77 e. writeRawBytes ( d-> m_data. data ( ), d-> m_data. size ( ));
78
79 return true;
80}
81
82QCString OQCopMessage::channel ( ) const
83{
84 return d-> m_channel;
85}
86
87QCString OQCopMessage::message ( ) const
88{
89 return d-> m_message;
90}
91
92QByteArray OQCopMessage::data ( ) const
93{
94 return d-> m_data;
95}
96
97bool OQCopMessage::isNull() const
98{
99 return d-> m_message.isNull() || d-> m_channel.isNull();
100}
101void OQCopMessage::setChannel ( const QCString &ch )
102{
103 d-> m_channel = ch;
104}
105
106void OQCopMessage::setMessage ( const QCString &m )
107{
108 d-> m_message = m;
109}
110
111void OQCopMessage::setData ( const QByteArray &data )
112{
113 d-> m_data = data;
114}
115
116/*! \class Opie::ODeviceButton
117 \brief The Opie::ODeviceButton class represents a physical user mappable button on a Qtopia device.
118
119 This class represents a physical button on a Qtopia device. A
120 device may have "user programmable" buttons.
121 The location and number of buttons will vary from device to
122 device. userText() and pixmap() may be used to describe this button
123 to the user in help documentation.
124
125 \ingroup qtopiaemb
126 \internal
127*/
128
129ODeviceButton::ODeviceButton()
130{
131}
132
133ODeviceButton::~ODeviceButton()
134{
135}
136
137/*!
138 Returns the button's keycode.
139 */
140ushort ODeviceButton::keycode() const
141{
142 return m_Keycode;
143}
144
145
146/*!
147 This function returns a human readable, translated description of the button.
148 */
149QString ODeviceButton::userText() const
150{
151 return m_UserText;
152}
153
154/*!
155 This function returns the pixmap for this button. If there isn't one
156 it will return an empty (null) pixmap.
157 */
158QPixmap ODeviceButton::pixmap() const
159{
160 return m_Pixmap;
161}
162
163/*!
164 This function returns the factory preset (default) action for when this button
165 is pressed. The return value is a legal QCop message.
166 */
167OQCopMessage ODeviceButton::factoryPresetPressedAction() const
168{
169 return m_FactoryPresetPressedAction;
170}
171
172/*!
173 This function returns the user assigned action for when this button is pressed.
174 If no action is assigned, factoryPresetAction() is returned.
175 */
176OQCopMessage ODeviceButton::pressedAction() const
177{
178 if (m_PressedAction.channel().isEmpty())
179 return factoryPresetPressedAction();
180 return m_PressedAction;
181}
182
183/*!
184 This function returns the factory preset (default) action for when this button
185 is pressed and held. The return value is a legal QCop message.
186 */
187OQCopMessage ODeviceButton::factoryPresetHeldAction() const
188{
189 return m_FactoryPresetHeldAction;
190}
191
192/*!
193 This function returns the user assigned action for when this button is pressed
194 and held. If no action is assigned, factoryPresetAction() is returned.
195 */
196OQCopMessage ODeviceButton::heldAction() const
197{
198 if (m_HeldAction.channel().isEmpty())
199 return factoryPresetHeldAction();
200 return m_HeldAction;
201}
202
203void ODeviceButton::setKeycode(ushort keycode)
204{
205 m_Keycode = keycode;
206}
207
208void ODeviceButton::setUserText(const QString& text)
209{
210 m_UserText = text;
211}
212
213void ODeviceButton::setPixmap(const QPixmap& picture)
214{
215 m_Pixmap = picture;
216}
217
218void ODeviceButton::setFactoryPresetPressedAction(const OQCopMessage& action)
219{
220 m_FactoryPresetPressedAction = action;
221}
222
223
224void ODeviceButton::setPressedAction(const OQCopMessage& action)
225{
226 m_PressedAction = action;
227}
228
229void ODeviceButton::setFactoryPresetHeldAction(const OQCopMessage& action)
230{
231 m_FactoryPresetHeldAction = action;
232}
233
234void ODeviceButton::setHeldAction(const OQCopMessage& action)
235{
236 m_HeldAction = action;
237}
diff --git a/noncore/unsupported/libopie/odevicebutton.h b/noncore/unsupported/libopie/odevicebutton.h
new file mode 100644
index 0000000..1621526
--- a/dev/null
+++ b/noncore/unsupported/libopie/odevicebutton.h
@@ -0,0 +1,107 @@
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3**
4** This file is part of the 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 DEVICE_BUTTON_H
21#define DEVICE_BUTTON_H
22
23#include <qpixmap.h>
24#include <qstring.h>
25
26class OQCopMessageData;
27
28namespace Opie
29{
30
31class OQCopMessage {
32public:
33 OQCopMessage ( );
34 OQCopMessage ( const OQCopMessage &copy );
35 OQCopMessage ( const QCString &m_channel, const QCString &message, const QByteArray &args = QByteArray ( ));
36
37 OQCopMessage &operator = ( const OQCopMessage &assign );
38
39 void setChannel ( const QCString &channel );
40 void setMessage ( const QCString &message );
41 void setData ( const QByteArray &ba );
42
43 QCString channel ( ) const;
44 QCString message ( ) const;
45 QByteArray data ( ) const;
46
47 bool isNull()const;
48
49 bool send ( );
50
51private:
52 void init ( const QCString &m_channel, const QCString &message, const QByteArray &args );
53
54 OQCopMessageData *d;
55 class Private;
56 Private* m_data;
57};
58
59
60/**
61 * This class represents a physical button on a Qtopia device. A device may
62 * have n "user programmable" buttons, which are number 1..n. The location
63 * and number of buttons will vary from device to device. userText() and pixmap()
64 * may be used to describe this button to the user in help documentation.
65 *
66 * @version 1.0
67 * @author Trolltech
68 * @short A representation of buttons
69 */
70
71class ODeviceButton
72{
73public:
74 ODeviceButton();
75 virtual ~ODeviceButton();
76
77 ushort keycode ( ) const;
78 QString userText ( ) const;
79 QPixmap pixmap ( ) const;
80 OQCopMessage factoryPresetPressedAction ( ) const;
81 OQCopMessage pressedAction ( ) const;
82 OQCopMessage factoryPresetHeldAction ( ) const;
83 OQCopMessage heldAction ( ) const;
84
85 void setKeycode ( ushort keycode );
86 void setUserText ( const QString& text );
87 void setPixmap ( const QPixmap& picture );
88 void setFactoryPresetPressedAction ( const OQCopMessage& qcopMessage );
89 void setPressedAction ( const OQCopMessage& qcopMessage );
90 void setFactoryPresetHeldAction ( const OQCopMessage& qcopMessage );
91 void setHeldAction ( const OQCopMessage& qcopMessage );
92
93private:
94 ushort m_Keycode;
95 QString m_UserText;
96 QPixmap m_Pixmap;
97 OQCopMessage m_FactoryPresetPressedAction;
98 OQCopMessage m_PressedAction;
99 OQCopMessage m_FactoryPresetHeldAction;
100 OQCopMessage m_HeldAction;
101 class Private;
102 Private *d;
103};
104
105}
106
107#endif
diff --git a/noncore/unsupported/libopie/ofiledialog.cc b/noncore/unsupported/libopie/ofiledialog.cc
new file mode 100644
index 0000000..47306b6
--- a/dev/null
+++ b/noncore/unsupported/libopie/ofiledialog.cc
@@ -0,0 +1,212 @@
1/*
2               =. This file is part of the OPIE Project
3             .=l. Copyright (c) 2002,2003 <zecke@handhelds.org>
4           .>+-=
5 _;:,     .>    :=|. This library is free software; you can
6.> <`_,   >  .   <= redistribute it and/or modify it under
7:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
8.="- .-=="i,     .._ License as published by the Free Software
9 - .   .-<_>     .<> Foundation; either version 2 of the License,
10     ._= =}       : or (at your option) any later version.
11    .%`+i>       _;_.
12    .i_,=:_.      -<s. This library is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
17..}^=.=       =       ; Library General Public License for more
18++=   -.     .`     .: details.
19 :     =  ...= . :.=-
20 -.   .:....=;==+<; You should have received a copy of the GNU
21  -_. . .   )=.  = Library General Public License along with
22    --        :-=` this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation,
24 Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
26
27*/
28
29#include <qpe/config.h>
30#include <qpe/qpeapplication.h>
31
32#include <qfileinfo.h>
33#include <qlayout.h>
34
35
36#include "ofiledialog.h"
37
38
39namespace {
40 /*
41 * helper functions to load the start dir
42 * and to save it
43 * helper to extract the dir out of a file name
44 */
45 /**
46 * This method will use Config( argv[0] );
47 * @param key The group key used
48 */
49 QString lastUsedDir( const QString& key ) {
50 if ( qApp->argc() < 1 )
51 return QString::null;
52
53 Config cfg( QFileInfo(qApp->argv()[0]).fileName() ); // appname
54 cfg.setGroup( key );
55 return cfg.readEntry("LastDir", QPEApplication::documentDir() );
56 }
57
58 void saveLastDir( const QString& key, const QString& file ) {
59 if ( qApp->argc() < 1 )
60 return;
61
62 Config cfg( QFileInfo(qApp->argv()[0]).fileName() );
63 cfg.setGroup( key );
64 QFileInfo inf( file );
65 cfg.writeEntry("LastDir", inf.dirPath( true ) );
66 }
67};
68
69/**
70 * This constructs a modal dialog
71 *
72 * @param caption The caption of the dialog
73 * @param wid The parent widget
74 * @param mode The mode of the OFileSelector @see OFileSelector
75 * @param selector The selector of the OFileSelector
76 * @param dirName the dir or resource to start from
77 * @param fileName a proposed or existing filename
78 * @param mimetypes The mimeTypes
79 */
80OFileDialog::OFileDialog(const QString &caption,
81 QWidget *wid, int mode, int selector,
82 const QString &dirName,
83 const QString &fileName,
84 const QMap<QString,QStringList>& mimetypes )
85 : QDialog( wid, "OFileDialog", true )
86{
87 // QVBoxLayout *lay = new QVBoxLayout(this);
88 //showMaximized();
89 QVBoxLayout *lay = new QVBoxLayout(this );
90 file = new OFileSelector(this , mode, selector,
91 dirName, fileName,
92 mimetypes );
93 lay->addWidget( file );
94
95 //lay->addWidget( file );
96 //showFullScreen();
97 setCaption( caption.isEmpty() ? tr("FileDialog") : caption );
98 connect(file, SIGNAL(fileSelected(const QString&) ),
99 this, SLOT(slotFileSelected(const QString&) ) );
100 connect(file, SIGNAL(ok() ),
101 this, SLOT(slotSelectorOk()) ) ;
102
103 connect(file, SIGNAL(dirSelected(const QString&) ), this, SLOT(slotDirSelected(const QString&) ) );
104
105#if 0
106 connect(file, SIGNAL(dirSelected(const QString &) ),
107 this, SLOT(slotDirSelected(const QString &) ) );
108#endif
109}
110/**
111 * @returns the mimetype of the selected
112 * currently it return QString::null
113 */
114QString OFileDialog::mimetype()const
115{
116 return QString::null;
117}
118
119/**
120 * @return the fileName
121 */
122QString OFileDialog::fileName()const
123{
124 return file->selectedName();
125}
126
127/**
128 * return a DocLnk to the current file
129 */
130DocLnk OFileDialog::selectedDocument()const
131{
132 return file->selectedDocument();
133}
134
135/**
136 * This opens up a filedialog in Open mode
137 *
138 * @param selector the Selector Mode
139 * @param startDir Where to start from
140 * @param file A proposed filename
141 * @param mimes A list of MimeTypes
142 * @param wid the parent
143 * @param caption of the dialog if QString::null tr("Open") will be used
144 * @return the fileName or QString::null
145 */
146QString OFileDialog::getOpenFileName(int selector,
147 const QString &_startDir,
148 const QString &file,
149 const MimeTypes &mimes,
150 QWidget *wid,
151 const QString &caption )
152{
153 QString ret;
154 QString startDir = _startDir;
155 if (startDir.isEmpty() )
156 startDir = lastUsedDir( "FileDialog-OPEN" );
157
158
159 OFileDialog dlg( caption.isEmpty() ? tr("Open") : caption,
160 wid, OFileSelector::Open, selector, startDir, file, mimes);
161 dlg.showMaximized();
162 if( dlg.exec() ) {
163 ret = dlg.fileName();
164 saveLastDir( "FileDialog-OPEN", ret );
165 }
166
167 return ret;
168}
169
170/**
171 * This opens up a file dialog in save mode
172 * @see getOpenFileName
173 */
174QString OFileDialog::getSaveFileName(int selector,
175 const QString &_startDir,
176 const QString &file,
177 const MimeTypes &mimes,
178 QWidget *wid,
179 const QString &caption )
180{
181 QString ret;
182 QString startDir = _startDir;
183 if (startDir.isEmpty() )
184 startDir = lastUsedDir( "FileDialog-SAVE" );
185
186 OFileDialog dlg( caption.isEmpty() ? tr("Save") : caption,
187 wid, OFileSelector::Save, selector, startDir, file, mimes);
188 dlg.showMaximized();
189 if( dlg.exec() ) {
190 ret = dlg.fileName();
191 saveLastDir( "FileDialog-SAVE", ret );
192 }
193
194 return ret;
195}
196
197void OFileDialog::slotFileSelected(const QString & )
198{
199 accept();
200}
201
202void OFileDialog::slotSelectorOk( )
203{
204 accept();
205}
206
207void OFileDialog::slotDirSelected(const QString &dir )
208{
209 setCaption( dir );
210 // if mode
211 //accept();
212}
diff --git a/noncore/unsupported/libopie/ofiledialog.h b/noncore/unsupported/libopie/ofiledialog.h
new file mode 100644
index 0000000..3b905c0
--- a/dev/null
+++ b/noncore/unsupported/libopie/ofiledialog.h
@@ -0,0 +1,101 @@
1/*
2               =. This file is part of the OPIE Project
3             .=l. Copyright (c) 2002 zecke <zecke@handhelds.org>
4           .>+-=
5 _;:,     .>    :=|. This library is free software; you can
6.> <`_,   >  .   <= redistribute it and/or modify it under
7:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
8.="- .-=="i,     .._ License as published by the Free Software
9 - .   .-<_>     .<> Foundation; either version 2 of the License,
10     ._= =}       : or (at your option) any later version.
11    .%`+i>       _;_.
12    .i_,=:_.      -<s. This library is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
17..}^=.=       =       ; Library General Public License for more
18++=   -.     .`     .: details.
19 :     =  ...= . :.=-
20 -.   .:....=;==+<; You should have received a copy of the GNU
21  -_. . .   )=.  = Library General Public License along with
22    --        :-=` this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation,
24 Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
26
27*/
28
29
30#ifndef OpieFileDialog_h
31#define OpieFileDialog_h
32
33#include <qdialog.h>
34
35#include <opie/ofileselector.h>
36
37/**
38 * This class places a OFileSelector inside a QDialog.
39 * It provides static method for letting a user chose
40 * a file for either opening or saving.
41 * Most of the time the c'tor will not be used instead using
42 * the static member functions is prefered.
43 *
44 * <pre>
45 * QMap<QString, QStringList> mimeTypes;
46 * QStringList types;
47 * types << "text@slash* ";
48 * mimeTypes.insert( tr("Text"), types );
49 * mimeTypes.insert( tr("All"), " *@slash* " ); // remove the spaces in the 2nd comment
50 * QString fileName= OFileDialog::getOpenFileName( OFileSelector::EXTENDED_ALL,
51 * "foo","bar", mimeTypes);
52 * </pre>
53 *
54 * @short A small QDialog swalloing a FileSelector
55 * @see QDialog
56 * @see OFileSelector
57 * @version 0.1-unfinished
58 * @author Holger Freyther ( zecke@handhelds.org )
59 */
60class OFileDialog : public QDialog {
61 Q_OBJECT
62 public:
63 OFileDialog(const QString &caption,
64 QWidget *, int mode, int selector,
65 const QString &dirName,
66 const QString &fileName = QString::null,
67 const MimeTypes &mimetypes = MimeTypes() );
68 QString mimetype() const;
69 QString fileName() const;
70 DocLnk selectedDocument()const;
71
72 // static methods
73 static QString getOpenFileName(int selector,
74 const QString& startDir = QString::null,
75 const QString &fileName = QString::null,
76 const MimeTypes& mime = MimeTypes(),
77 QWidget *wid = 0,
78 const QString &caption = QString::null );
79
80 static QString getSaveFileName(int selector,
81 const QString& startDir = QString::null,
82 const QString& fileName = QString::null,
83 const MimeTypes& mimefilter = MimeTypes(),
84 QWidget *wid = 0,
85 const QString &caption = QString::null );
86
87 //let's OFileSelector catch up first
88 //static QString getExistingDirectory(const QString& startDir = QString::null,
89 // QWidget *parent = 0,
90 // const QString& caption = QString::null );
91 private:
92 class OFileDialogPrivate;
93 OFileDialogPrivate *d;
94 OFileSelector *file;
95
96 private slots:
97 void slotFileSelected( const QString & );
98 void slotDirSelected(const QString & );
99 void slotSelectorOk();
100};
101#endif
diff --git a/noncore/unsupported/libopie/ofileselector.cpp b/noncore/unsupported/libopie/ofileselector.cpp
new file mode 100644
index 0000000..2a6aed0
--- a/dev/null
+++ b/noncore/unsupported/libopie/ofileselector.cpp
@@ -0,0 +1,929 @@
1#include <qcombobox.h>
2#include <qdir.h>
3#include <qlabel.h>
4#include <qlayout.h>
5#include <qlineedit.h>
6#include <qpopupmenu.h>
7#include <qwidgetstack.h>
8
9/* hacky but we need to get FileSelector::filter */
10#define private public
11#include <qpe/fileselector.h>
12#undef private
13
14#include <qpe/qpeapplication.h>
15#include <qpe/mimetype.h>
16#include <qpe/resource.h>
17#include <qpe/storage.h>
18
19#include "ofileselector_p.h"
20#include "ofileselector.h"
21
22
23
24OFileViewInterface::OFileViewInterface( OFileSelector* selector )
25 : m_selector( selector ) {
26}
27OFileViewInterface::~OFileViewInterface() {
28}
29QString OFileViewInterface::name()const{
30 return m_name;
31}
32void OFileViewInterface::setName( const QString& name ) {
33 m_name = name;
34}
35OFileSelector* OFileViewInterface::selector()const {
36 return m_selector;
37}
38DocLnk OFileViewInterface::selectedDocument()const {
39 return DocLnk( selectedName() );
40}
41bool OFileViewInterface::showNew()const {
42 return selector()->showNew();
43}
44bool OFileViewInterface::showClose()const {
45 return selector()->showClose();
46}
47MimeTypes OFileViewInterface::mimeTypes()const {
48 return selector()->mimeTypes();
49}
50QStringList OFileViewInterface::currentMimeType()const {
51 return selector()->currentMimeType();
52}
53void OFileViewInterface::activate( const QString& ) {
54 // not implemented here
55}
56void OFileViewInterface::ok() {
57 emit selector()->ok();
58}
59void OFileViewInterface::cancel() {
60 emit selector()->cancel();
61}
62void OFileViewInterface::closeMe() {
63 emit selector()->closeMe();
64}
65void OFileViewInterface::fileSelected( const QString& str) {
66 emit selector()->fileSelected( str);
67}
68void OFileViewInterface::fileSelected( const DocLnk& lnk) {
69 emit selector()->fileSelected( lnk );
70}
71void OFileViewInterface::setCurrentFileName( const QString& str ) {
72 selector()->m_lneEdit->setText( str );
73}
74QString OFileViewInterface::currentFileName()const{
75 return selector()->m_lneEdit->text();
76}
77QString OFileViewInterface::startDirectory()const{
78 return selector()->m_startDir;
79}
80
81
82ODocumentFileView::ODocumentFileView( OFileSelector* selector )
83 : OFileViewInterface( selector ) {
84 m_selector = 0;
85 setName( QObject::tr("Documents") );
86}
87ODocumentFileView::~ODocumentFileView() {
88
89}
90QString ODocumentFileView::selectedName()const {
91 if (!m_selector)
92 return QString::null;
93
94 return m_selector->selectedDocument().file();
95}
96QString ODocumentFileView::selectedPath()const {
97 return QPEApplication::documentDir();
98}
99QString ODocumentFileView::directory()const {
100 return selectedPath();
101}
102void ODocumentFileView::reread() {
103 if (!m_selector)
104 return;
105
106 m_selector->setNewVisible( showNew() );
107 m_selector->setCloseVisible( showClose() );
108 m_selector->filter = currentMimeType().join(";");
109 m_selector->reread();
110}
111int ODocumentFileView::fileCount()const {
112 if (!m_selector)
113 return -1;
114
115 return m_selector->fileCount();
116}
117DocLnk ODocumentFileView::selectedDocument()const {
118 if (!m_selector)
119 return DocLnk();
120
121 return m_selector->selectedDocument();
122}
123QWidget* ODocumentFileView::widget( QWidget* parent ) {
124 if (!m_selector ) {
125 m_selector = new FileSelector(currentMimeType().join(";"), parent, "fileselector", showNew(), showClose() );
126 QObject::connect(m_selector, SIGNAL(fileSelected(const DocLnk&) ),
127 selector(), SLOT(slotDocLnkBridge(const DocLnk&) ) );
128 QObject::connect(m_selector, SIGNAL(closeMe() ),
129 selector(), SIGNAL(closeMe() ) );
130 QObject::connect(m_selector, SIGNAL(newSelected(const DocLnk&) ),
131 selector(), SIGNAL(newSelected(const DocLnk&) ) );
132 }
133
134 return m_selector;
135}
136
137/*
138 * This is the file system view used
139 * we use a QListView + QListViewItems for it
140 */
141
142OFileSelectorItem::OFileSelectorItem( QListView* view, const QPixmap& pixmap,
143 const QString& path, const QString& date,
144 const QString& size, const QString& dir,
145 bool isLocked, bool isDir )
146 : QListViewItem( view )
147{
148 setPixmap(0, pixmap );
149 setText(1, path );
150 setText(2, size );
151 setText(3, date );
152 m_isDir = isDir;
153 m_dir = dir;
154 m_locked = isLocked;
155}
156OFileSelectorItem::~OFileSelectorItem() {
157
158}
159bool OFileSelectorItem::isLocked()const {
160 return m_locked;
161}
162QString OFileSelectorItem::directory()const {
163 return m_dir;
164}
165bool OFileSelectorItem::isDir()const {
166 return m_isDir;
167}
168QString OFileSelectorItem::path()const {
169 return text( 1 );
170}
171QString OFileSelectorItem::key( int id, bool )const {
172 QString ke;
173 if( id == 0 || id == 1 ){ // name
174 if( m_isDir ){
175 ke.append("0" );
176 ke.append( text(1) );
177 }else{
178 ke.append("1" );
179 ke.append( text(1) );
180 }
181 return ke;
182 }else
183 return text( id );
184
185}
186
187OFileViewFileListView::OFileViewFileListView( QWidget* parent, const QString& startDir,
188 OFileSelector* sel)
189 : QWidget( parent ), m_sel( sel ) {
190 m_all = false;
191 QVBoxLayout* lay = new QVBoxLayout( this );
192 m_currentDir = startDir;
193
194 /*
195 * now we add a special bar
196 * One Button For Up
197 * Home
198 * Doc
199 * And a dropdown menu with FileSystems
200 * FUTURE: one to change dir with lineedit
201 * Bookmarks
202 * Create Dir
203 */
204 QHBox* box = new QHBox(this );
205 box->setBackgroundMode( PaletteButton );
206 box->setSpacing( 0 );
207
208 QToolButton *btn = new QToolButton( box );
209 btn->setIconSet( Resource::loadIconSet("up") );
210 connect(btn, SIGNAL(clicked() ),
211 this, SLOT( cdUP() ) );
212
213 btn = new QToolButton( box );
214 btn->setIconSet( Resource::loadIconSet("home") );
215 connect(btn, SIGNAL(clicked() ),
216 this, SLOT( cdHome() ) );
217
218 btn = new QToolButton( box );
219 btn->setIconSet( Resource::loadIconSet("DocsIcon") );
220 connect(btn, SIGNAL(clicked() ),
221 this, SLOT(cdDoc() ) );
222
223 m_btnNew = new QToolButton( box );
224 m_btnNew->setIconSet( Resource::loadIconSet("new") );
225 connect(m_btnNew, SIGNAL(clicked() ),
226 this, SLOT(slotNew() ) );
227
228
229 m_btnClose = new QToolButton( box );
230 m_btnClose->setIconSet( Resource::loadIconSet("close") );
231 connect(m_btnClose, SIGNAL(clicked() ),
232 selector(), SIGNAL(closeMe() ) );
233
234 btn = new QToolButton( box );
235 btn->setIconSet( Resource::loadIconSet("cardmon/pcmcia") );
236
237 /* let's fill device parts */
238 QPopupMenu* pop = new QPopupMenu(this);
239 connect(pop, SIGNAL( activated(int) ),
240 this, SLOT(slotFSActivated(int) ) );
241
242 StorageInfo storage;
243 const QList<FileSystem> &fs = storage.fileSystems();
244 QListIterator<FileSystem> it(fs);
245 for ( ; it.current(); ++it ) {
246 const QString disk = (*it)->name();
247 const QString path = (*it)->path();
248 m_dev.insert( disk, path );
249 pop->insertItem( disk );
250 }
251 m_fsPop = pop;
252
253
254 btn->setPopup( pop );
255
256 lay->addWidget( box );
257
258 m_view = new QListView( this );
259
260 m_view->installEventFilter(this);
261
262 QPEApplication::setStylusOperation( m_view->viewport(),
263 QPEApplication::RightOnHold);
264 m_view->addColumn(" " );
265 m_view->addColumn(tr("Name"), 135 );
266 m_view->addColumn(tr("Size"), -1 );
267 m_view->addColumn(tr("Date"), 60 );
268 m_view->addColumn(tr("Mime Type"), -1 );
269
270
271 m_view->setSorting( 1 );
272 m_view->setAllColumnsShowFocus( TRUE );
273
274 lay->addWidget( m_view, 1000 );
275 connectSlots();
276}
277OFileViewFileListView::~OFileViewFileListView() {
278}
279void OFileViewFileListView::slotNew() {
280 DocLnk lnk;
281 emit selector()->newSelected( lnk );
282}
283OFileSelectorItem* OFileViewFileListView::currentItem()const{
284 QListViewItem* item = m_view->currentItem();
285 if (!item )
286 return 0l;
287
288 return static_cast<OFileSelectorItem*>(item);
289}
290void OFileViewFileListView::reread( bool all ) {
291 m_view->clear();
292
293 if (selector()->showClose() )
294 m_btnClose->show();
295 else
296 m_btnClose->hide();
297
298 if (selector()->showNew() )
299 m_btnNew->show();
300 else
301 m_btnNew->hide();
302
303 m_mimes = selector()->currentMimeType();
304 m_all = all;
305
306 QDir dir( m_currentDir );
307 if (!dir.exists() )
308 return;
309
310 dir.setSorting( QDir::Name | QDir::DirsFirst | QDir::Reversed );
311 int filter;
312 if (m_all )
313 filter = QDir::Files | QDir::Dirs | QDir::Hidden | QDir::All;
314 else
315 filter = QDir::Files | QDir::Dirs | QDir::All;
316 dir.setFilter( filter );
317
318 // now go through all files
319 const QFileInfoList *list = dir.entryInfoList();
320 if (!list) {
321 cdUP();
322 return;
323 }
324 QFileInfoListIterator it( *list );
325 QFileInfo *fi;
326 while( (fi=it.current() ) ){
327 if( fi->fileName() == QString::fromLatin1("..") || fi->fileName() == QString::fromLatin1(".") ){
328 ++it;
329 continue;
330 }
331
332 /*
333 * It is a symlink we try to resolve it now but don't let us attack by DOS
334 *
335 */
336 if( fi->isSymLink() ){
337 QString file = fi->dirPath( true ) + "/" + fi->readLink();
338 for( int i = 0; i<=4; i++) { // 5 tries to prevent dos
339 QFileInfo info( file );
340 if( !info.exists() ){
341 addSymlink( fi, TRUE );
342 break;
343 }else if( info.isDir() ){
344 addDir( fi, TRUE );
345 break;
346 }else if( info.isFile() ){
347 addFile( fi, TRUE );
348 break;
349 }else if( info.isSymLink() ){
350 file = info.dirPath(true ) + "/" + info.readLink() ;
351 break;
352 }else if( i == 4){ // couldn't resolve symlink add it as symlink
353 addSymlink( fi );
354 }
355 } // off for loop for symlink resolving
356 }else if( fi->isDir() )
357 addDir( fi );
358 else if( fi->isFile() )
359 addFile( fi );
360
361 ++it;
362 } // of while loop
363 m_view->sort();
364
365}
366int OFileViewFileListView::fileCount()const{
367 return m_view->childCount();
368}
369QString OFileViewFileListView::currentDir()const{
370 return m_currentDir;
371}
372OFileSelector* OFileViewFileListView::selector() {
373 return m_sel;
374}
375
376bool OFileViewFileListView::eventFilter (QObject *o, QEvent *e) {
377 if ( e->type() == QEvent::KeyPress ) {
378 QKeyEvent *k = (QKeyEvent *)e;
379 if ( (k->key()==Key_Enter) || (k->key()==Key_Return)) {
380 slotClicked( Qt::LeftButton,m_view->currentItem(),QPoint(0,0),0);
381 return true;
382 }
383 }
384 return false;
385}
386
387
388void OFileViewFileListView::connectSlots() {
389 connect(m_view, SIGNAL(clicked(QListViewItem*) ),
390 this, SLOT(slotCurrentChanged(QListViewItem*) ) );
391 connect(m_view, SIGNAL(mouseButtonClicked(int,QListViewItem*,const QPoint&,int) ),
392 this, SLOT(slotClicked(int,QListViewItem*,const QPoint&,int) ) );
393}
394void OFileViewFileListView::slotCurrentChanged( QListViewItem* item) {
395 if (!item)
396 return;
397#if 0
398
399 OFileSelectorItem *sel = static_cast<OFileSelectorItem*>(item);
400
401 if (!sel->isDir() ) {
402 selector()->m_lneEdit->setText( sel->text(1) );
403 // if in fileselector mode we will emit selected
404 if ( selector()->mode() == OFileSelector::FileSelector ) {
405 qWarning("slot Current Changed");
406 QStringList str = QStringList::split("->", sel->text(1) );
407 QString path = sel->directory() + "/" + str[0].stripWhiteSpace();
408 emit selector()->fileSelected( path );
409 DocLnk lnk( path );
410 emit selector()->fileSelected( lnk );
411 }
412 }
413#endif
414}
415void OFileViewFileListView::slotClicked(int button , QListViewItem* item, const QPoint&, int ) {
416 if (!item || ( button != Qt::LeftButton) )
417 return;
418
419 OFileSelectorItem *sel = static_cast<OFileSelectorItem*>(item);
420 if (!sel->isLocked() ) {
421 QStringList str = QStringList::split("->", sel->text(1) );
422 if (sel->isDir() ) {
423 m_currentDir = sel->directory() + "/" + str[0].stripWhiteSpace();
424 emit selector()->dirSelected( m_currentDir );
425 reread( m_all );
426 }else { // file
427 qWarning("slot Clicked");
428 selector()->m_lneEdit->setText( str[0].stripWhiteSpace() );
429 QString path = sel->directory() + "/" + str[0].stripWhiteSpace();
430 emit selector()->fileSelected( path );
431 DocLnk lnk( path );
432 emit selector()->fileSelected( lnk );
433 }
434 } // not locked
435}
436void OFileViewFileListView::addFile( QFileInfo* info, bool symlink ) {
437 MimeType type( info->absFilePath() );
438 if (!compliesMime( type.id() ) )
439 return;
440
441 QPixmap pix = type.pixmap();
442 QString dir, name; bool locked;
443 if ( pix.isNull() ) {
444 QWMatrix matrix;
445 QPixmap pixer(Resource::loadPixmap("UnknownDocument") );
446 matrix.scale( .4, .4 );
447 pix = pixer.xForm( matrix );
448 }
449 dir = info->dirPath( true );
450 locked = false;
451 if ( symlink )
452 name = info->fileName() + " -> " + info->dirPath() + "/" + info->readLink();
453 else{
454 name = info->fileName();
455 if ( ( (selector()->mode() == OFileSelector::Open)&& !info->isReadable() ) ||
456 ( (selector()->mode() == OFileSelector::Save)&& !info->isWritable() ) ) {
457 locked = true; pix = Resource::loadPixmap("locked");
458 }
459 }
460 (void)new OFileSelectorItem( m_view, pix, name,
461 info->lastModified().toString(), QString::number( info->size() ),
462 dir, locked );
463}
464void OFileViewFileListView::addDir( QFileInfo* info, bool symlink ) {
465 bool locked = false; QString name; QPixmap pix;
466
467 if ( ( ( selector()->mode() == OFileSelector::Open ) && !info->isReadable() ) ||
468 ( ( selector()->mode() == OFileSelector::Save ) && !info->isWritable() ) ) {
469 locked = true;
470 if ( symlink )
471 pix = Resource::loadPixmap( "opie/symlink" );
472 else
473 pix = Resource::loadPixmap( "lockedfolder" );
474 }else
475 pix = symlink ? Resource::loadPixmap( "opie/symlink") : Resource::loadPixmap("folder");
476
477 name = symlink ? info->fileName() + " -> " + info->dirPath(true) + "/" + info->readLink() :
478 info->fileName();
479
480 (void)new OFileSelectorItem( m_view, pix, name,
481 info->lastModified().toString(),
482 QString::number( info->size() ),
483 info->dirPath( true ), locked, true );
484
485
486}
487void OFileViewFileListView::addSymlink( QFileInfo* , bool ) {
488
489}
490void OFileViewFileListView::cdUP() {
491 QDir dir( m_currentDir );
492 dir.cdUp();
493
494 if (!dir.exists() )
495 m_currentDir = "/";
496 else
497 m_currentDir = dir.absPath();
498
499 emit selector()->dirSelected( m_currentDir );
500 reread( m_all );
501}
502void OFileViewFileListView::cdHome() {
503 m_currentDir = QDir::homeDirPath();
504 emit selector()->dirSelected( m_currentDir );
505 reread( m_all );
506}
507void OFileViewFileListView::cdDoc() {
508 m_currentDir = QPEApplication::documentDir();
509 emit selector()->dirSelected( m_currentDir );
510 reread( m_all );
511}
512void OFileViewFileListView::changeDir( const QString& dir ) {
513 m_currentDir = dir;
514 emit selector()->dirSelected( m_currentDir );
515 reread( m_all );
516}
517void OFileViewFileListView::slotFSActivated( int id ) {
518 changeDir ( m_dev[m_fsPop->text(id)] );
519}
520
521/* check if the mimetype in mime
522 * complies with the one which is current
523 */
524/*
525 * We've the mimetype of the file
526 * We need to get the stringlist of the current mimetype
527 *
528 * mime = image@slashjpeg
529 * QStringList = 'image@slash*'
530 * or QStringList = image/jpeg;image/png;application/x-ogg
531 * or QStringList = application/x-ogg;image@slash*;
532 * with all these mime filters it should get acceptes
533 * to do so we need to look if mime is contained inside
534 * the stringlist
535 * if it's contained return true
536 * if not ( I'm no RegExp expert at all ) we'll look if a '@slash*'
537 * is contained in the mimefilter and then we will
538 * look if both are equal until the '/'
539 */
540bool OFileViewFileListView::compliesMime( const QString& str) {
541 if (str.isEmpty() || m_mimes.isEmpty() || str.stripWhiteSpace().isEmpty() )
542 return true;
543
544 for (QStringList::Iterator it = m_mimes.begin(); it != m_mimes.end(); ++it ) {
545 QRegExp reg( (*it) );
546 reg.setWildcard( true );
547 if ( str.find( reg ) != -1 )
548 return true;
549
550 }
551 return false;
552}
553/*
554 * The listView giving access to the file system!
555 */
556class OFileViewFileSystem : public OFileViewInterface {
557public:
558 OFileViewFileSystem( OFileSelector* );
559 ~OFileViewFileSystem();
560
561 QString selectedName() const;
562 QString selectedPath() const;
563
564 QString directory()const;
565 void reread();
566 int fileCount()const;
567
568 QWidget* widget( QWidget* parent );
569 void activate( const QString& );
570private:
571 OFileViewFileListView* m_view;
572 bool m_all : 1;
573};
574OFileViewFileSystem::OFileViewFileSystem( OFileSelector* sel)
575 : OFileViewInterface( sel ) {
576 m_view = 0;
577 m_all = false;
578}
579OFileViewFileSystem::~OFileViewFileSystem() {
580}
581QString OFileViewFileSystem::selectedName()const{
582 if (!m_view )
583 return QString::null;
584
585 QString cFN=currentFileName();
586 if (cFN.startsWith("/")) return cFN;
587 return m_view->currentDir() + "/" + cFN;
588}
589QString OFileViewFileSystem::selectedPath()const{
590 return QString::null;
591}
592QString OFileViewFileSystem::directory()const{
593 if (!m_view)
594 return QString::null;
595
596 OFileSelectorItem* item = m_view->currentItem();
597 if (!item )
598 return QString::null;
599
600 return QDir(item->directory() ).absPath();
601}
602void OFileViewFileSystem::reread() {
603 if (!m_view)
604 return;
605
606 m_view->reread( m_all );
607}
608int OFileViewFileSystem::fileCount()const{
609 if (!m_view )
610 return -1;
611 return m_view->fileCount();
612}
613QWidget* OFileViewFileSystem::widget( QWidget* parent ) {
614 if (!m_view ) {
615 m_view = new OFileViewFileListView( parent, startDirectory(), selector() );
616 }
617 return m_view;
618}
619void OFileViewFileSystem::activate( const QString& str) {
620 m_all = (str != QObject::tr("Files") );
621
622
623}
624
625/* Selector */
626/**
627 * @short new and complete c'tor
628 *
629 * Create a OFileSelector to let the user select a file. It can
630 * either be used to open a file, select a save name in a dir or
631 * as a dropin for the FileSelector.
632 *
633 * <pre>
634 * QMap<QString, QStringList> mimeTypes;
635 * QStringList types;
636 * types << "text@slash* ";
637 * types << "audio@slash*";
638 * mimeTypes.insert( tr("Audio and Text"), types );
639 * mimeTypes.insert( tr("All"), "*@slash*);
640 *
641 * now you could create your fileselector
642 * </pre>
643 *
644 *
645 * @param parent the parent of this widget
646 * @param mode The mode from the enum Mode (Open,Save,FILESELECTOR)
647 * @param sel The selector to be used
648 * @param dirName The name of the dir to start int
649 * @param fileName The fileName placed in the fileselector lineedit
650 * @param mimetypes The MimeType map of used mimetypes
651 * @param showNew Show a New Button. Most likely to be used in the FileSelector view.
652 * @param showClose Show a Close Button. Most likely to be used in FileSelector view.
653 *
654 */
655OFileSelector::OFileSelector( QWidget* parent, int mode, int sel,
656 const QString& dirName, const QString& fileName,
657 const MimeTypes& mimetypes,
658 bool showNew, bool showClose)
659 : QWidget( parent, "OFileSelector" )
660{
661 m_current = 0;
662 m_shNew = showNew;
663 m_shClose = showClose;
664 m_mimeType = mimetypes;
665 m_startDir = dirName;
666
667 m_mode = mode;
668 m_selector = sel;
669
670 initUI();
671 m_lneEdit->setText( fileName );
672 initMime();
673 initViews();
674
675 QString str;
676 switch ( m_selector ) {
677 default:
678 case Normal:
679 str = QObject::tr("Documents");
680 m_cmbView->setCurrentItem( 0 );
681 break;
682 case Extended:
683 str = QObject::tr("Files");
684 m_cmbView->setCurrentItem( 1 );
685 break;
686 case ExtendedAll:
687 str = QObject::tr("All Files");
688 m_cmbView->setCurrentItem( 2 );
689 break;
690 }
691 slotViewChange( str );
692
693}
694
695/**
696 * This a convience c'tor to just substitute the use of FileSelector
697 */
698OFileSelector::OFileSelector( const QString& mimeFilter, QWidget* parent, const char* name,
699 bool showNew, bool showClose )
700 : QWidget( parent, name )
701{
702 m_current = 0;
703 m_shNew = showNew;
704 m_shClose = showClose;
705 m_startDir = QPEApplication::documentDir();
706
707 if (!mimeFilter.isEmpty() )
708 m_mimeType.insert(mimeFilter, QStringList::split(";", mimeFilter ) );
709
710 m_mode = OFileSelector::FileSelector;
711 m_selector = OFileSelector::Normal;
712
713 initUI();
714 initMime();
715 initViews();
716 m_cmbView->setCurrentItem( 0 );
717 slotViewChange( QObject::tr("Documents") );
718}
719/*
720 * INIT UI will set up the basic GUI
721 * Layout: Simple VBoxLayout
722 * On top a WidgetStack containing the Views...
723 * - List View
724 * - Document View
725 * Below we will have a Label + LineEdit
726 * Below we will have two ComoBoxes one for choosing the view one for
727 * choosing the mimetype
728 */
729void OFileSelector::initUI() {
730 QVBoxLayout* lay = new QVBoxLayout( this );
731
732 m_stack = new QWidgetStack( this );
733 lay->addWidget( m_stack, 1000 );
734
735 m_nameBox = new QHBox( this );
736 (void)new QLabel( tr("Name:"), m_nameBox );
737 m_lneEdit = new QLineEdit( m_nameBox );
738 m_lneEdit ->installEventFilter(this);
739 lay->addWidget( m_nameBox );
740
741 m_cmbBox = new QHBox( this );
742 m_cmbView = new QComboBox( m_cmbBox );
743 m_cmbMime = new QComboBox( m_cmbBox );
744 lay->addWidget( m_cmbBox );
745}
746
747/*
748 * This will make sure that the return key in the name edit causes dialogs to close
749 */
750
751bool OFileSelector::eventFilter (QObject *o, QEvent *e) {
752 if ( e->type() == QEvent::KeyPress ) {
753 QKeyEvent *k = (QKeyEvent *)e;
754 if ( (k->key()==Key_Enter) || (k->key()==Key_Return)) {
755 emit ok();
756 return true;
757 }
758 }
759 return false;
760}
761
762/*
763 * This will insert the MimeTypes into the Combo Box
764 * And also connect the changed signal
765 *
766 * AutoMimeTyping is disabled for now. It used to reparse a dir and then set available mimetypes
767 */
768void OFileSelector::initMime() {
769 MimeTypes::Iterator it;
770 for ( it = m_mimeType.begin(); it != m_mimeType.end(); ++it ) {
771 m_cmbMime->insertItem( it.key() );
772 }
773 m_cmbMime->setCurrentItem( 0 );
774
775 connect( m_cmbMime, SIGNAL(activated(int) ),
776 this, SLOT(slotMimeTypeChanged() ) );
777
778}
779void OFileSelector::initViews() {
780 m_cmbView->insertItem( QObject::tr("Documents") );
781 m_cmbView->insertItem( QObject::tr("Files") );
782 m_cmbView->insertItem( QObject::tr("All Files") );
783 connect(m_cmbView, SIGNAL(activated(const QString&) ),
784 this, SLOT(slotViewChange(const QString&) ) );
785
786
787 m_views.insert( QObject::tr("Documents"), new ODocumentFileView(this) );
788
789 /* see above why add both */
790 OFileViewInterface* in = new OFileViewFileSystem( this );
791 m_views.insert( QObject::tr("Files"), in );
792 m_views.insert( QObject::tr("All Files"), in );
793}
794
795/**
796 * d'tor
797 */
798OFileSelector::~OFileSelector() {
799
800}
801
802/**
803 * Convience function for the fileselector
804 * make sure to delete the DocLnk
805 *
806 * @see DocLnk
807 * @todo remove in ODP
808 */
809const DocLnk* OFileSelector::selected() {
810 DocLnk* lnk = new DocLnk( currentView()->selectedDocument() );
811 return lnk;
812}
813
814/**
815 *
816 * @return the name of the selected file
817 */
818QString OFileSelector::selectedName()const{
819 return currentView()->selectedName();
820}
821
822/**
823 * @return the selected path
824 */
825QString OFileSelector::selectedPath()const {
826 return currentView()->selectedPath();
827}
828
829/**
830 * @return the directory name
831 */
832QString OFileSelector::directory()const {
833 return currentView()->directory();
834}
835
836/**
837 * @return a DocLnk for the selected document
838 */
839DocLnk OFileSelector::selectedDocument()const {
840 return currentView()->selectedDocument();
841}
842
843/**
844 * @return the number of items for the current view
845 */
846int OFileSelector::fileCount()const {
847 return currentView()->fileCount();
848}
849
850/**
851 * @return reparse the file content
852 */
853void OFileSelector::reread() {
854 return currentView()->reread();
855}
856OFileViewInterface* OFileSelector::currentView()const{
857 return m_current;
858}
859bool OFileSelector::showNew()const {
860 return m_shNew;
861}
862bool OFileSelector::showClose()const {
863 return m_shClose;
864}
865MimeTypes OFileSelector::mimeTypes()const {
866 return m_mimeType;
867}
868
869/**
870 * @return the Mode of the OFileSelector
871 */
872int OFileSelector::mode()const{
873 return m_mode;
874}
875
876/**
877 * @return the Selector of the OFileSelector
878 */
879int OFileSelector::selector()const{
880 return m_selector;
881}
882QStringList OFileSelector::currentMimeType()const {
883 return m_mimeType[m_cmbMime->currentText()];
884}
885void OFileSelector::slotMimeTypeChanged() {
886 reread();
887}
888void OFileSelector::slotDocLnkBridge( const DocLnk& lnk) {
889 m_lneEdit->setText( lnk.name() );
890 emit fileSelected( lnk );
891 emit fileSelected( lnk.name() );
892}
893void OFileSelector::slotFileBridge( const QString& str) {
894 DocLnk lnk( str );
895 emit fileSelected( lnk );
896}
897void OFileSelector::slotViewChange( const QString& view ) {
898 OFileViewInterface* interface = m_views[view];
899 if (!interface)
900 return;
901
902 interface->activate( view );
903 if (m_current)
904 m_stack->removeWidget( m_current->widget( m_stack ) );
905
906 static int id = 1;
907
908 m_stack->addWidget( interface->widget(m_stack), id );
909 m_stack->raiseWidget( id );
910
911 interface->reread();
912 m_current = interface;
913
914 id++;
915}
916void OFileSelector::setNewVisible( bool b ) {
917 m_shNew = b;
918 currentView()->reread();
919}
920void OFileSelector::setCloseVisible( bool b ) {
921 m_shClose = b;
922 currentView()->reread();
923}
924void OFileSelector::setNameVisible( bool b ) {
925 if ( b )
926 m_nameBox->show();
927 else
928 m_nameBox->hide();
929}
diff --git a/noncore/unsupported/libopie/ofileselector.h b/noncore/unsupported/libopie/ofileselector.h
new file mode 100644
index 0000000..767455c
--- a/dev/null
+++ b/noncore/unsupported/libopie/ofileselector.h
@@ -0,0 +1,210 @@
1/*
2 This is based on code and ideas of
3 L. J. Potter ljp@llornkcor.com
4 Thanks a lot
5
6
7               =. This file is part of the OPIE Project
8             .=l. Copyright (c) 2002,2003 Holger Freyther <zecke@handhelds.org>
9           .>+-=
10 _;:,     .>    :=|. This library is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This library is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31
32*/
33
34
35#ifndef OPIE_OFILESELECTOR_FOO_H
36#define OPIE_OFILESELECTOR_FOO_H
37
38#include <qlist.h>
39#include <qwidget.h>
40#include <qmap.h>
41#include <qvaluelist.h>
42#include <qstringlist.h>
43
44#include <qpe/applnk.h>
45
46typedef QMap<QString, QStringList> MimeTypes;
47
48class OFileViewInterface;
49class OFileViewFileListView;
50class QLineEdit;
51class QComboBox;
52class QWidgetStack;
53class QHBox;
54
55
56/**
57 * @short a dropin replacement for the FileSelector
58 *
59 * This class is first used insert the OFileDialog.
60 * It supports multiple view and mimetype filtering for now.
61 *
62 * @see OFileDialog
63 * @see FileSelector
64 * @author zecke
65 * @version 0.1
66 */
67class OFileSelector : public QWidget {
68 Q_OBJECT
69 friend class OFileViewInterface;
70 friend class OFileViewFileListView;
71public:
72 /**
73 * The Mode of the Fileselector
74 * Open = Open A File
75 * Save = Save a File
76 * FILESELECTOR = As A GUI in a screen to select a file
77 */
78 enum Mode { Open=1, Save=2, FileSelector=4, OPEN=1, SAVE=2, FILESELECTOR=4 };
79// enum OldMode { OPEN=1, SAVE=2, FILESELECTOR = 4 };
80 /**
81 * Normal = The old FileSelector
82 * Extended = Dir View
83 * ExtendedAll = Dir View with all hidden files
84 * Default = What the vendor considers best
85 */
86 enum Selector { Normal = 0, Extended=1, ExtendedAll =2, Default=3, NORMAL=0,EXTENDED=1, EXTENDED_ALL =2, DEFAULT=3 };
87// enum OldSelector { NORMAL = 0, EXTENDED =1, EXTENDED_ALL = 2};
88
89
90 OFileSelector(QWidget* parent, int mode, int selector,
91 const QString& dirName,
92 const QString& fileName,
93 const MimeTypes& mimetypes = MimeTypes(),
94 bool newVisible = FALSE, bool closeVisible = FALSE );
95
96 OFileSelector(const QString& mimeFilter, QWidget* parent,
97 const char* name = 0, bool newVisible = TRUE, bool closeVisible = FALSE );
98 ~OFileSelector();
99
100 const DocLnk* selected();
101
102 QString selectedName()const;
103 QString selectedPath()const;
104 QString directory()const;
105
106 DocLnk selectedDocument()const;
107
108 int fileCount()const;
109 void reread();
110
111 int mode()const;
112 int selector()const;
113
114 /**
115 * Set the Icon visible
116 * @param b Show or Hide the New Button
117 */
118 void setNewVisible( bool b );
119
120 /**
121 * Set the Icon visible
122 */
123 void setCloseVisible( bool b );
124
125 /**
126 * Set the Name Line visible
127 */
128 void setNameVisible( bool b );
129
130signals:
131 /**
132 * dirSelected is emitted whenever changed into a different dir
133 */
134 void dirSelected( const QString& );
135
136 /**
137 * fileSelected is emitted when a file is selected
138 * it uses a DocLnk as parameter
139 */
140 void fileSelected( const DocLnk& );
141
142 /**
143 * fileSelected is emitted when a file is selected
144 * the complete path is a parameter
145 */
146 void fileSelected( const QString& );
147
148 /**
149 * Create a new File with a DocLnk
150 */
151 void newSelected( const DocLnk& );
152
153 void closeMe();
154
155 /**
156 * Ok is emitted on a Qt::Key_Return or Q::Key_Enter
157 * in the line edit
158 */
159 void ok();
160 void cancel();
161
162/* used by the ViewInterface */
163private:
164 bool showNew()const;
165 bool showClose()const;
166 MimeTypes mimeTypes()const;
167 QStringList currentMimeType()const;
168
169private:
170 /* inits the Widgets */
171 void initUI();
172 /* inits the MimeType ComboBox content + connects signals and slots */
173 void initMime();
174 /* init the Views :) */
175 void initViews();
176
177private:
178 QLineEdit* m_lneEdit; // the LineEdit for the Name
179 QComboBox *m_cmbView, *m_cmbMime; // two ComboBoxes to select the View and MimeType
180 QWidgetStack* m_stack; // our widget stack which will contain the views
181 OFileViewInterface* currentView()const; // returns the currentView
182 OFileViewInterface* m_current; // here is the view saved
183 bool m_shNew : 1; // should we show New?
184 bool m_shClose : 1; // should we show Close?
185 MimeTypes m_mimeType; // list of mimetypes
186
187 QMap<QString, OFileViewInterface*> m_views; // QString translated view name + ViewInterface Ptr
188 QHBox* m_nameBox; // the LineEdit + Label is hold here
189 QHBox* m_cmbBox; // this holds the two combo boxes
190
191 QString m_startDir;
192 int m_mode;
193 int m_selector;
194
195 struct Data; // used for future versions
196 Data *d;
197
198private slots:
199 void slotMimeTypeChanged();
200
201 /* will set the text of the lineedit and emit a fileChanged signal */
202 void slotDocLnkBridge( const DocLnk& );
203 void slotFileBridge( const QString& );
204 void slotViewChange( const QString& );
205
206 bool eventFilter (QObject *o, QEvent *e);
207
208};
209
210#endif
diff --git a/noncore/unsupported/libopie/ofileselector_p.h b/noncore/unsupported/libopie/ofileselector_p.h
new file mode 100644
index 0000000..7fd0c50
--- a/dev/null
+++ b/noncore/unsupported/libopie/ofileselector_p.h
@@ -0,0 +1,151 @@
1#ifndef OPIE_OFILE_SELECTOR_PRIVATE_H
2#define OPIE_OFILE_SELECTOR_PRIVATE_H
3
4#include <qmap.h>
5#include <qstringlist.h>
6#include <qwidget.h>
7#include <qlistview.h>
8
9#include <qpe/applnk.h>
10#include <qpe/fileselector.h>
11
12
13/*
14 * How to avoid having really two different objects
15 * for Extended and ExtendedAll
16 * The only difference is the Lister...
17 * a) static object?
18 * b) leave some object inside the OFileSelector which can be used?
19 * c) when switching views tell which view we want o have.. internally we can switch then
20 *
21 * I'll take c) -zecke
22 */
23
24
25/* the View Interface */
26class OFileSelector;
27typedef QMap<QString, QStringList> MimeTypes;
28class QFileInfo;
29class QToolButton;
30class OFileViewInterface {
31public:
32 OFileViewInterface( OFileSelector* selector );
33 virtual ~OFileViewInterface();
34 virtual QString selectedName()const = 0;
35 virtual QString selectedPath()const = 0;
36 virtual QString directory()const = 0;
37 virtual void reread() = 0;
38 virtual int fileCount()const = 0;
39 virtual DocLnk selectedDocument()const;
40 virtual QWidget* widget( QWidget* parent) = 0;
41 virtual void activate( const QString& );
42 QString name()const;
43protected:
44 OFileSelector* selector()const;
45 void setName( const QString& );
46 bool showNew()const;
47 bool showClose()const;
48 MimeTypes mimeTypes()const;
49 QStringList currentMimeType()const;
50 QString startDirectory()const;
51protected:
52 void ok();
53 void cancel();
54 void closeMe();
55 void fileSelected( const QString& );
56 void fileSelected( const DocLnk& );
57 void setCurrentFileName( const QString& );
58 QString currentFileName()const;
59
60private:
61 QString m_name;
62 OFileSelector* m_selector;
63};
64
65
66/* THE Document View hosting a FileSelector*/
67class ODocumentFileView : public OFileViewInterface {
68public:
69 ODocumentFileView( OFileSelector* selector );
70 ~ODocumentFileView();
71
72 QString selectedName() const;
73 QString selectedPath() const;
74
75 QString directory() const;
76 void reread();
77 int fileCount()const;
78 DocLnk selectedDocument()const;
79
80 QWidget* widget( QWidget* parent );
81
82private:
83 mutable FileSelector* m_selector;
84
85};
86
87class OFileSelectorItem : public QListViewItem {
88public:
89 OFileSelectorItem( QListView* view, const QPixmap& pixmap,
90 const QString& path, const QString& date,
91 const QString& size, const QString& mDir,
92 bool isLocked = false, bool isDir = false );
93 ~OFileSelectorItem();
94 bool isLocked()const;
95 bool isDir()const;
96 QString directory()const;
97 QString path()const;
98 QString key(int id, bool )const;
99
100private:
101 bool m_locked : 1;
102 bool m_isDir : 1;
103 QString m_dir;
104};
105
106class OFileViewFileListView : public QWidget {
107 Q_OBJECT
108public:
109 OFileViewFileListView( QWidget* parent, const QString& dir, OFileSelector* selector );
110 ~OFileViewFileListView();
111
112 OFileSelectorItem* currentItem()const;
113 void reread( bool all = false );
114 int fileCount()const;
115 QString currentDir()const;
116protected:
117 bool eventFilter (QObject *o, QEvent *e);
118private slots:
119 void slotNew(); // will emit newSelected
120 void cdUP();
121 void cdHome();
122 void cdDoc();
123 void changeDir( const QString& );
124 void slotCurrentChanged( QListViewItem* );
125 void slotClicked(int, QListViewItem*, const QPoint&, int );
126 void slotFSActivated(int);
127
128protected:
129
130 OFileSelector* selector();
131
132private:
133 QMap<QString, QString> m_dev;
134 bool m_all : 1;
135 OFileSelector* m_sel;
136 QPopupMenu* m_fsPop;
137 bool compliesMime( const QString& );
138 QStringList m_mimes; // used in compy mime
139 QString m_currentDir;
140 QToolButton *m_btnNew, *m_btnClose;
141 void connectSlots();
142 void addFile( QFileInfo* info, bool symlink = FALSE );
143 void addDir ( QFileInfo* info, bool symlink = FALSE );
144 void addSymlink( QFileInfo* info, bool = FALSE );
145
146
147private:
148 QListView* m_view;
149};
150
151#endif
diff --git a/noncore/unsupported/libopie/ofileview.h b/noncore/unsupported/libopie/ofileview.h
new file mode 100644
index 0000000..e072477
--- a/dev/null
+++ b/noncore/unsupported/libopie/ofileview.h
@@ -0,0 +1,87 @@
1/*
2               =. This file is part of the OPIE Project
3             .=l. Copyright (c) 2002 zecke <zecke@handhelds.org>
4           .>+-=
5 _;:,     .>    :=|. This library is free software; you can
6.> <`_,   >  .   <= redistribute it and/or modify it under
7:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
8.="- .-=="i,     .._ License as published by the Free Software
9 - .   .-<_>     .<> Foundation; either version 2 of the License,
10     ._= =}       : or (at your option) any later version.
11    .%`+i>       _;_.
12    .i_,=:_.      -<s. This library is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
17..}^=.=       =       ; Library General Public License for more
18++=   -.     .`     .: details.
19 :     =  ...= . :.=-
20 -.   .:....=;==+<; You should have received a copy of the GNU
21  -_. . .   )=.  = Library General Public License along with
22    --        :-=` this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation,
24 Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
26
27*/
28
29#ifndef ofileview_h
30#define ofileview_h
31
32#include <qobject.h>
33#include <qwidget.h>
34
35class QFileInfo;
36class QDir;
37class DocLnk;
38
39/**
40 * A OFileView is a specialised View for the
41 * OFileSelector
42 * With a View you can chage the user visible
43 * representation of a OFileLister
44 * OFileView is just a basic interface which helps you to
45 * write new views
46 */
47class OFileView {
48 Q_OBJECT
49 public:
50 OFileView(QWidget *widget,
51 const char *name );
52 virtual OFileView();
53 virtual ~OFileSelectorView() = 0;
54
55 virtual void addFile(const QString &mine,
56 QFileInfo *info,
57 bool isSymlink = FALSE ) = 0;
58
59 virtual void addDir (const QString &mine,
60 QFileInfo *info,
61 bool isSymlink = FALSE ) = 0;
62
63 virtual void addSymlink(const QString &mime,
64 QFileInfo *info,
65 bool isSymlink = FALSE ) = 0;
66
67 virtual void cd(const QString &path ) = 0;
68 signals:
69 void fileSelected(const QString &);
70 void fileSelected(const DocLnk & );
71 void contextMenu();
72 void changedDir(const QString &);
73 void changedDir(const QDir & );
74};
75
76class OFileViewFactory {
77 // Q_OBJECT
78 public:
79 OFileViewFactory() {} ;
80 virtual ~OFileViewFactory() = 0;
81
82 OFileSelectorView* newView(QWidget *parent, const char *name );
83 QString name()const;
84};
85
86
87#endif
diff --git a/noncore/unsupported/libopie/ofontmenu.cc b/noncore/unsupported/libopie/ofontmenu.cc
new file mode 100644
index 0000000..d16c5e5
--- a/dev/null
+++ b/noncore/unsupported/libopie/ofontmenu.cc
@@ -0,0 +1,156 @@
1
2
3#include <qpe/config.h>
4#include "ofontmenu.h"
5
6
7/**
8 * Constructs the FontMenu.
9 *
10 * @param parent The parent widget
11 * @param name A name for this widget
12 * @param list The list of widgets to be controlled
13 */
14OFontMenu::OFontMenu(QWidget *parent, const char *name, const QList<QWidget> &list )
15 : QPopupMenu( parent, name )
16{
17 m_list = list;
18 m_wids.setAutoDelete( TRUE );
19
20 insertItem(tr("Large"), this, SLOT(slotLarge() ),
21 0, 10);
22 insertItem(tr("Medium"), this, SLOT(slotMedium() ),
23 0, 11 );
24 insertItem(tr("Small"), this, SLOT(slotSmall() ),
25 0, 12 );
26 setCheckable( true );
27 m_size=10;
28}
29
30/**
31 * This method saves the font size
32 * into a Config object
33 * OFontMenu will be used as group and size as key
34 * @param cfg The Config object to be used
35 */
36void OFontMenu::save(Config *cfg )
37{
38 cfg->setGroup("OFontMenu" );
39 cfg->writeEntry("size", m_size );
40}
41
42/**
43 * This method restores the font size from a Config object
44 * it'll apply the sizes to the widgets and will also set the
45 * menu appropriate
46 */
47void OFontMenu::restore(Config *cfg )
48{
49 cfg->setGroup("OFontMeny" );
50 m_size = cfg->readNumEntry("size" );
51 setItemChecked(10, false );
52 setItemChecked(11, false );
53 setItemChecked(12, false );
54 switch( m_size ){
55 case 8:
56 setItemChecked(12, true );
57 break;
58 case 14:
59 setItemChecked(10, true );
60 break;
61 case 10:// fall through
62 default:
63 setItemChecked(11, true );
64 m_size = 10;
65 break;
66 }
67 setFontSize( m_size );
68}
69
70/**
71 * set the list of widgets
72 * @param list the widget list
73 */
74void OFontMenu::setWidgets(const QList<QWidget> &list )
75{
76 m_list = list;
77}
78
79/**
80 * add a widget to the list
81 * @param wid The widget to be added
82 */
83void OFontMenu::addWidget( QWidget *wid )
84{
85 m_list.append(wid );
86}
87
88/**
89 * removes the widget from the list of controlled objects
90 * @param wid the to be removed widget
91 */
92void OFontMenu::removeWidget( QWidget *wid )
93{
94 m_list.remove( wid );
95}
96
97/**
98 * The list of controlled widgets
99 */
100const QList<QWidget> &OFontMenu::widgets()const
101{
102 return m_list;
103}
104
105/**
106 * Forces a size on a widget
107 * @param wid The widget
108 * @param size The font size forced onto the widget
109 */
110void OFontMenu::forceSize(QWidget *wid, int size )
111{
112 WidSize *widz = new WidSize;
113 widz->wid = wid;
114 widz->size = size;
115 m_wids.append( widz );
116}
117void OFontMenu::slotSmall()
118{
119 setItemChecked(10, false );
120 setItemChecked(11, false );
121 setItemChecked(12, true );
122 setFontSize( 8 );
123}
124void OFontMenu::slotMedium()
125{
126 setItemChecked(10, false );
127 setItemChecked(11, true );
128 setItemChecked(12, false );
129 setFontSize(10 );
130}
131void OFontMenu::slotLarge()
132{
133 setItemChecked(10, true );
134 setItemChecked(11, false );
135 setItemChecked(12, false );
136 setFontSize(14 );
137}
138void OFontMenu::setFontSize(int size )
139{
140 m_size = size;
141 QWidget *wid;
142 for(wid = m_list.first(); wid !=0; wid = m_list.next() ){
143 QFont font = wid->font();
144 font.setPointSize( size );
145 wid->setFont( font );
146 }
147 if(!m_wids.isEmpty() ){
148 WidSize *wids;
149 for( wids = m_wids.first(); wids != 0; wids = m_wids.next() ){
150 QFont font = wids->wid->font();
151 font.setPointSize( wids->size );
152 wids->wid->setFont( font );
153 }
154 }
155 emit fontChanged(size );
156}
diff --git a/noncore/unsupported/libopie/ofontmenu.h b/noncore/unsupported/libopie/ofontmenu.h
new file mode 100644
index 0000000..6e143ca
--- a/dev/null
+++ b/noncore/unsupported/libopie/ofontmenu.h
@@ -0,0 +1,113 @@
1
2/*
3
4               =. This file is part of the OPIE Project
5             .=l. Copyright (c) 2002 zecke <zecke@handhelds.org>
6           .>+-=
7 _;:,     .>    :=|. This library is free software; you can
8.> <`_,   >  .   <= redistribute it and/or modify it under
9:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
10.="- .-=="i,     .._ License as published by the Free Software
11 - .   .-<_>     .<> Foundation; either version 2 of the License,
12     ._= =}       : or (at your option) any later version.
13    .%`+i>       _;_.
14    .i_,=:_.      -<s. This library is distributed in the hope that
15     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
16    : ..    .:,     . . . without even the implied warranty of
17    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
18  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.=       =       ; Library General Public License for more
20++=   -.     .`     .: details.
21 :     =  ...= . :.=-
22 -.   .:....=;==+<; You should have received a copy of the GNU
23  -_. . .   )=.  = Library General Public License along with
24    --        :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28
29*/
30
31
32
33
34#ifndef ofontmenu_h
35#define ofontmenu_h
36
37#include <qpopupmenu.h>
38#include <qlist.h>
39
40/*
41 * @internal
42 */
43namespace {
44 struct WidSize {
45 QWidget *wid;
46 int size;
47 };
48
49};
50
51// forward declarations
52class Config;
53
54/**
55 * This class is a specialised QPopupMenu. It'll display three different
56 * font sizes. Small, Normal and large by adding widgets to the Menu
57 * you can control the font size of these widgets
58 * by using the save and restore method you can also apply font sizes
59 * over two different runtimes
60 *
61 * <pre>
62 * QTable* tbl = new QTable();
63 * QList<QWidget> wid;
64 * wid.append( tbl );
65 * OFontMenu* menu = new OFontMenu(this, "Popup Menu", wid );
66 * Config cfg("mycfg");
67 * menu->restore( cfg );
68 * </pre>
69 *
70 * @author Holger Freyther ( zecke@handhelds.org )
71 * @version 0.1
72 * @short PopupMenu which can control the size of Widgets
73 * @see QPopupMenu
74 */
75class OFontMenu : public QPopupMenu {
76 Q_OBJECT
77 public:
78 OFontMenu(QWidget *parent, const char* name, const QList<QWidget> &list );
79 void save(Config *cfg );
80 void restore(Config *cfg );
81 void setWidgets(const QList<QWidget> &list );
82 void addWidget(QWidget *wid );
83 void forceSize(QWidget *wid, int size );
84 void removeWidget(QWidget *wid );
85 const QList<QWidget> &widgets()const;
86
87 signals:
88 /**
89 * this signal gets emitted when the font size gets changed
90 * @param size The new size of font
91 */
92 void fontChanged(int size );
93
94 private:
95 QList<QWidget> m_list;
96 QList<WidSize> m_wids;
97 int m_size;
98 class OFontMenuPrivate;
99 OFontMenuPrivate *d;
100
101 private slots:
102 virtual void slotSmall();
103 virtual void slotMedium();
104 virtual void slotLarge();
105 void setFontSize(int size );
106};
107
108#endif
109
110
111
112
113
diff --git a/noncore/unsupported/libopie/ofontselector.cpp b/noncore/unsupported/libopie/ofontselector.cpp
new file mode 100644
index 0000000..87b7869
--- a/dev/null
+++ b/noncore/unsupported/libopie/ofontselector.cpp
@@ -0,0 +1,411 @@
1/*
2               =. This file is part of the OPIE Project
3             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
4           .>+-=
5 _;:,     .>    :=|. This library is free software; you can
6.> <`_,   >  .   <= redistribute it and/or modify it under
7:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
8.="- .-=="i,     .._ License as published by the Free Software
9 - .   .-<_>     .<> Foundation; either version 2 of the License,
10     ._= =}       : or (at your option) any later version.
11    .%`+i>       _;_.
12    .i_,=:_.      -<s. This library is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
17..}^=.=       =       ; Library General Public License for more
18++=   -.     .`     .: details.
19 :     =  ...= . :.=-
20 -.   .:....=;==+<; You should have received a copy of the GNU
21  -_. . .   )=.  = Library General Public License along with
22    --        :-=` this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation,
24 Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
26
27*/
28
29#include <qlayout.h>
30#include <qlistbox.h>
31#include <qcombobox.h>
32#include <qlabel.h>
33#include <qmultilineedit.h>
34
35#include <qpe/fontdatabase.h>
36
37#include "ofontselector.h"
38
39class OFontSelectorPrivate {
40public:
41 QListBox * m_font_family_list;
42 QComboBox * m_font_style_list;
43 QComboBox * m_font_size_list;
44 QMultiLineEdit *m_preview;
45
46 bool m_pointbug : 1;
47
48 FontDatabase m_fdb;
49};
50
51namespace {
52
53class FontListItem : public QListBoxText {
54public:
55 FontListItem ( const QString &t, const QStringList &styles, const QValueList<int> &sizes ) : QListBoxText ( )
56 {
57 m_name = t;
58 m_styles = styles;
59 m_sizes = sizes;
60
61 QString str = t;
62 str [0] = str [0]. upper ( );
63 setText ( str );
64 }
65
66 QString family ( ) const
67 {
68 return m_name;
69 }
70
71 const QStringList &styles ( ) const
72 {
73 return m_styles;
74 }
75
76 const QValueList<int> &sizes ( ) const
77 {
78 return m_sizes;
79 }
80
81private:
82 QStringList m_styles;
83 QValueList<int> m_sizes;
84 QString m_name;
85};
86
87
88static int findItemCB ( QComboBox *box, const QString &str )
89{
90 for ( int i = 0; i < box-> count ( ); i++ ) {
91 if ( box-> text ( i ) == str )
92 return i;
93 }
94 return -1;
95}
96
97}
98/* static same as anon. namespace */
99static int qt_version ( )
100{
101 const char *qver = qVersion ( );
102
103 return ( qver [0] - '0' ) * 100 + ( qver [2] - '0' ) * 10 + ( qver [4] - '0' );
104}
105
106/**
107 * Constructs the Selector object
108 * @param withpreview If a font preview should be given
109 * @param parent The parent of the Font Selector
110 * @param name The name of the object
111 * @param fl WidgetFlags
112 */
113OFontSelector::OFontSelector ( bool withpreview, QWidget *parent, const char *name, WFlags fl ) : QWidget ( parent, name, fl )
114{
115 d = new OFontSelectorPrivate ( );
116
117 QGridLayout *gridLayout = new QGridLayout ( this, 0, 0, 4, 4 );
118 gridLayout->setRowStretch ( 4, 10 );
119
120 d-> m_font_family_list = new QListBox( this, "FontListBox" );
121 gridLayout->addMultiCellWidget( d-> m_font_family_list, 0, 4, 0, 0 );
122 connect( d-> m_font_family_list, SIGNAL( highlighted(int) ), this, SLOT( fontFamilyClicked(int) ) );
123
124 QLabel *label = new QLabel( tr( "Style" ), this );
125 gridLayout->addWidget( label, 0, 1 );
126
127 d-> m_font_style_list = new QComboBox( this, "StyleListBox" );
128 connect( d-> m_font_style_list, SIGNAL( activated(int) ), this, SLOT( fontStyleClicked(int) ) );
129 gridLayout->addWidget( d-> m_font_style_list, 1, 1 );
130
131 label = new QLabel( tr( "Size" ), this );
132 gridLayout->addWidget( label, 2, 1 );
133
134 d-> m_font_size_list = new QComboBox( this, "SizeListBox" );
135 connect( d-> m_font_size_list, SIGNAL( activated(int) ),
136 this, SLOT( fontSizeClicked(int) ) );
137 gridLayout->addWidget( d-> m_font_size_list, 3, 1 );
138
139 d-> m_pointbug = ( qt_version ( ) <= 233 );
140
141 if ( withpreview ) {
142 d-> m_preview = new QMultiLineEdit ( this, "Preview" );
143 d-> m_preview-> setAlignment ( AlignCenter );
144 d-> m_preview-> setWordWrap ( QMultiLineEdit::WidgetWidth );
145 d-> m_preview-> setMargin ( 3 );
146 d-> m_preview-> setText ( tr( "The Quick Brown Fox Jumps Over The Lazy Dog" ));
147 gridLayout-> addRowSpacing ( 5, 4 );
148 gridLayout-> addMultiCellWidget ( d-> m_preview, 6, 6, 0, 1 );
149 gridLayout-> setRowStretch ( 6, 5 );
150 }
151 else
152 d-> m_preview = 0;
153
154 loadFonts ( d-> m_font_family_list );
155}
156
157OFontSelector::~OFontSelector ( )
158{
159 delete d;
160}
161
162/**
163 * This methods tries to set the font
164 * @param f The wishes font
165 * @return success or failure
166 */
167bool OFontSelector::setSelectedFont ( const QFont &f )
168{
169 return setSelectedFont ( f. family ( ), d-> m_fdb. styleString ( f ), f. pointSize ( ), QFont::encodingName ( f. charSet ( )));
170}
171
172
173/**
174 * This is an overloaded method @see setSelectedFont
175 * @param familyStr The family of the font
176 * @param styleStr The style of the font
177 * @param sizeVal The size of font
178 * @param charset The charset to be used. Will be deprecated by QT3
179 */
180bool OFontSelector::setSelectedFont ( const QString &familyStr, const QString &styleStr, int sizeVal, const QString & charset )
181{
182 QString sizeStr = QString::number ( sizeVal );
183
184 QListBoxItem *family = d-> m_font_family_list-> findItem ( familyStr );
185 if ( !family )
186 family = d-> m_font_family_list-> findItem ( "Helvetica" );
187 if ( !family )
188 family = d-> m_font_family_list-> firstItem ( );
189 d-> m_font_family_list-> setCurrentItem ( family );
190 fontFamilyClicked ( d-> m_font_family_list-> index ( family ));
191
192 int style = findItemCB ( d-> m_font_style_list, styleStr );
193 if ( style < 0 )
194 style = findItemCB ( d-> m_font_style_list, "Regular" );
195 if ( style < 0 && d-> m_font_style_list-> count ( ) > 0 )
196 style = 0;
197 d-> m_font_style_list-> setCurrentItem ( style );
198 fontStyleClicked ( style );
199
200 int size = findItemCB ( d-> m_font_size_list, sizeStr );
201 if ( size < 0 )
202 size = findItemCB ( d-> m_font_size_list, "10" );
203 if ( size < 0 && d-> m_font_size_list-> count ( ) > 0 )
204 size = 0;
205 d-> m_font_size_list-> setCurrentItem ( size );
206 fontSizeClicked ( size );
207
208 return (( family ) && ( style >= 0 ) && ( size >= 0 ));
209}
210
211/**
212 * This method returns the name, style and size of the currently selected
213 * font or false if no font is selected
214 * @param family The font family will be written there
215 * @param style The style will be written there
216 * @param size The size will be written there
217 * @return success or failure
218 */
219bool OFontSelector::selectedFont ( QString &family, QString &style, int &size )
220{
221 QString dummy;
222 return selectedFont ( family, style, size, dummy );
223}
224
225
226/**
227 * This method does return the font family or QString::null if there is
228 * no font item selected
229 * @return the font family
230 */
231QString OFontSelector::fontFamily ( ) const
232{
233 FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( ));
234
235 return fli ? fli-> family ( ) : QString::null;
236}
237
238/**
239 * This method will return the style of the font or QString::null
240 * @return the style of the font
241 */
242QString OFontSelector::fontStyle ( ) const
243{
244 FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( ));
245 int fst = d-> m_font_style_list-> currentItem ( );
246
247 return ( fli && fst >= 0 ) ? fli-> styles ( ) [fst] : QString::null;
248}
249
250/**
251 * This method will return the font size or 10 if no font size is available
252 */
253int OFontSelector::fontSize ( ) const
254{
255 FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( ));
256 int fsi = d-> m_font_size_list-> currentItem ( );
257
258 return ( fli && fsi >= 0 ) ? fli-> sizes ( ) [fsi] : 10;
259}
260
261/**
262 * returns the charset of the font or QString::null
263 */
264QString OFontSelector::fontCharSet ( ) const
265{
266 FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( ));
267
268 return fli ? d-> m_fdb. charSets ( fli-> family ( )) [0] : QString::null;
269}
270
271/**
272 * Overloaded member function see above
273 * @see selectedFont
274 */
275bool OFontSelector::selectedFont ( QString &family, QString &style, int &size, QString &charset )
276{
277 int ffa = d-> m_font_family_list-> currentItem ( );
278 int fst = d-> m_font_style_list-> currentItem ( );
279 int fsi = d-> m_font_size_list-> currentItem ( );
280
281 FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( ffa );
282
283 if ( fli ) {
284 family = fli-> family ( );
285 style = fst >= 0 ? fli-> styles ( ) [fst] : QString::null;
286 size = fsi >= 0 ? fli-> sizes ( ) [fsi] : 10;
287 charset = d-> m_fdb. charSets ( fli-> family ( )) [0];
288
289 return true;
290 }
291 else
292 return false;
293}
294
295
296
297
298void OFontSelector::loadFonts ( QListBox *list )
299{
300 QStringList f = d-> m_fdb. families ( );
301
302 for ( QStringList::ConstIterator it = f. begin ( ); it != f. end ( ); ++it ) {
303 QValueList <int> ps = d-> m_fdb. pointSizes ( *it );
304
305 if ( d-> m_pointbug ) {
306 for ( QValueList <int>::Iterator it = ps. begin ( ); it != ps. end ( ); it++ )
307 *it /= 10;
308 }
309
310 list-> insertItem ( new FontListItem ( *it, d-> m_fdb. styles ( *it ), ps ));
311 }
312}
313
314void OFontSelector::fontFamilyClicked ( int index )
315{
316 QString oldstyle = d-> m_font_style_list-> currentText ( );
317 QString oldsize = d-> m_font_size_list-> currentText ( );
318
319 FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( index );
320
321 d-> m_font_style_list-> clear ( );
322 d-> m_font_style_list-> insertStringList ( fli-> styles ( ));
323 d-> m_font_style_list-> setEnabled ( !fli-> styles ( ). isEmpty ( ));
324
325 int i;
326
327 i = findItemCB ( d-> m_font_style_list, oldstyle );
328 if ( i < 0 )
329 i = findItemCB ( d-> m_font_style_list, "Regular" );
330 if (( i < 0 ) && ( d-> m_font_style_list-> count ( ) > 0 ))
331 i = 0;
332
333 if ( i >= 0 ) {
334 d-> m_font_style_list-> setCurrentItem ( i );
335 fontStyleClicked ( i );
336 }
337
338 d-> m_font_size_list-> clear ( );
339 QValueList<int> sl = fli-> sizes ( );
340
341 for ( QValueList<int>::Iterator it = sl. begin ( ); it != sl. end ( ); ++it )
342 d-> m_font_size_list-> insertItem ( QString::number ( *it ));
343
344 i = findItemCB ( d-> m_font_size_list, oldsize );
345 if ( i < 0 )
346 i = findItemCB ( d-> m_font_size_list, "10" );
347 if (( i < 0 ) && ( d-> m_font_size_list-> count ( ) > 0 ))
348 i = 0;
349
350 if ( i >= 0 ) {
351 d-> m_font_size_list-> setCurrentItem ( i );
352 fontSizeClicked ( i );
353 }
354 changeFont ( );
355}
356
357void OFontSelector::fontStyleClicked ( int /*index*/ )
358{
359 changeFont ( );
360}
361
362void OFontSelector::fontSizeClicked ( int /*index*/ )
363{
364 changeFont ( );
365}
366
367void OFontSelector::changeFont ( )
368{
369 QFont f = selectedFont ( );
370
371 if ( d-> m_preview )
372 d-> m_preview-> setFont ( f );
373
374 emit fontSelected ( f );
375}
376
377/**
378 * Return the selected font
379 */
380QFont OFontSelector::selectedFont ( )
381{
382 int ffa = d-> m_font_family_list-> currentItem ( );
383 int fst = d-> m_font_style_list-> currentItem ( );
384 int fsi = d-> m_font_size_list-> currentItem ( );
385
386 FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( ffa );
387
388 if ( fli ) {
389 return d-> m_fdb. font ( fli-> family ( ), \
390 fst >= 0 ? fli-> styles ( ) [fst] : QString::null, \
391 fsi >= 0 ? fli-> sizes ( ) [fsi] : 10, \
392 d-> m_fdb. charSets ( fli-> family ( )) [0] );
393 }
394 else
395 return QFont ( );
396}
397
398
399void OFontSelector::resizeEvent ( QResizeEvent *re )
400{
401 if ( d-> m_preview ) {
402 d-> m_preview-> setMinimumHeight ( 1 );
403 d-> m_preview-> setMaximumHeight ( 32767 );
404 }
405
406 QWidget::resizeEvent ( re );
407
408 if ( d-> m_preview )
409 d-> m_preview-> setFixedHeight ( d-> m_preview-> height ( ));
410
411}
diff --git a/noncore/unsupported/libopie/ofontselector.h b/noncore/unsupported/libopie/ofontselector.h
new file mode 100644
index 0000000..b819c45
--- a/dev/null
+++ b/noncore/unsupported/libopie/ofontselector.h
@@ -0,0 +1,96 @@
1/*
2               =. This file is part of the OPIE Project
3             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
4           .>+-=
5 _;:,     .>    :=|. This library is free software; you can
6.> <`_,   >  .   <= redistribute it and/or modify it under
7:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
8.="- .-=="i,     .._ License as published by the Free Software
9 - .   .-<_>     .<> Foundation; either version 2 of the License,
10     ._= =}       : or (at your option) any later version.
11    .%`+i>       _;_.
12    .i_,=:_.      -<s. This library is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
17..}^=.=       =       ; Library General Public License for more
18++=   -.     .`     .: details.
19 :     =  ...= . :.=-
20 -.   .:....=;==+<; You should have received a copy of the GNU
21  -_. . .   )=.  = Library General Public License along with
22    --        :-=` this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation,
24 Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
26
27*/
28
29#ifndef OPIE_FONTSELECTOR_H__
30#define OPIE_FONTSELECTOR_H__
31
32#include <qwidget.h>
33
34class QListBox;
35class OFontSelectorPrivate;
36
37/**
38 * This class lets you chose a Font out of a list of Fonts.
39 * It can show a preview too. This selector will use all available
40 * fonts
41 *
42 *
43 * @short A widget to select a font
44 * @see QWidget
45 * @see QFont
46 * @author Rober Griebl
47 */
48class OFontSelector : public QWidget
49{
50 Q_OBJECT
51
52public:
53 OFontSelector ( bool withpreview, QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
54 virtual ~OFontSelector ( );
55
56 bool selectedFont ( QString &family, QString &style, int &size );
57 bool selectedFont ( QString &family, QString &style, int &size, QString &charset );
58
59 QFont selectedFont ( );
60
61 bool setSelectedFont ( const QFont & );
62 bool setSelectedFont ( const QString &family, const QString &style, int size, const QString &charset = 0 );
63
64 QString fontFamily ( ) const;
65 QString fontStyle ( ) const;
66 int fontSize ( ) const;
67 QString fontCharSet ( ) const;
68
69signals:
70 /**
71 * This signal gets emitted when a font got chosen
72 */
73 void fontSelected ( const QFont & );
74
75protected slots:
76 /** @internal */
77 virtual void fontFamilyClicked ( int );
78 /** @internal */
79 virtual void fontStyleClicked ( int );
80 /** @internal */
81 virtual void fontSizeClicked ( int );
82
83protected:
84 virtual void resizeEvent ( QResizeEvent *re );
85
86private:
87 void loadFonts ( QListBox * );
88
89 void changeFont ( );
90
91private:
92 OFontSelectorPrivate *d;
93};
94
95#endif
96
diff --git a/noncore/unsupported/libopie/oprocctrl.cpp b/noncore/unsupported/libopie/oprocctrl.cpp
new file mode 100644
index 0000000..df8da1e
--- a/dev/null
+++ b/noncore/unsupported/libopie/oprocctrl.cpp
@@ -0,0 +1,267 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19//
20// KPROCESSCONTROLLER -- A helper class for KProcess
21//
22// version 0.3.1, Jan, 8th 1997
23//
24// (C) Christian Czezatke
25// e9025461@student.tuwien.ac.at
26// Ported by Holger Freyther
27//
28
29//#include <config.h>
30
31#include <sys/types.h>
32#include <sys/socket.h>
33
34#include <errno.h>
35#include <fcntl.h>
36#include <stdio.h>
37#include <string.h>
38#include <unistd.h>
39#include <assert.h>
40
41#include <qsocketnotifier.h>
42#include "oprocctrl.h"
43
44OProcessController *OProcessController::theOProcessController = 0;
45
46struct sigaction OProcessController::oldChildHandlerData;
47bool OProcessController::handlerSet = false;
48
49OProcessController::OProcessController()
50{
51 assert( theOProcessController == 0 );
52
53 if (0 > pipe(fd))
54 printf(strerror(errno));
55
56 notifier = new QSocketNotifier(fd[0], QSocketNotifier::Read);
57 notifier->setEnabled(true);
58 QObject::connect(notifier, SIGNAL(activated(int)),
59 this, SLOT(slotDoHousekeeping(int)));
60 connect( &delayedChildrenCleanupTimer, SIGNAL( timeout()),
61 SLOT( delayedChildrenCleanup()));
62
63 theOProcessController = this;
64
65 setupHandlers();
66}
67
68
69void OProcessController::setupHandlers()
70{
71 if( handlerSet )
72 return;
73 struct sigaction act;
74 act.sa_handler=theSigCHLDHandler;
75 sigemptyset(&(act.sa_mask));
76 sigaddset(&(act.sa_mask), SIGCHLD);
77 // Make sure we don't block this signal. gdb tends to do that :-(
78 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0);
79
80 act.sa_flags = SA_NOCLDSTOP;
81
82 // CC: take care of SunOS which automatically restarts interrupted system
83 // calls (and thus does not have SA_RESTART)
84
85#ifdef SA_RESTART
86 act.sa_flags |= SA_RESTART;
87#endif
88
89 sigaction( SIGCHLD, &act, &oldChildHandlerData );
90
91 act.sa_handler=SIG_IGN;
92 sigemptyset(&(act.sa_mask));
93 sigaddset(&(act.sa_mask), SIGPIPE);
94 act.sa_flags = 0;
95 sigaction( SIGPIPE, &act, 0L);
96 handlerSet = true;
97}
98
99void OProcessController::resetHandlers()
100{
101 if( !handlerSet )
102 return;
103 sigaction( SIGCHLD, &oldChildHandlerData, 0 );
104 // there should be no problem with SIGPIPE staying SIG_IGN
105 handlerSet = false;
106}
107
108// block SIGCHLD handler, because it accesses processList
109void OProcessController::addOProcess( OProcess* p )
110{
111 sigset_t newset, oldset;
112 sigemptyset( &newset );
113 sigaddset( &newset, SIGCHLD );
114 sigprocmask( SIG_BLOCK, &newset, &oldset );
115 processList.append( p );
116 sigprocmask( SIG_SETMASK, &oldset, 0 );
117}
118
119void OProcessController::removeOProcess( OProcess* p )
120{
121 sigset_t newset, oldset;
122 sigemptyset( &newset );
123 sigaddset( &newset, SIGCHLD );
124 sigprocmask( SIG_BLOCK, &newset, &oldset );
125 processList.remove( p );
126 sigprocmask( SIG_SETMASK, &oldset, 0 );
127}
128
129//using a struct which contains both the pid and the status makes it easier to write
130//and read the data into the pipe
131//especially this solves a problem which appeared on my box where slotDoHouseKeeping() received
132//only 4 bytes (with some debug output around the write()'s it received all 8 bytes)
133//don't know why this happened, but when writing all 8 bytes at once it works here, aleXXX
134struct waitdata
135{
136 pid_t pid;
137 int status;
138};
139
140void OProcessController::theSigCHLDHandler(int arg)
141{
142 struct waitdata wd;
143// int status;
144// pid_t this_pid;
145 int saved_errno;
146
147 saved_errno = errno;
148 // since waitpid and write change errno, we have to save it and restore it
149 // (Richard Stevens, Advanced programming in the Unix Environment)
150
151 bool found = false;
152 if( theOProcessController != 0 ) {
153 // iterating the list doesn't perform any system call
154 for( QValueList<OProcess*>::ConstIterator it = theOProcessController->processList.begin();
155 it != theOProcessController->processList.end();
156 ++it )
157 {
158 if( !(*it)->isRunning())
159 continue;
160 wd.pid = waitpid( (*it)->pid(), &wd.status, WNOHANG );
161 if ( wd.pid > 0 ) {
162 ::write(theOProcessController->fd[1], &wd, sizeof(wd));
163 found = true;
164 }
165 }
166 }
167 if( !found && oldChildHandlerData.sa_handler != SIG_IGN
168 && oldChildHandlerData.sa_handler != SIG_DFL )
169 oldChildHandlerData.sa_handler( arg ); // call the old handler
170 // handle the rest
171 if( theOProcessController != 0 ) {
172 static const struct waitdata dwd = { 0, 0 }; // delayed waitpid()
173 ::write(theOProcessController->fd[1], &dwd, sizeof(dwd));
174 } else {
175 int dummy;
176 while( waitpid( -1, &dummy, WNOHANG ) > 0 )
177 ;
178 }
179
180 errno = saved_errno;
181}
182
183
184
185void OProcessController::slotDoHousekeeping(int )
186{
187 unsigned int bytes_read = 0;
188 unsigned int errcnt=0;
189 // read pid and status from the pipe.
190 struct waitdata wd;
191 while ((bytes_read < sizeof(wd)) && (errcnt < 50)) {
192 int r = ::read(fd[0], ((char *)&wd) + bytes_read, sizeof(wd) - bytes_read);
193 if (r > 0) bytes_read += r;
194 else if (r < 0) errcnt++;
195 }
196 if (errcnt >= 50) {
197 fprintf(stderr,
198 "Error: Max. error count for pipe read "
199 "exceeded in OProcessController::slotDoHousekeeping\n");
200 return; // it makes no sense to continue here!
201 }
202 if (bytes_read != sizeof(wd)) {
203 fprintf(stderr,
204 "Error: Could not read info from signal handler %d <> %d!\n",
205 bytes_read, sizeof(wd));
206 return; // it makes no sense to continue here!
207 }
208 if (wd.pid==0) { // special case, see delayedChildrenCleanup()
209 delayedChildrenCleanupTimer.start( 1000, true );
210 return;
211 }
212
213 for( QValueList<OProcess*>::ConstIterator it = processList.begin();
214 it != processList.end();
215 ++it ) {
216 OProcess* proc = *it;
217 if (proc->pid() == wd.pid) {
218 // process has exited, so do emit the respective events
219 if (proc->run_mode == OProcess::Block) {
220 // If the reads are done blocking then set the status in proc
221 // but do nothing else because OProcess will perform the other
222 // actions of processHasExited.
223 proc->status = wd.status;
224 proc->runs = false;
225 } else {
226 proc->processHasExited(wd.status);
227 }
228 return;
229 }
230 }
231}
232
233// this is needed e.g. for popen(), which calls waitpid() checking
234// for its forked child, if we did waitpid() directly in the SIGCHLD
235// handler, popen()'s waitpid() call would fail
236void OProcessController::delayedChildrenCleanup()
237{
238 struct waitdata wd;
239 while(( wd.pid = waitpid( -1, &wd.status, WNOHANG ) ) > 0 ) {
240 for( QValueList<OProcess*>::ConstIterator it = processList.begin();
241 it != processList.end();
242 ++it )
243 {
244 if( !(*it)->isRunning() || (*it)->pid() != wd.pid )
245 continue;
246 // it's OProcess, handle it
247 ::write(fd[1], &wd, sizeof(wd));
248 break;
249 }
250 }
251}
252
253OProcessController::~OProcessController()
254{
255 assert( theOProcessController == this );
256 resetHandlers();
257
258 notifier->setEnabled(false);
259
260 close(fd[0]);
261 close(fd[1]);
262
263 delete notifier;
264 theOProcessController = 0;
265}
266
267//#include "kprocctrl.moc"
diff --git a/noncore/unsupported/libopie/oprocctrl.h b/noncore/unsupported/libopie/oprocctrl.h
new file mode 100644
index 0000000..5b39490
--- a/dev/null
+++ b/noncore/unsupported/libopie/oprocctrl.h
@@ -0,0 +1,121 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19//
20// KPROCESSCONTROLLER -- A helper class for KProcess
21//
22// version 0.3.1, Jan 8th 1997
23//
24// (C) Christian Czezatke
25// e9025461@student.tuwien.ac.at
26// Ported by Holger Freyther
27//
28
29#ifndef __KPROCCTRL_H__
30#define __KPROCCTRL_H__
31
32#include <qvaluelist.h>
33#include <qtimer.h>
34
35#include "oprocess.h"
36
37class OProcessControllerPrivate;
38class QSocketNotifier;
39
40/**
41 * @short Used internally by @ref OProcess
42 * @internal
43 * @author Christian Czezakte <e9025461@student.tuwien.ac.at>
44 *
45 * A class for internal use by OProcess only. -- Exactly one instance
46 * of this class is generated by the first instance of OProcess that is
47 * created (a pointer to it gets stored in @ref theOProcessController ).
48 *
49 * This class takes care of the actual (UN*X) signal handling.
50*/
51class OProcessController : public QObject
52{
53 Q_OBJECT
54
55public:
56 OProcessController();
57 ~OProcessController();
58 //CC: WARNING! Destructor Not virtual (but you don't derive classes from this anyhow...)
59
60public:
61
62 /**
63 * Only a single instance of this class is allowed at a time,
64 * and this static variable is used to track the one instance.
65 */
66 static OProcessController *theOProcessController;
67
68 /**
69 * Automatically called upon SIGCHLD.
70 *
71 * Normally you do not need to do anything with this function but
72 * if your application needs to disable SIGCHLD for some time for
73 * reasons beyond your control, you should call this function afterwards
74 * to make sure that no SIGCHLDs where missed.
75 */
76 static void theSigCHLDHandler(int signal);
77 // handler for sigchld
78
79 /**
80 * @internal
81 */
82 static void setupHandlers();
83 /**
84 * @internal
85 */
86 static void resetHandlers();
87 /**
88 * @internal
89 */
90 void addOProcess( OProcess* );
91 /**
92 * @internal
93 */
94 void removeOProcess( OProcess* );
95 public slots:
96 /**
97 * @internal
98 */
99 void slotDoHousekeeping(int socket);
100
101 private slots:
102 void delayedChildrenCleanup();
103private:
104 int fd[2];
105 QSocketNotifier *notifier;
106 static struct sigaction oldChildHandlerData;
107 static bool handlerSet;
108 QValueList<OProcess*> processList;
109 QTimer delayedChildrenCleanupTimer;
110
111 // Disallow assignment and copy-construction
112 OProcessController( const OProcessController& );
113 OProcessController& operator= ( const OProcessController& );
114
115 OProcessControllerPrivate *d;
116};
117
118
119
120#endif
121
diff --git a/noncore/unsupported/libopie/oprocess.cpp b/noncore/unsupported/libopie/oprocess.cpp
new file mode 100644
index 0000000..c19881a
--- a/dev/null
+++ b/noncore/unsupported/libopie/oprocess.cpp
@@ -0,0 +1,925 @@
1/*
2
3 $Id$
4
5 This file is part of the KDE libraries
6 Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at)
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.
22
23*/
24
25
26//
27// KPROCESS -- A class for handling child processes in KDE without
28// having to take care of Un*x specific implementation details
29//
30// version 0.3.1, Jan 8th 1998
31//
32// (C) Christian Czezatke
33// e9025461@student.tuwien.ac.at
34//
35// Changes:
36//
37// March 2nd, 1998: Changed parameter list for KShellProcess:
38// Arguments are now placed in a single string so that
39// <shell> -c <commandstring> is passed to the shell
40// to make the use of "operator<<" consistent with KProcess
41//
42//
43// Ported by Holger Freyther
44// <zekce> Harlekin: oprocess and say it was ported to Qt by the Opie developers an Qt 2
45
46
47
48#include "oprocess.h"
49#define _MAY_INCLUDE_KPROCESSCONTROLLER_
50#include "oprocctrl.h"
51
52//#include <config.h>
53
54#include <qfile.h>
55#include <qsocketnotifier.h>
56
57#include <sys/time.h>
58#include <sys/types.h>
59#include <sys/stat.h>
60#include <sys/socket.h>
61
62#include <errno.h>
63#include <fcntl.h>
64#include <stdlib.h>
65#include <signal.h>
66#include <stdio.h>
67#include <string.h>
68#include <unistd.h>
69#ifdef HAVE_SYS_SELECT_H
70#include <sys/select.h>
71#endif
72#ifdef HAVE_INITGROUPS
73#include <grp.h>
74#endif
75#include <pwd.h>
76
77#include <qapplication.h>
78#include <qmap.h>
79//#include <kdebug.h>
80
81/////////////////////////////
82// public member functions //
83/////////////////////////////
84
85class OProcessPrivate {
86public:
87 OProcessPrivate() : useShell(false) { }
88
89 bool useShell;
90 QMap<QString,QString> env;
91 QString wd;
92 QCString shell;
93};
94
95
96OProcess::OProcess(QObject *parent, const char *name)
97 : QObject(parent, name)
98{
99 init ( );
100}
101
102OProcess::OProcess(const QString &arg0, QObject *parent, const char *name)
103 : QObject(parent, name)
104{
105 init ( );
106 *this << arg0;
107}
108
109OProcess::OProcess(const QStringList &args, QObject *parent, const char *name)
110 : QObject(parent, name)
111{
112 init ( );
113 *this << args;
114}
115
116void OProcess::init ( )
117{
118 run_mode = NotifyOnExit;
119 runs = false;
120 pid_ = 0;
121 status = 0;
122 keepPrivs = false;
123 innot = 0;
124 outnot = 0;
125 errnot = 0;
126 communication = NoCommunication;
127 input_data = 0;
128 input_sent = 0;
129 input_total = 0;
130 d = 0;
131
132 if (0 == OProcessController::theOProcessController) {
133 (void) new OProcessController();
134 CHECK_PTR(OProcessController::theOProcessController);
135 }
136
137 OProcessController::theOProcessController->addOProcess(this);
138 out[0] = out[1] = -1;
139 in[0] = in[1] = -1;
140 err[0] = err[1] = -1;
141}
142
143void
144OProcess::setEnvironment(const QString &name, const QString &value)
145{
146 if (!d)
147 d = new OProcessPrivate;
148 d->env.insert(name, value);
149}
150
151void
152OProcess::setWorkingDirectory(const QString &dir)
153{
154 if (!d)
155 d = new OProcessPrivate;
156 d->wd = dir;
157}
158
159void
160OProcess::setupEnvironment()
161{
162 if (d)
163 {
164 QMap<QString,QString>::Iterator it;
165 for(it = d->env.begin(); it != d->env.end(); ++it)
166 setenv(QFile::encodeName(it.key()).data(),
167 QFile::encodeName(it.data()).data(), 1);
168 if (!d->wd.isEmpty())
169 chdir(QFile::encodeName(d->wd).data());
170 }
171}
172
173void
174OProcess::setRunPrivileged(bool keepPrivileges)
175{
176 keepPrivs = keepPrivileges;
177}
178
179bool
180OProcess::runPrivileged() const
181{
182 return keepPrivs;
183}
184
185
186OProcess::~OProcess()
187{
188 // destroying the OProcess instance sends a SIGKILL to the
189 // child process (if it is running) after removing it from the
190 // list of valid processes (if the process is not started as
191 // "DontCare")
192
193 OProcessController::theOProcessController->removeOProcess(this);
194 // this must happen before we kill the child
195 // TODO: block the signal while removing the current process from the process list
196
197 if (runs && (run_mode != DontCare))
198 kill(SIGKILL);
199
200 // Clean up open fd's and socket notifiers.
201 closeStdin();
202 closeStdout();
203 closeStderr();
204
205 // TODO: restore SIGCHLD and SIGPIPE handler if this is the last OProcess
206 delete d;
207}
208
209void OProcess::detach()
210{
211 OProcessController::theOProcessController->removeOProcess(this);
212
213 runs = false;
214 pid_ = 0;
215
216 // Clean up open fd's and socket notifiers.
217 closeStdin();
218 closeStdout();
219 closeStderr();
220}
221
222bool OProcess::setExecutable(const QString& proc)
223{
224 if (runs) return false;
225
226 if (proc.isEmpty()) return false;
227
228 if (!arguments.isEmpty())
229 arguments.remove(arguments.begin());
230 arguments.prepend(QFile::encodeName(proc));
231
232 return true;
233}
234
235OProcess &OProcess::operator<<(const QStringList& args)
236{
237 QStringList::ConstIterator it = args.begin();
238 for ( ; it != args.end() ; ++it )
239 arguments.append(QFile::encodeName(*it));
240 return *this;
241}
242
243OProcess &OProcess::operator<<(const QCString& arg)
244{
245 return operator<< (arg.data());
246}
247
248OProcess &OProcess::operator<<(const char* arg)
249{
250 arguments.append(arg);
251 return *this;
252}
253
254OProcess &OProcess::operator<<(const QString& arg)
255{
256 arguments.append(QFile::encodeName(arg));
257 return *this;
258}
259
260void OProcess::clearArguments()
261{
262 arguments.clear();
263}
264
265bool OProcess::start(RunMode runmode, Communication comm)
266{
267 uint i;
268 uint n = arguments.count();
269 char **arglist;
270
271 if (runs || (0 == n)) {
272 return false; // cannot start a process that is already running
273 // or if no executable has been assigned
274 }
275 run_mode = runmode;
276 status = 0;
277
278 QCString shellCmd;
279 if (d && d->useShell)
280 {
281 if (d->shell.isEmpty())
282 {
283 qWarning( "Could not find a valid shell" );
284 return false;
285 }
286
287 arglist = static_cast<char **>(malloc( (4)*sizeof(char *)));
288 for (i=0; i < n; i++) {
289 shellCmd += arguments[i];
290 shellCmd += " "; // CC: to separate the arguments
291 }
292
293 arglist[0] = d->shell.data();
294 arglist[1] = (char *) "-c";
295 arglist[2] = shellCmd.data();
296 arglist[3] = 0;
297 }
298 else
299 {
300 arglist = static_cast<char **>(malloc( (n+1)*sizeof(char *)));
301 for (i=0; i < n; i++)
302 arglist[i] = arguments[i].data();
303 arglist[n]= 0;
304 }
305
306 if (!setupCommunication(comm))
307 qWarning( "Could not setup Communication!");
308
309 // We do this in the parent because if we do it in the child process
310 // gdb gets confused when the application runs from gdb.
311 uid_t uid = getuid();
312 gid_t gid = getgid();
313#ifdef HAVE_INITGROUPS
314 struct passwd *pw = getpwuid(uid);
315#endif
316
317 int fd[2];
318 if (0 > pipe(fd))
319 {
320 fd[0] = fd[1] = 0; // Pipe failed.. continue
321 }
322
323 runs = true;
324
325 QApplication::flushX();
326
327 // WABA: Note that we use fork() and not vfork() because
328 // vfork() has unclear semantics and is not standardized.
329 pid_ = fork();
330
331 if (0 == pid_) {
332 if (fd[0])
333 close(fd[0]);
334 if (!runPrivileged())
335 {
336 setgid(gid);
337#if defined( HAVE_INITGROUPS)
338 if(pw)
339 initgroups(pw->pw_name, pw->pw_gid);
340#endif
341 setuid(uid);
342 }
343 // The child process
344 if(!commSetupDoneC())
345 qWarning( "Could not finish comm setup in child!" );
346
347 setupEnvironment();
348
349 // Matthias
350 if (run_mode == DontCare)
351 setpgid(0,0);
352 // restore default SIGPIPE handler (Harri)
353 struct sigaction act;
354 sigemptyset(&(act.sa_mask));
355 sigaddset(&(act.sa_mask), SIGPIPE);
356 act.sa_handler = SIG_DFL;
357 act.sa_flags = 0;
358 sigaction(SIGPIPE, &act, 0L);
359
360 // We set the close on exec flag.
361 // Closing of fd[1] indicates that the execvp succeeded!
362 if (fd[1])
363 fcntl(fd[1], F_SETFD, FD_CLOEXEC);
364 execvp(arglist[0], arglist);
365 char resultByte = 1;
366 if (fd[1])
367 write(fd[1], &resultByte, 1);
368 _exit(-1);
369 } else if (-1 == pid_) {
370 // forking failed
371
372 runs = false;
373 free(arglist);
374 return false;
375 } else {
376 if (fd[1])
377 close(fd[1]);
378 // the parent continues here
379
380 // Discard any data for stdin that might still be there
381 input_data = 0;
382
383 // Check whether client could be started.
384 if (fd[0]) for(;;)
385 {
386 char resultByte;
387 int n = ::read(fd[0], &resultByte, 1);
388 if (n == 1)
389 {
390 // Error
391 runs = false;
392 close(fd[0]);
393 free(arglist);
394 pid_ = 0;
395 return false;
396 }
397 if (n == -1)
398 {
399 if ((errno == ECHILD) || (errno == EINTR))
400 continue; // Ignore
401 }
402 break; // success
403 }
404 if (fd[0])
405 close(fd[0]);
406
407 if (!commSetupDoneP()) // finish communication socket setup for the parent
408 qWarning( "Could not finish comm setup in parent!" );
409
410 if (run_mode == Block) {
411 commClose();
412
413 // The SIGCHLD handler of the process controller will catch
414 // the exit and set the status
415 while(runs)
416 {
417 OProcessController::theOProcessController->
418 slotDoHousekeeping(0);
419 }
420 runs = FALSE;
421 emit processExited(this);
422 }
423 }
424 free(arglist);
425 return true;
426}
427
428
429
430bool OProcess::kill(int signo)
431{
432 bool rv=false;
433
434 if (0 != pid_)
435 rv= (-1 != ::kill(pid_, signo));
436 // probably store errno somewhere...
437 return rv;
438}
439
440
441
442bool OProcess::isRunning() const
443{
444 return runs;
445}
446
447
448
449pid_t OProcess::pid() const
450{
451 return pid_;
452}
453
454
455
456bool OProcess::normalExit() const
457{
458 int _status = status;
459 return (pid_ != 0) && (!runs) && (WIFEXITED((_status)));
460}
461
462
463
464int OProcess::exitStatus() const
465{
466 int _status = status;
467 return WEXITSTATUS((_status));
468}
469
470
471
472bool OProcess::writeStdin(const char *buffer, int buflen)
473{
474 bool rv;
475
476 // if there is still data pending, writing new data
477 // to stdout is not allowed (since it could also confuse
478 // kprocess...
479 if (0 != input_data)
480 return false;
481
482 if (runs && (communication & Stdin)) {
483 input_data = buffer;
484 input_sent = 0;
485 input_total = buflen;
486 slotSendData(0);
487 innot->setEnabled(true);
488 rv = true;
489 } else
490 rv = false;
491 return rv;
492}
493
494void OProcess::flushStdin ( )
495{
496 if ( !input_data || ( input_sent == input_total ))
497 return;
498
499 int d1, d2;
500
501 do {
502 d1 = input_total - input_sent;
503 slotSendData ( 0 );
504 d2 = input_total - input_sent;
505 } while ( d2 <= d1 );
506}
507
508void OProcess::suspend()
509{
510 if ((communication & Stdout) && outnot)
511 outnot->setEnabled(false);
512}
513
514void OProcess::resume()
515{
516 if ((communication & Stdout) && outnot)
517 outnot->setEnabled(true);
518}
519
520bool OProcess::closeStdin()
521{
522 bool rv;
523
524 if (communication & Stdin) {
525 communication = (Communication) (communication & ~Stdin);
526 delete innot;
527 innot = 0;
528 close(in[1]);
529 rv = true;
530 } else
531 rv = false;
532 return rv;
533}
534
535bool OProcess::closeStdout()
536{
537 bool rv;
538
539 if (communication & Stdout) {
540 communication = (Communication) (communication & ~Stdout);
541 delete outnot;
542 outnot = 0;
543 close(out[0]);
544 rv = true;
545 } else
546 rv = false;
547 return rv;
548}
549
550bool OProcess::closeStderr()
551{
552 bool rv;
553
554 if (communication & Stderr) {
555 communication = static_cast<Communication>(communication & ~Stderr);
556 delete errnot;
557 errnot = 0;
558 close(err[0]);
559 rv = true;
560 } else
561 rv = false;
562 return rv;
563}
564
565
566/////////////////////////////
567// protected slots //
568/////////////////////////////
569
570
571
572void OProcess::slotChildOutput(int fdno)
573{
574 if (!childOutput(fdno))
575 closeStdout();
576}
577
578
579void OProcess::slotChildError(int fdno)
580{
581 if (!childError(fdno))
582 closeStderr();
583}
584
585
586void OProcess::slotSendData(int)
587{
588 if (input_sent == input_total) {
589 innot->setEnabled(false);
590 input_data = 0;
591 emit wroteStdin(this);
592 } else
593 input_sent += ::write(in[1], input_data+input_sent, input_total-input_sent);
594}
595
596
597
598//////////////////////////////
599// private member functions //
600//////////////////////////////
601
602
603
604void OProcess::processHasExited(int state)
605{
606 if (runs)
607 {
608 runs = false;
609 status = state;
610
611 commClose(); // cleanup communication sockets
612
613 // also emit a signal if the process was run Blocking
614 if (DontCare != run_mode)
615 {
616 emit processExited(this);
617 }
618 }
619}
620
621
622
623int OProcess::childOutput(int fdno)
624{
625 if (communication & NoRead) {
626 int len = -1;
627 emit receivedStdout(fdno, len);
628 errno = 0; // Make sure errno doesn't read "EAGAIN"
629 return len;
630 }
631 else
632 {
633 char buffer[1024];
634 int len;
635
636 len = ::read(fdno, buffer, 1024);
637
638 if ( 0 < len) {
639 emit receivedStdout(this, buffer, len);
640 }
641 return len;
642 }
643}
644
645
646
647int OProcess::childError(int fdno)
648{
649 char buffer[1024];
650 int len;
651
652 len = ::read(fdno, buffer, 1024);
653
654 if ( 0 < len)
655 emit receivedStderr(this, buffer, len);
656 return len;
657}
658
659
660
661int OProcess::setupCommunication(Communication comm)
662{
663 int ok;
664
665 communication = comm;
666
667 ok = 1;
668 if (comm & Stdin)
669 ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, in) >= 0;
670
671 if (comm & Stdout)
672 ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, out) >= 0;
673
674 if (comm & Stderr)
675 ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, err) >= 0;
676
677 return ok;
678}
679
680
681
682int OProcess::commSetupDoneP()
683{
684 int ok = 1;
685
686 if (communication != NoCommunication) {
687 if (communication & Stdin)
688 close(in[0]);
689 if (communication & Stdout)
690 close(out[1]);
691 if (communication & Stderr)
692 close(err[1]);
693
694 // Don't create socket notifiers and set the sockets non-blocking if
695 // blocking is requested.
696 if (run_mode == Block) return ok;
697
698 if (communication & Stdin) {
699// ok &= (-1 != fcntl(in[1], F_SETFL, O_NONBLOCK));
700 innot = new QSocketNotifier(in[1], QSocketNotifier::Write, this);
701 CHECK_PTR(innot);
702 innot->setEnabled(false); // will be enabled when data has to be sent
703 QObject::connect(innot, SIGNAL(activated(int)),
704 this, SLOT(slotSendData(int)));
705 }
706
707 if (communication & Stdout) {
708// ok &= (-1 != fcntl(out[0], F_SETFL, O_NONBLOCK));
709 outnot = new QSocketNotifier(out[0], QSocketNotifier::Read, this);
710 CHECK_PTR(outnot);
711 QObject::connect(outnot, SIGNAL(activated(int)),
712 this, SLOT(slotChildOutput(int)));
713 if (communication & NoRead)
714 suspend();
715 }
716
717 if (communication & Stderr) {
718// ok &= (-1 != fcntl(err[0], F_SETFL, O_NONBLOCK));
719 errnot = new QSocketNotifier(err[0], QSocketNotifier::Read, this );
720 CHECK_PTR(errnot);
721 QObject::connect(errnot, SIGNAL(activated(int)),
722 this, SLOT(slotChildError(int)));
723 }
724 }
725 return ok;
726}
727
728
729
730int OProcess::commSetupDoneC()
731{
732 int ok = 1;
733 struct linger so;
734 memset(&so, 0, sizeof(so));
735
736 if (communication & Stdin)
737 close(in[1]);
738 if (communication & Stdout)
739 close(out[0]);
740 if (communication & Stderr)
741 close(err[0]);
742
743 if (communication & Stdin)
744 ok &= dup2(in[0], STDIN_FILENO) != -1;
745 else {
746 int null_fd = open( "/dev/null", O_RDONLY );
747 ok &= dup2( null_fd, STDIN_FILENO ) != -1;
748 close( null_fd );
749 }
750 if (communication & Stdout) {
751 ok &= dup2(out[1], STDOUT_FILENO) != -1;
752 ok &= !setsockopt(out[1], SOL_SOCKET, SO_LINGER, (char*)&so, sizeof(so));
753 }
754 else {
755 int null_fd = open( "/dev/null", O_WRONLY );
756 ok &= dup2( null_fd, STDOUT_FILENO ) != -1;
757 close( null_fd );
758 }
759 if (communication & Stderr) {
760 ok &= dup2(err[1], STDERR_FILENO) != -1;
761 ok &= !setsockopt(err[1], SOL_SOCKET, SO_LINGER, reinterpret_cast<char *>(&so), sizeof(so));
762 }
763 else {
764 int null_fd = open( "/dev/null", O_WRONLY );
765 ok &= dup2( null_fd, STDERR_FILENO ) != -1;
766 close( null_fd );
767 }
768 return ok;
769}
770
771
772
773void OProcess::commClose()
774{
775 if (NoCommunication != communication) {
776 bool b_in = (communication & Stdin);
777 bool b_out = (communication & Stdout);
778 bool b_err = (communication & Stderr);
779 if (b_in)
780 delete innot;
781
782 if (b_out || b_err) {
783 // If both channels are being read we need to make sure that one socket buffer
784 // doesn't fill up whilst we are waiting for data on the other (causing a deadlock).
785 // Hence we need to use select.
786
787 // Once one or other of the channels has reached EOF (or given an error) go back
788 // to the usual mechanism.
789
790 int fds_ready = 1;
791 fd_set rfds;
792
793 int max_fd = 0;
794 if (b_out) {
795 fcntl(out[0], F_SETFL, O_NONBLOCK);
796 if (out[0] > max_fd)
797 max_fd = out[0];
798 delete outnot;
799 outnot = 0;
800 }
801 if (b_err) {
802 fcntl(err[0], F_SETFL, O_NONBLOCK);
803 if (err[0] > max_fd)
804 max_fd = err[0];
805 delete errnot;
806 errnot = 0;
807 }
808
809
810 while (b_out || b_err) {
811 // * If the process is still running we block until we
812 // receive data. (p_timeout = 0, no timeout)
813 // * If the process has already exited, we only check
814 // the available data, we don't wait for more.
815 // (p_timeout = &timeout, timeout immediately)
816 struct timeval timeout;
817 timeout.tv_sec = 0;
818 timeout.tv_usec = 0;
819 struct timeval *p_timeout = runs ? 0 : &timeout;
820
821 FD_ZERO(&rfds);
822 if (b_out)
823 FD_SET(out[0], &rfds);
824
825 if (b_err)
826 FD_SET(err[0], &rfds);
827
828 fds_ready = select(max_fd+1, &rfds, 0, 0, p_timeout);
829 if (fds_ready <= 0) break;
830
831 if (b_out && FD_ISSET(out[0], &rfds)) {
832 int ret = 1;
833 while (ret > 0) ret = childOutput(out[0]);
834 if ((ret == -1 && errno != EAGAIN) || ret == 0)
835 b_out = false;
836 }
837
838 if (b_err && FD_ISSET(err[0], &rfds)) {
839 int ret = 1;
840 while (ret > 0) ret = childError(err[0]);
841 if ((ret == -1 && errno != EAGAIN) || ret == 0)
842 b_err = false;
843 }
844 }
845 }
846
847 if (b_in) {
848 communication = (Communication) (communication & ~Stdin);
849 close(in[1]);
850 }
851 if (b_out) {
852 communication = (Communication) (communication & ~Stdout);
853 close(out[0]);
854 }
855 if (b_err) {
856 communication = (Communication) (communication & ~Stderr);
857 close(err[0]);
858 }
859 }
860}
861
862void OProcess::setUseShell(bool useShell, const char *shell)
863{
864 if (!d)
865 d = new OProcessPrivate;
866 d->useShell = useShell;
867 d->shell = shell;
868 if (d->shell.isEmpty())
869 d->shell = searchShell();
870}
871
872QString OProcess::quote(const QString &arg)
873{
874 QString res = arg;
875 res.replace(QRegExp(QString::fromLatin1("\'")),
876 QString::fromLatin1("'\"'\"'"));
877 res.prepend('\'');
878 res.append('\'');
879 return res;
880}
881
882QCString OProcess::searchShell()
883{
884 QCString tmpShell = QCString(getenv("SHELL")).stripWhiteSpace();
885 if (!isExecutable(tmpShell))
886 {
887 tmpShell = "/bin/sh";
888 }
889
890 return tmpShell;
891}
892
893bool OProcess::isExecutable(const QCString &filename)
894{
895 struct stat fileinfo;
896
897 if (filename.isEmpty()) return false;
898
899 // CC: we've got a valid filename, now let's see whether we can execute that file
900
901 if (-1 == stat(filename.data(), &fileinfo)) return false;
902 // CC: return false if the file does not exist
903
904 // CC: anyway, we cannot execute directories, block/character devices, fifos or sockets
905 if ( (S_ISDIR(fileinfo.st_mode)) ||
906 (S_ISCHR(fileinfo.st_mode)) ||
907 (S_ISBLK(fileinfo.st_mode)) ||
908#ifdef S_ISSOCK
909 // CC: SYSVR4 systems don't have that macro
910 (S_ISSOCK(fileinfo.st_mode)) ||
911#endif
912 (S_ISFIFO(fileinfo.st_mode)) ||
913 (S_ISDIR(fileinfo.st_mode)) ) {
914 return false;
915 }
916
917 // CC: now check for permission to execute the file
918 if (access(filename.data(), X_OK) != 0) return false;
919
920 // CC: we've passed all the tests...
921 return true;
922}
923
924
925
diff --git a/noncore/unsupported/libopie/oprocess.h b/noncore/unsupported/libopie/oprocess.h
new file mode 100644
index 0000000..af7cddb
--- a/dev/null
+++ b/noncore/unsupported/libopie/oprocess.h
@@ -0,0 +1,747 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19//
20// KPROCESS -- A class for handling child processes in KDE without
21// having to take care of Un*x specific implementation details
22//
23// version 0.3.1, Jan 8th 1998
24//
25// (C) Christian Czezatke
26// e9025461@student.tuwien.ac.at
27// Ported by Holger Freyther to the Open Palmtop Integrated Environment
28//
29
30#ifndef __kprocess_h__
31#define __kprocess_h__
32
33#include <sys/types.h> // for pid_t
34#include <sys/wait.h>
35#include <signal.h>
36#include <unistd.h>
37#include <qvaluelist.h>
38#include <qcstring.h>
39#include <qobject.h>
40
41class QSocketNotifier;
42class OProcessPrivate;
43
44/**
45 * Child process invocation, monitoring and control.
46 *
47 * @sect General usage and features
48 *
49 *This class allows a KDE and OPIE application to start child processes without having
50 *to worry about UN*X signal handling issues and zombie process reaping.
51 *
52 *@see KProcIO
53 *
54 *Basically, this class distinguishes three different ways of running
55 *child processes:
56 *
57 *@li OProcess::DontCare -- The child process is invoked and both the child
58 *process and the parent process continue concurrently.
59 *
60 *Starting a DontCare child process means that the application is
61 *not interested in any notification to determine whether the
62 *child process has already exited or not.
63 *
64 *@li OProcess::NotifyOnExit -- The child process is invoked and both the
65 *child and the parent process run concurrently.
66 *
67 *When the child process exits, the OProcess instance
68 *corresponding to it emits the Qt signal @ref processExited().
69 *
70 *Since this signal is @em not emitted from within a UN*X
71 *signal handler, arbitrary function calls can be made.
72 *
73 *Be aware: When the OProcess objects gets destructed, the child
74 *process will be killed if it is still running!
75 *This means in particular, that you cannot use a OProcess on the stack
76 *with OProcess::NotifyOnExit.
77 *
78 *@li OProcess::Block -- The child process starts and the parent process
79 *is suspended until the child process exits. (@em Really not recommended
80 *for programs with a GUI.)
81 *
82 *OProcess also provides several functions for determining the exit status
83 *and the pid of the child process it represents.
84 *
85 *Furthermore it is possible to supply command-line arguments to the process
86 *in a clean fashion (no null -- terminated stringlists and such...)
87 *
88 *A small usage example:
89 *<pre>
90 *OProcess *proc = new OProcess;
91 *
92 **proc << "my_executable";
93 **proc << "These" << "are" << "the" << "command" << "line" << "args";
94 *QApplication::connect(proc, SIGNAL(processExited(OProcess *)),
95 * pointer_to_my_object, SLOT(my_objects_slot(OProcess *)));
96 *proc->start();
97 *</pre>
98 *
99 *This will start "my_executable" with the commandline arguments "These"...
100 *
101 *When the child process exits, the respective Qt signal will be emitted.
102 *
103 *@sect Communication with the child process
104 *
105 *OProcess supports communication with the child process through
106 *stdin/stdout/stderr.
107 *
108 *The following functions are provided for getting data from the child
109 *process or sending data to the child's stdin (For more information,
110 *have a look at the documentation of each function):
111 *
112 *@li bool @ref writeStdin(char *buffer, int buflen);
113 *@li -- Transmit data to the child process's stdin.
114 *
115 *@li bool @ref closeStdin();
116 *@li -- Closes the child process's stdin (which causes it to see an feof(stdin)).
117 *Returns false if you try to close stdin for a process that has been started
118 *without a communication channel to stdin.
119 *
120 *@li bool @ref closeStdout();
121 *@li -- Closes the child process's stdout.
122 *Returns false if you try to close stdout for a process that has been started
123 *without a communication channel to stdout.
124 *
125 *@li bool @ref closeStderr();
126 *@li -- Closes the child process's stderr.
127 *Returns false if you try to close stderr for a process that has been started
128 *without a communication channel to stderr.
129 *
130 *
131 *@sect QT signals:
132 *
133 *@li void @ref receivedStdout(OProcess *proc, char *buffer, int buflen);
134 *@li void @ref receivedStderr(OProcess *proc, char *buffer, int buflen);
135 *@li -- Indicates that new data has arrived from either the
136 *child process's stdout or stderr.
137 *
138 *@li void @ref wroteStdin(OProcess *proc);
139 *@li -- Indicates that all data that has been sent to the child process
140 *by a prior call to @ref writeStdin() has actually been transmitted to the
141 *client .
142 *
143 *@author Christian Czezakte e9025461@student.tuwien.ac.at
144 *
145 *
146 **/
147class OProcess : public QObject
148{
149 Q_OBJECT
150
151public:
152
153 /**
154 * Modes in which the communication channel can be opened.
155 *
156 * If communication for more than one channel is required,
157 * the values have to be or'ed together, for example to get
158 * communication with stdout as well as with stdin, you would
159 * specify @p Stdin @p | @p Stdout
160 *
161 * If @p NoRead is specified in conjunction with @p Stdout,
162 * no data is actually read from @p Stdout but only
163 * the signal @ref childOutput(int fd) is emitted.
164 */
165 enum Communication { NoCommunication = 0, Stdin = 1, Stdout = 2, Stderr = 4,
166 AllOutput = 6, All = 7,
167 NoRead };
168
169 /**
170 * Run-modes for a child process.
171 */
172 enum RunMode {
173 /**
174 * The application does not receive notifications from the subprocess when
175 * it is finished or aborted.
176 */
177 DontCare,
178 /**
179 * The application is notified when the subprocess dies.
180 */
181 NotifyOnExit,
182 /**
183 * The application is suspended until the started process is finished.
184 */
185 Block };
186
187 /**
188 * Constructor
189 */
190 OProcess(QObject *parent = 0, const char *name = 0);
191 /**
192 * Constructor
193 */
194 OProcess(const QString &arg0, QObject *parent = 0, const char *name = 0);
195 /**
196 * Constructor
197 */
198 OProcess(const QStringList &args, QObject *parent = 0, const char *name = 0);
199
200 /**
201 *Destructor:
202 *
203 * If the process is running when the destructor for this class
204 * is called, the child process is killed with a SIGKILL, but
205 * only if the run mode is not of type @p DontCare.
206 * Processes started as @p DontCare keep running anyway.
207 */
208 virtual ~OProcess();
209
210 /**
211 @deprecated
212
213 The use of this function is now deprecated. -- Please use the
214 "operator<<" instead of "setExecutable".
215
216 Sets the executable to be started with this OProcess object.
217 Returns false if the process is currently running (in that
218 case the executable remains unchanged.)
219
220 @see operator<<
221
222 */
223 bool setExecutable(const QString& proc);
224
225
226 /**
227 * Sets the executable and the command line argument list for this process.
228 *
229 * For example, doing an "ls -l /usr/local/bin" can be achieved by:
230 * <pre>
231 * OProcess p;
232 * ...
233 * p << "ls" << "-l" << "/usr/local/bin"
234 * </pre>
235 *
236 **/
237 OProcess &operator<<(const QString& arg);
238 /**
239 * Similar to previous method, takes a char *, supposed to be in locale 8 bit already.
240 */
241 OProcess &operator<<(const char * arg);
242 /**
243 * Similar to previous method, takes a QCString, supposed to be in locale 8 bit already.
244 */
245 OProcess &operator<<(const QCString & arg);
246
247 /**
248 * Sets the executable and the command line argument list for this process,
249 * in a single method call, or add a list of arguments.
250 **/
251 OProcess &operator<<(const QStringList& args);
252
253 /**
254 * Clear a command line argument list that has been set by using
255 * the "operator<<".
256 */
257 void clearArguments();
258
259 /**
260 * Starts the process.
261 * For a detailed description of the
262 * various run modes and communication semantics, have a look at the
263 * general description of the OProcess class.
264 *
265 * The following problems could cause this function to
266 * return false:
267 *
268 * @li The process is already running.
269 * @li The command line argument list is empty.
270 * @li The starting of the process failed (could not fork).
271 * @li The executable was not found.
272 *
273 * @param comm Specifies which communication links should be
274 * established to the child process (stdin/stdout/stderr). By default,
275 * no communication takes place and the respective communication
276 * signals will never get emitted.
277 *
278 * @return true on success, false on error
279 * (see above for error conditions)
280 **/
281 virtual bool start(RunMode runmode = NotifyOnExit,
282 Communication comm = NoCommunication);
283
284 /**
285 * Stop the process (by sending it a signal).
286 *
287 * @param signoThe signal to send. The default is SIGTERM.
288 * @return @p true if the signal was delivered successfully.
289 */
290 virtual bool kill(int signo = SIGTERM);
291
292 /**
293 @return @p true if the process is (still) considered to be running
294 */
295 bool isRunning() const;
296
297 /** Returns the process id of the process.
298 *
299 * If it is called after
300 * the process has exited, it returns the process id of the last
301 * child process that was created by this instance of OProcess.
302 *
303 * Calling it before any child process has been started by this
304 * OProcess instance causes pid() to return 0.
305 **/
306 pid_t pid() const;
307
308 /**
309 * Suspend processing of data from stdout of the child process.
310 */
311 void suspend();
312
313 /**
314 * Resume processing of data from stdout of the child process.
315 */
316 void resume();
317
318 /**
319 * @return @p true if the process has already finished and has exited
320 * "voluntarily", ie: it has not been killed by a signal.
321 *
322 * Note that you should check @ref OProcess::exitStatus() to determine
323 * whether the process completed its task successful or not.
324 */
325 bool normalExit() const;
326
327 /**
328 * Returns the exit status of the process.
329 *
330 * Please use
331 * @ref OProcess::normalExit() to check whether the process has exited
332 * cleanly (i.e., @ref OProcess::normalExit() returns @p true) before calling
333 * this function because if the process did not exit normally,
334 * it does not have a valid exit status.
335 */
336 int exitStatus() const;
337
338
339 /**
340 * Transmit data to the child process's stdin.
341 *
342 * OProcess::writeStdin may return false in the following cases:
343 *
344 * @li The process is not currently running.
345 *
346 * @li Communication to stdin has not been requested in the @ref start() call.
347 *
348 * @li Transmission of data to the child process by a previous call to
349 * @ref writeStdin() is still in progress.
350 *
351 * Please note that the data is sent to the client asynchronously,
352 * so when this function returns, the data might not have been
353 * processed by the child process.
354 *
355 * If all the data has been sent to the client, the signal
356 * @ref wroteStdin() will be emitted.
357 *
358 * Please note that you must not free "buffer" or call @ref writeStdin()
359 * again until either a @ref wroteStdin() signal indicates that the
360 * data has been sent or a @ref processHasExited() signal shows that
361 * the child process is no longer alive...
362 **/
363 bool writeStdin(const char *buffer, int buflen);
364
365 void flushStdin();
366
367 /**
368 * This causes the stdin file descriptor of the child process to be
369 * closed indicating an "EOF" to the child.
370 *
371 * @return @p false if no communication to the process's stdin
372 * had been specified in the call to @ref start().
373 */
374 bool closeStdin();
375
376 /**
377 * This causes the stdout file descriptor of the child process to be
378 * closed.
379 *
380 * @return @p false if no communication to the process's stdout
381 * had been specified in the call to @ref start().
382 */
383 bool closeStdout();
384
385 /**
386 * This causes the stderr file descriptor of the child process to be
387 * closed.
388 *
389 * @return @p false if no communication to the process's stderr
390 * had been specified in the call to @ref start().
391 */
392 bool closeStderr();
393
394 /**
395 * Lets you see what your arguments are for debugging.
396 */
397
398 const QValueList<QCString> &args() { return arguments; }
399
400 /**
401 * Controls whether the started process should drop any
402 * setuid/segid privileges or whether it should keep them
403 *
404 * The default is @p false : drop privileges
405 */
406 void setRunPrivileged(bool keepPrivileges);
407
408 /**
409 * Returns whether the started process will drop any
410 * setuid/segid privileges or whether it will keep them
411 */
412 bool runPrivileged() const;
413
414 /**
415 * Modifies the environment of the process to be started.
416 * This function must be called before starting the process.
417 */
418 void setEnvironment(const QString &name, const QString &value);
419
420 /**
421 * Changes the current working directory (CWD) of the process
422 * to be started.
423 * This function must be called before starting the process.
424 */
425 void setWorkingDirectory(const QString &dir);
426
427 /**
428 * Specify whether to start the command via a shell or directly.
429 * The default is to start the command directly.
430 * If @p useShell is true @p shell will be used as shell, or
431 * if shell is empty, the standard shell is used.
432 * @p quote A flag indicating whether to quote the arguments.
433 *
434 * When using a shell, the caller should make sure that all filenames etc.
435 * are properly quoted when passed as argument.
436 * @see quote()
437 */
438 void setUseShell(bool useShell, const char *shell = 0);
439
440 /**
441 * This function can be used to quote an argument string such that
442 * the shell processes it properly. This is e. g. necessary for
443 * user-provided file names which may contain spaces or quotes.
444 * It also prevents expansion of wild cards and environment variables.
445 */
446 static QString quote(const QString &arg);
447
448 /**
449 * Detaches OProcess from child process. All communication is closed.
450 * No exit notification is emitted any more for the child process.
451 * Deleting the OProcess will no longer kill the child process.
452 * Note that the current process remains the parent process of the
453 * child process.
454 */
455 void detach();
456
457
458
459signals:
460
461 /**
462 * Emitted after the process has terminated when
463 * the process was run in the @p NotifyOnExit (==default option to
464 * @ref start()) or the @ref Block mode.
465 **/
466 void processExited(OProcess *proc);
467
468
469 /**
470 * Emitted, when output from the child process has
471 * been received on stdout.
472 *
473 * To actually get
474 * these signals, the respective communication link (stdout/stderr)
475 * has to be turned on in @ref start().
476 *
477 * @param buffer The data received.
478 * @param buflen The number of bytes that are available.
479 *
480 * You should copy the information contained in @p buffer to your private
481 * data structures before returning from this slot.
482 **/
483 void receivedStdout(OProcess *proc, char *buffer, int buflen);
484
485 /**
486 * Emitted when output from the child process has
487 * been received on stdout.
488 *
489 * To actually get these signals, the respective communications link
490 * (stdout/stderr) has to be turned on in @ref start() and the
491 * @p NoRead flag should have been passed.
492 *
493 * You will need to explicitly call resume() after your call to start()
494 * to begin processing data from the child process's stdout. This is
495 * to ensure that this signal is not emitted when no one is connected
496 * to it, otherwise this signal will not be emitted.
497 *
498 * The data still has to be read from file descriptor @p fd.
499 **/
500 void receivedStdout(int fd, int &len);
501
502
503 /**
504 * Emitted, when output from the child process has
505 * been received on stderr.
506 * To actually get
507 * these signals, the respective communication link (stdout/stderr)
508 * has to be turned on in @ref start().
509 *
510 * @param buffer The data received.
511 * @param buflen The number of bytes that are available.
512 *
513 * You should copy the information contained in @p buffer to your private
514 * data structures before returning from this slot.
515 */
516 void receivedStderr(OProcess *proc, char *buffer, int buflen);
517
518 /**
519 * Emitted after all the data that has been
520 * specified by a prior call to @ref writeStdin() has actually been
521 * written to the child process.
522 **/
523 void wroteStdin(OProcess *proc);
524
525
526protected slots:
527
528 /**
529 * This slot gets activated when data from the child's stdout arrives.
530 * It usually calls "childOutput"
531 */
532 void slotChildOutput(int fdno);
533
534 /**
535 * This slot gets activated when data from the child's stderr arrives.
536 * It usually calls "childError"
537 */
538 void slotChildError(int fdno);
539 /*
540 Slot functions for capturing stdout and stderr of the child
541 */
542
543 /**
544 * Called when another bulk of data can be sent to the child's
545 * stdin. If there is no more data to be sent to stdin currently
546 * available, this function must disable the QSocketNotifier "innot".
547 */
548 void slotSendData(int dummy);
549
550protected:
551
552 /**
553 * Sets up the environment according to the data passed via
554 * setEnvironment(...)
555 */
556 void setupEnvironment();
557
558 /**
559 * The list of the process' command line arguments. The first entry
560 * in this list is the executable itself.
561 */
562 QValueList<QCString> arguments;
563 /**
564 * How to run the process (Block, NotifyOnExit, DontCare). You should
565 * not modify this data member directly from derived classes.
566 */
567 RunMode run_mode;
568 /**
569 * true if the process is currently running. You should not
570 * modify this data member directly from derived classes. For
571 * reading the value of this data member, please use "isRunning()"
572 * since "runs" will probably be made private in later versions
573 * of OProcess.
574 */
575 bool runs;
576
577 /**
578 * The PID of the currently running process (see "getPid()").
579 * You should not modify this data member in derived classes.
580 * Please use "getPid()" instead of directly accessing this
581 * member function since it will probably be made private in
582 * later versions of OProcess.
583 */
584 pid_t pid_;
585
586 /**
587 * The process' exit status as returned by "waitpid". You should not
588 * modify the value of this data member from derived classes. You should
589 * rather use @ref exitStatus than accessing this data member directly
590 * since it will probably be made private in further versions of
591 * OProcess.
592 */
593 int status;
594
595
596 /**
597 * See setRunPrivileged()
598 */
599 bool keepPrivs;
600
601 /*
602 Functions for setting up the sockets for communication.
603 setupCommunication
604 -- is called from "start" before "fork"ing.
605 commSetupDoneP
606 -- completes communication socket setup in the parent
607 commSetupDoneC
608 -- completes communication setup in the child process
609 commClose
610 -- frees all allocated communication resources in the parent
611 after the process has exited
612 */
613
614 /**
615 * This function is called from "OProcess::start" right before a "fork" takes
616 * place. According to
617 * the "comm" parameter this function has to initialize the "in", "out" and
618 * "err" data member of OProcess.
619 *
620 * This function should return 0 if setting the needed communication channels
621 * was successful.
622 *
623 * The default implementation is to create UNIX STREAM sockets for the communication,
624 * but you could overload this function and establish a TCP/IP communication for
625 * network communication, for example.
626 */
627 virtual int setupCommunication(Communication comm);
628
629 /**
630 * Called right after a (successful) fork on the parent side. This function
631 * will usually do some communications cleanup, like closing the reading end
632 * of the "stdin" communication channel.
633 *
634 * Furthermore, it must also create the QSocketNotifiers "innot", "outnot" and
635 * "errnot" and connect their Qt slots to the respective OProcess member functions.
636 *
637 * For a more detailed explanation, it is best to have a look at the default
638 * implementation of "setupCommunication" in kprocess.cpp.
639 */
640 virtual int commSetupDoneP();
641
642 /**
643 * Called right after a (successful) fork, but before an "exec" on the child
644 * process' side. It usually just closes the unused communication ends of
645 * "in", "out" and "err" (like the writing end of the "in" communication
646 * channel.
647 */
648 virtual int commSetupDoneC();
649
650
651 /**
652 * Immediately called after a process has exited. This function normally
653 * calls commClose to close all open communication channels to this
654 * process and emits the "processExited" signal (if the process was
655 * not running in the "DontCare" mode).
656 */
657 virtual void processHasExited(int state);
658
659 /**
660 * Should clean up the communication links to the child after it has
661 * exited. Should be called from "processHasExited".
662 */
663 virtual void commClose();
664
665
666 /**
667 * the socket descriptors for stdin/stdout/stderr.
668 */
669 int out[2];
670 int in[2];
671 int err[2];
672
673 /**
674 * The socket notifiers for the above socket descriptors.
675 */
676 QSocketNotifier *innot;
677 QSocketNotifier *outnot;
678 QSocketNotifier *errnot;
679
680 /**
681 * Lists the communication links that are activated for the child
682 * process. Should not be modified from derived classes.
683 */
684 Communication communication;
685
686 /**
687 * Called by "slotChildOutput" this function copies data arriving from the
688 * child process's stdout to the respective buffer and emits the signal
689 * "@ref receivedStderr".
690 */
691 int childOutput(int fdno);
692
693 /**
694 * Called by "slotChildOutput" this function copies data arriving from the
695 * child process's stdout to the respective buffer and emits the signal
696 * "@ref receivedStderr"
697 */
698 int childError(int fdno);
699
700 // information about the data that has to be sent to the child:
701
702 const char *input_data; // the buffer holding the data
703 int input_sent; // # of bytes already transmitted
704 int input_total; // total length of input_data
705
706 /**
707 * @ref OProcessController is a friend of OProcess because it has to have
708 * access to various data members.
709 */
710 friend class OProcessController;
711
712
713private:
714 /**
715 * Searches for a valid shell.
716 * Here is the algorithm used for finding an executable shell:
717 *
718 * @li Try the executable pointed to by the "SHELL" environment
719 * variable with white spaces stripped off
720 *
721 * @li If your process runs with uid != euid or gid != egid, a shell
722 * not listed in /etc/shells will not used.
723 *
724 * @li If no valid shell could be found, "/bin/sh" is used as a last resort.
725 */
726 QCString searchShell();
727
728 /**
729 * Used by @ref searchShell in order to find out whether the shell found
730 * is actually executable at all.
731 */
732 bool isExecutable(const QCString &filename);
733
734 // Disallow assignment and copy-construction
735 OProcess( const OProcess& );
736 OProcess& operator= ( const OProcess& );
737
738private:
739 void init ( );
740
741 OProcessPrivate *d;
742};
743
744
745
746#endif
747
diff --git a/noncore/unsupported/libopie/orecurrancebase.ui b/noncore/unsupported/libopie/orecurrancebase.ui
new file mode 100644
index 0000000..baf79d3
--- a/dev/null
+++ b/noncore/unsupported/libopie/orecurrancebase.ui
@@ -0,0 +1,713 @@
1<!DOCTYPE UI><UI>
2<class>ORecurranceBase</class>
3<comment>*********************************************************************
4** Copyright (C) 2000 Trolltech AS. All rights reserved.
5**
6** This file is part of Qtopia Environment.
7**
8** This file may be distributed and/or modified under the terms of the
9** GNU General Public License version 2 as published by the Free Software
10** Foundation and appearing in the file LICENSE.GPL included in the
11** packaging of this file.
12**
13** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
14** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15**
16** See http://www.trolltech.com/gpl/ for GPL licensing information.
17**
18** Contact info@trolltech.com if any conditions of this licensing are
19** not clear to you.
20**
21** $Id$
22**
23*********************************************************************</comment>
24<widget>
25 <class>QDialog</class>
26 <property stdset="1">
27 <name>name</name>
28 <cstring>ORecurranceBase</cstring>
29 </property>
30 <property stdset="1">
31 <name>geometry</name>
32 <rect>
33 <x>0</x>
34 <y>0</y>
35 <width>246</width>
36 <height>309</height>
37 </rect>
38 </property>
39 <property stdset="1">
40 <name>caption</name>
41 <string>Repeating Event </string>
42 </property>
43 <property>
44 <name>layoutMargin</name>
45 </property>
46 <property>
47 <name>layoutSpacing</name>
48 </property>
49 <vbox>
50 <property stdset="1">
51 <name>margin</name>
52 <number>5</number>
53 </property>
54 <property stdset="1">
55 <name>spacing</name>
56 <number>1</number>
57 </property>
58 <widget>
59 <class>QButtonGroup</class>
60 <property stdset="1">
61 <name>name</name>
62 <cstring>fraType</cstring>
63 </property>
64 <property stdset="1">
65 <name>frameShape</name>
66 <enum>NoFrame</enum>
67 </property>
68 <property stdset="1">
69 <name>frameShadow</name>
70 <enum>Sunken</enum>
71 </property>
72 <property stdset="1">
73 <name>title</name>
74 <string></string>
75 </property>
76 <property stdset="1">
77 <name>exclusive</name>
78 <bool>true</bool>
79 </property>
80 <property>
81 <name>layoutMargin</name>
82 </property>
83 <property>
84 <name>layoutSpacing</name>
85 </property>
86 <hbox>
87 <property stdset="1">
88 <name>margin</name>
89 <number>5</number>
90 </property>
91 <property stdset="1">
92 <name>spacing</name>
93 <number>1</number>
94 </property>
95 <widget>
96 <class>QToolButton</class>
97 <property stdset="1">
98 <name>name</name>
99 <cstring>cmdNone</cstring>
100 </property>
101 <property stdset="1">
102 <name>text</name>
103 <string>None</string>
104 </property>
105 <property stdset="1">
106 <name>toggleButton</name>
107 <bool>true</bool>
108 </property>
109 <property stdset="1">
110 <name>toggleButton</name>
111 <bool>true</bool>
112 </property>
113 </widget>
114 <widget>
115 <class>QToolButton</class>
116 <property stdset="1">
117 <name>name</name>
118 <cstring>cmdDay</cstring>
119 </property>
120 <property stdset="1">
121 <name>text</name>
122 <string>Day</string>
123 </property>
124 <property stdset="1">
125 <name>toggleButton</name>
126 <bool>true</bool>
127 </property>
128 <property stdset="1">
129 <name>toggleButton</name>
130 <bool>true</bool>
131 </property>
132 </widget>
133 <widget>
134 <class>QToolButton</class>
135 <property stdset="1">
136 <name>name</name>
137 <cstring>cmdWeek</cstring>
138 </property>
139 <property stdset="1">
140 <name>sizePolicy</name>
141 <sizepolicy>
142 <hsizetype>1</hsizetype>
143 <vsizetype>0</vsizetype>
144 </sizepolicy>
145 </property>
146 <property stdset="1">
147 <name>text</name>
148 <string>Week</string>
149 </property>
150 <property stdset="1">
151 <name>toggleButton</name>
152 <bool>true</bool>
153 </property>
154 <property stdset="1">
155 <name>toggleButton</name>
156 <bool>true</bool>
157 </property>
158 </widget>
159 <widget>
160 <class>QToolButton</class>
161 <property stdset="1">
162 <name>name</name>
163 <cstring>cmdMonth</cstring>
164 </property>
165 <property stdset="1">
166 <name>sizePolicy</name>
167 <sizepolicy>
168 <hsizetype>1</hsizetype>
169 <vsizetype>0</vsizetype>
170 </sizepolicy>
171 </property>
172 <property stdset="1">
173 <name>text</name>
174 <string>Month</string>
175 </property>
176 <property stdset="1">
177 <name>toggleButton</name>
178 <bool>true</bool>
179 </property>
180 <property stdset="1">
181 <name>toggleButton</name>
182 <bool>true</bool>
183 </property>
184 </widget>
185 <widget>
186 <class>QToolButton</class>
187 <property stdset="1">
188 <name>name</name>
189 <cstring>cmdYear</cstring>
190 </property>
191 <property stdset="1">
192 <name>text</name>
193 <string>Year</string>
194 </property>
195 <property stdset="1">
196 <name>toggleButton</name>
197 <bool>true</bool>
198 </property>
199 <property stdset="1">
200 <name>toggleButton</name>
201 <bool>true</bool>
202 </property>
203 </widget>
204 </hbox>
205 </widget>
206 <widget>
207 <class>QLayoutWidget</class>
208 <property stdset="1">
209 <name>name</name>
210 <cstring>Layout4</cstring>
211 </property>
212 <hbox>
213 <property stdset="1">
214 <name>margin</name>
215 <number>0</number>
216 </property>
217 <property stdset="1">
218 <name>spacing</name>
219 <number>6</number>
220 </property>
221 <widget>
222 <class>QLabel</class>
223 <property stdset="1">
224 <name>name</name>
225 <cstring>lblEvery</cstring>
226 </property>
227 <property stdset="1">
228 <name>text</name>
229 <string>Every:</string>
230 </property>
231 </widget>
232 <widget>
233 <class>QSpinBox</class>
234 <property stdset="1">
235 <name>name</name>
236 <cstring>spinFreq</cstring>
237 </property>
238 <property stdset="1">
239 <name>minValue</name>
240 <number>1</number>
241 </property>
242 </widget>
243 <widget>
244 <class>QLabel</class>
245 <property stdset="1">
246 <name>name</name>
247 <cstring>lblFreq</cstring>
248 </property>
249 <property stdset="1">
250 <name>sizePolicy</name>
251 <sizepolicy>
252 <hsizetype>1</hsizetype>
253 <vsizetype>1</vsizetype>
254 </sizepolicy>
255 </property>
256 <property stdset="1">
257 <name>text</name>
258 <string>Frequency</string>
259 </property>
260 </widget>
261 </hbox>
262 </widget>
263 <widget>
264 <class>QLayoutWidget</class>
265 <property stdset="1">
266 <name>name</name>
267 <cstring>Layout8</cstring>
268 </property>
269 <hbox>
270 <property stdset="1">
271 <name>margin</name>
272 <number>0</number>
273 </property>
274 <property stdset="1">
275 <name>spacing</name>
276 <number>6</number>
277 </property>
278 <widget>
279 <class>QLabel</class>
280 <property stdset="1">
281 <name>name</name>
282 <cstring>lblEnd</cstring>
283 </property>
284 <property stdset="1">
285 <name>sizePolicy</name>
286 <sizepolicy>
287 <hsizetype>1</hsizetype>
288 <vsizetype>0</vsizetype>
289 </sizepolicy>
290 </property>
291 <property stdset="1">
292 <name>text</name>
293 <string>End On:</string>
294 </property>
295 </widget>
296 <widget>
297 <class>QToolButton</class>
298 <property stdset="1">
299 <name>name</name>
300 <cstring>cmdEnd</cstring>
301 </property>
302 <property stdset="1">
303 <name>text</name>
304 <string>No End Date</string>
305 </property>
306 </widget>
307 <widget>
308 <class>QCheckBox</class>
309 <property stdset="1">
310 <name>name</name>
311 <cstring>chkNoEnd</cstring>
312 </property>
313 <property stdset="1">
314 <name>text</name>
315 <string>No End Date</string>
316 </property>
317 </widget>
318 </hbox>
319 </widget>
320 <widget>
321 <class>QButtonGroup</class>
322 <property stdset="1">
323 <name>name</name>
324 <cstring>fraExtra</cstring>
325 </property>
326 <property stdset="1">
327 <name>sizePolicy</name>
328 <sizepolicy>
329 <hsizetype>7</hsizetype>
330 <vsizetype>7</vsizetype>
331 </sizepolicy>
332 </property>
333 <property stdset="1">
334 <name>frameShape</name>
335 <enum>Box</enum>
336 </property>
337 <property stdset="1">
338 <name>title</name>
339 <string>Repeat On</string>
340 </property>
341 <property>
342 <name>layoutMargin</name>
343 </property>
344 <property>
345 <name>layoutSpacing</name>
346 </property>
347 <hbox>
348 <property stdset="1">
349 <name>margin</name>
350 <number>5</number>
351 </property>
352 <property stdset="1">
353 <name>spacing</name>
354 <number>1</number>
355 </property>
356 <widget>
357 <class>QToolButton</class>
358 <property stdset="1">
359 <name>name</name>
360 <cstring>cmdExtra1</cstring>
361 </property>
362 <property stdset="1">
363 <name>text</name>
364 <string>Mon</string>
365 </property>
366 <property stdset="1">
367 <name>toggleButton</name>
368 <bool>true</bool>
369 </property>
370 <property stdset="1">
371 <name>toggleButton</name>
372 <bool>true</bool>
373 </property>
374 </widget>
375 <widget>
376 <class>QToolButton</class>
377 <property stdset="1">
378 <name>name</name>
379 <cstring>cmdExtra2</cstring>
380 </property>
381 <property stdset="1">
382 <name>text</name>
383 <string>Tue</string>
384 </property>
385 <property stdset="1">
386 <name>toggleButton</name>
387 <bool>true</bool>
388 </property>
389 <property stdset="1">
390 <name>toggleButton</name>
391 <bool>true</bool>
392 </property>
393 </widget>
394 <widget>
395 <class>QToolButton</class>
396 <property stdset="1">
397 <name>name</name>
398 <cstring>cmdExtra3</cstring>
399 </property>
400 <property stdset="1">
401 <name>text</name>
402 <string>Wed</string>
403 </property>
404 <property stdset="1">
405 <name>toggleButton</name>
406 <bool>true</bool>
407 </property>
408 <property stdset="1">
409 <name>toggleButton</name>
410 <bool>true</bool>
411 </property>
412 </widget>
413 <widget>
414 <class>QToolButton</class>
415 <property stdset="1">
416 <name>name</name>
417 <cstring>cmdExtra4</cstring>
418 </property>
419 <property stdset="1">
420 <name>text</name>
421 <string>Thu</string>
422 </property>
423 <property stdset="1">
424 <name>toggleButton</name>
425 <bool>true</bool>
426 </property>
427 <property stdset="1">
428 <name>toggleButton</name>
429 <bool>true</bool>
430 </property>
431 </widget>
432 <widget>
433 <class>QToolButton</class>
434 <property stdset="1">
435 <name>name</name>
436 <cstring>cmdExtra5</cstring>
437 </property>
438 <property stdset="1">
439 <name>text</name>
440 <string>Fri</string>
441 </property>
442 <property stdset="1">
443 <name>toggleButton</name>
444 <bool>true</bool>
445 </property>
446 <property stdset="1">
447 <name>toggleButton</name>
448 <bool>true</bool>
449 </property>
450 </widget>
451 <widget>
452 <class>QToolButton</class>
453 <property stdset="1">
454 <name>name</name>
455 <cstring>cmdExtra6</cstring>
456 </property>
457 <property stdset="1">
458 <name>text</name>
459 <string>Sat</string>
460 </property>
461 <property stdset="1">
462 <name>toggleButton</name>
463 <bool>true</bool>
464 </property>
465 <property stdset="1">
466 <name>toggleButton</name>
467 <bool>true</bool>
468 </property>
469 </widget>
470 <widget>
471 <class>QToolButton</class>
472 <property stdset="1">
473 <name>name</name>
474 <cstring>cmdExtra7</cstring>
475 </property>
476 <property stdset="1">
477 <name>text</name>
478 <string>Sun</string>
479 </property>
480 <property stdset="1">
481 <name>toggleButton</name>
482 <bool>true</bool>
483 </property>
484 <property stdset="1">
485 <name>toggleButton</name>
486 <bool>true</bool>
487 </property>
488 </widget>
489 </hbox>
490 </widget>
491 <widget>
492 <class>QFrame</class>
493 <property stdset="1">
494 <name>name</name>
495 <cstring>Frame3</cstring>
496 </property>
497 <property stdset="1">
498 <name>sizePolicy</name>
499 <sizepolicy>
500 <hsizetype>7</hsizetype>
501 <vsizetype>7</vsizetype>
502 </sizepolicy>
503 </property>
504 <property stdset="1">
505 <name>frameShape</name>
506 <enum>Box</enum>
507 </property>
508 <property stdset="1">
509 <name>frameShadow</name>
510 <enum>Sunken</enum>
511 </property>
512 <property>
513 <name>layoutMargin</name>
514 </property>
515 <property>
516 <name>layoutSpacing</name>
517 </property>
518 <vbox>
519 <property stdset="1">
520 <name>margin</name>
521 <number>5</number>
522 </property>
523 <property stdset="1">
524 <name>spacing</name>
525 <number>1</number>
526 </property>
527 <widget>
528 <class>QLayoutWidget</class>
529 <property stdset="1">
530 <name>name</name>
531 <cstring>Layout6</cstring>
532 </property>
533 <property>
534 <name>layoutSpacing</name>
535 </property>
536 <hbox>
537 <property stdset="1">
538 <name>margin</name>
539 <number>0</number>
540 </property>
541 <property stdset="1">
542 <name>spacing</name>
543 <number>0</number>
544 </property>
545 <widget>
546 <class>QLabel</class>
547 <property stdset="1">
548 <name>name</name>
549 <cstring>lblRepeat</cstring>
550 </property>
551 <property stdset="1">
552 <name>sizePolicy</name>
553 <sizepolicy>
554 <hsizetype>1</hsizetype>
555 <vsizetype>3</vsizetype>
556 </sizepolicy>
557 </property>
558 <property stdset="1">
559 <name>text</name>
560 <string>Every</string>
561 </property>
562 <property stdset="1">
563 <name>alignment</name>
564 <set>AlignTop|AlignLeft</set>
565 </property>
566 <property>
567 <name>hAlign</name>
568 </property>
569 <property>
570 <name>vAlign</name>
571 </property>
572 </widget>
573 <widget>
574 <class>QLabel</class>
575 <property stdset="1">
576 <name>name</name>
577 <cstring>lblVar1</cstring>
578 </property>
579 <property stdset="1">
580 <name>sizePolicy</name>
581 <sizepolicy>
582 <hsizetype>1</hsizetype>
583 <vsizetype>1</vsizetype>
584 </sizepolicy>
585 </property>
586 <property stdset="1">
587 <name>text</name>
588 <string>Var1</string>
589 </property>
590 <property stdset="1">
591 <name>alignment</name>
592 <set>AlignTop|AlignLeft</set>
593 </property>
594 <property>
595 <name>hAlign</name>
596 </property>
597 <property>
598 <name>vAlign</name>
599 </property>
600 </widget>
601 <widget>
602 <class>QLabel</class>
603 <property stdset="1">
604 <name>name</name>
605 <cstring>lblVar2</cstring>
606 </property>
607 <property stdset="1">
608 <name>sizePolicy</name>
609 <sizepolicy>
610 <hsizetype>4</hsizetype>
611 <vsizetype>1</vsizetype>
612 </sizepolicy>
613 </property>
614 <property stdset="1">
615 <name>text</name>
616 <string>Var 2</string>
617 </property>
618 <property stdset="1">
619 <name>alignment</name>
620 <set>AlignTop|AlignRight</set>
621 </property>
622 <property>
623 <name>hAlign</name>
624 </property>
625 <property>
626 <name>vAlign</name>
627 </property>
628 </widget>
629 </hbox>
630 </widget>
631 <widget>
632 <class>QLabel</class>
633 <property stdset="1">
634 <name>name</name>
635 <cstring>lblWeekVar</cstring>
636 </property>
637 <property stdset="1">
638 <name>sizePolicy</name>
639 <sizepolicy>
640 <hsizetype>1</hsizetype>
641 <vsizetype>7</vsizetype>
642 </sizepolicy>
643 </property>
644 <property stdset="1">
645 <name>text</name>
646 <string>WeekVar</string>
647 </property>
648 <property stdset="1">
649 <name>alignment</name>
650 <set>AlignTop|AlignHCenter</set>
651 </property>
652 <property>
653 <name>hAlign</name>
654 </property>
655 <property>
656 <name>vAlign</name>
657 </property>
658 </widget>
659 </vbox>
660 </widget>
661 </vbox>
662</widget>
663<connections>
664 <connection>
665 <sender>chkNoEnd</sender>
666 <signal>toggled(bool)</signal>
667 <receiver>cmdEnd</receiver>
668 <slot>setDisabled(bool)</slot>
669 </connection>
670 <connection>
671 <sender>chkNoEnd</sender>
672 <signal>toggled(bool)</signal>
673 <receiver>ORecurranceBase</receiver>
674 <slot>slotNoEnd(bool)</slot>
675 </connection>
676 <connection>
677 <sender>spinFreq</sender>
678 <signal>valueChanged(int)</signal>
679 <receiver>lblVar1</receiver>
680 <slot>setNum(int)</slot>
681 </connection>
682 <connection>
683 <sender>spinFreq</sender>
684 <signal>valueChanged(int)</signal>
685 <receiver>ORecurranceBase</receiver>
686 <slot>setupRepeatLabel( int )</slot>
687 </connection>
688 <connection>
689 <sender>fraType</sender>
690 <signal>clicked(int)</signal>
691 <receiver>ORecurranceBase</receiver>
692 <slot>slotSetRType( int )</slot>
693 </connection>
694 <connection>
695 <sender>fraExtra</sender>
696 <signal>clicked(int)</signal>
697 <receiver>ORecurranceBase</receiver>
698 <slot>slotMonthLabel( int )</slot>
699 </connection>
700 <connection>
701 <sender>fraExtra</sender>
702 <signal>clicked(int)</signal>
703 <receiver>ORecurranceBase</receiver>
704 <slot>slotWeekLabel()</slot>
705 </connection>
706 <slot access="public">setupRepeatLabel( const QString &amp; )</slot>
707 <slot access="public">setupRepeatLabel( int )</slot>
708 <slot access="public">slotMonthLabel( int )</slot>
709 <slot access="public">slotNoEnd(bool)</slot>
710 <slot access="public">slotSetRType( int )</slot>
711 <slot access="public">slotWeekLabel()</slot>
712</connections>
713</UI>
diff --git a/noncore/unsupported/libopie/orecurrancewidget.cpp b/noncore/unsupported/libopie/orecurrancewidget.cpp
new file mode 100644
index 0000000..33be269
--- a/dev/null
+++ b/noncore/unsupported/libopie/orecurrancewidget.cpp
@@ -0,0 +1,632 @@
1#include <qapplication.h>
2#include <qlabel.h>
3#include <qspinbox.h>
4
5
6#include "orecurrancewidget.h"
7
8// Global Templates for use in setting up the repeat label...
9// the problem is these strings get initialized before QPEApplication can install the translator -zecke
10namespace {
11QString strDayTemplate;
12QString strYearTemplate;
13QString strMonthDateTemplate;
14QString strMonthDayTemplate;
15QString strWeekTemplate;
16QString dayLabel[7];
17}
18
19/*
20 * static linkage to not polute the symbol table...
21 * The problem is that const and static linkage are resolved prior to installing a translator
22 * leading to that the above strings are translted but to the original we delay the init of these strings...
23 * -zecke
24 */
25static void fillStrings() {
26 strDayTemplate = QObject::tr("Every");
27 strYearTemplate = QObject::tr("%1 %2 every ");
28 strMonthDateTemplate = QObject::tr("The %1 every ");
29 strMonthDayTemplate = QObject::tr("The %1 %2 of every");
30 strWeekTemplate = QObject::tr("Every ");
31 dayLabel[0] = QObject::tr("Monday");
32 dayLabel[1] = QObject::tr("Tuesday");
33 dayLabel[2] = QObject::tr("Wednesday");
34 dayLabel[3] = QObject::tr("Thursday");
35 dayLabel[4] = QObject::tr("Friday");
36 dayLabel[5] = QObject::tr("Saturday");
37 dayLabel[6] = QObject::tr("Sunday");
38}
39
40 static QString numberPlacing( int x );// return the proper word format for
41 // x (1st, 2nd, etc)
42static int week( const QDate &dt ); // what week in the month is dt?
43
44/**
45 * Constructs the Widget
46 * @param startOnMonday Does the week start on monday
47 * @param newStart The start date of the recurrence
48 * @param parent The parent widget
49 * @param name the name of object
50 * @param modal if the dialog should be modal
51 * @param fl Additional window flags
52 */
53ORecurranceWidget::ORecurranceWidget( bool startOnMonday,
54 const QDate& newStart,
55 QWidget* parent,
56 const char* name,
57 bool modal,
58 WFlags fl )
59 : ORecurranceBase( parent, name, modal, fl ),
60 start( newStart ),
61 currInterval( None ),
62 startWeekOnMonday( startOnMonday )
63{
64 if (strDayTemplate.isEmpty() )
65 fillStrings();
66
67 init();
68 fraType->setButton( currInterval );
69 chkNoEnd->setChecked( TRUE );
70 setupNone();
71}
72
73/**
74 * Different constructor
75 * @param startOnMonday Does the week start on monday?
76 * @param rp Already set ORecur object
77 * @param startDate The start date
78 * @param parent The parent widget
79 * @param name The name of the object
80 * @param modal
81 * @param fl The flags for window
82 */
83ORecurranceWidget::ORecurranceWidget( bool startOnMonday,
84 const ORecur& rp, const QDate& startDate,
85 QWidget* parent, const char* name,
86 bool modal, WFlags fl)
87 : ORecurranceBase( parent, name, modal, fl ),
88 start( startDate ),
89 end( rp.endDate() ),
90 startWeekOnMonday( startOnMonday )
91{
92 if (strDayTemplate.isEmpty() )
93 fillStrings();
94 // do some stuff with the repeat pattern
95 init();
96 setRecurrence( rp );
97}
98
99ORecurranceWidget::~ORecurranceWidget() {
100}
101
102/**
103 * set the start date
104 * @param date the new start date
105 */
106void ORecurranceWidget::setStartDate( const QDate& date ) {
107 setRecurrence( recurrence(), date );
108}
109/**
110 * set the recurrence
111 * @param rp The ORecur object with the new recurrence rules
112 */
113void ORecurranceWidget::setRecurrence( const ORecur& rp ) {
114 setRecurrence( rp, start );
115}
116
117/**
118 * overloaded method taking ORecur and a new start date
119 * @param rp Recurrence rule
120 * @param date The new start date
121 */
122void ORecurranceWidget::setRecurrence( const ORecur& rp, const QDate& date ) {
123 start = date;
124 end = rp.endDate();
125 switch ( rp.type() ) {
126 default:
127 case ORecur::NoRepeat:
128 currInterval = None;
129 setupNone();
130 break;
131 case ORecur::Daily:
132 currInterval = Day;
133 setupDaily();
134 break;
135 case ORecur::Weekly:
136 currInterval = Week;
137 setupWeekly();
138 int day, buttons;
139 for ( day = 0x01, buttons = 0; buttons < 7;
140 day = day << 1, buttons++ ) {
141 if ( rp.days() & day ) {
142 if ( startWeekOnMonday )
143 fraExtra->setButton( buttons );
144 else {
145 if ( buttons == 7 )
146 fraExtra->setButton( 0 );
147 else
148 fraExtra->setButton( buttons + 1 );
149 }
150 }
151 }
152 slotWeekLabel();
153 break;
154 case ORecur::MonthlyDay:
155 currInterval = Month;
156 setupMonthly();
157 fraExtra->setButton( 0 );
158 slotMonthLabel( 0 );
159 break;
160 case ORecur::MonthlyDate:
161 currInterval = Month;
162 setupMonthly();
163 fraExtra->setButton( 1 );
164 slotMonthLabel( 1 );
165 break;
166 case ORecur::Yearly:
167 currInterval = Year;
168 setupYearly();
169 break;
170 }
171 fraType->setButton( currInterval );
172 spinFreq->setValue( rp.frequency() );
173 if ( !rp.hasEndDate() ) {
174 cmdEnd->setText( tr("No End Date") );
175 chkNoEnd->setChecked( TRUE );
176 } else
177 cmdEnd->setText( TimeString::shortDate( end ) );
178}
179
180/**
181 * the user selected recurrence rule.
182 * @return The recurrence rule.
183 */
184ORecur ORecurranceWidget::recurrence()const {
185 QListIterator<QToolButton> it( listRTypeButtons );
186 QListIterator<QToolButton> itExtra( listExtra );
187 ORecur rpTmp;
188 int i;
189 for ( i = 0; *it; ++it, i++ ) {
190 if ( (*it)->isOn() ) {
191 switch ( i ) {
192 case None:
193 rpTmp.setType( ORecur::NoRepeat );
194 break;
195 case Day:
196 rpTmp.setType( ORecur::Daily );
197 break;
198 case Week:{
199 rpTmp.setType( ORecur::Weekly );
200 int day;
201 int day2 = 0;
202 for ( day = 1; *itExtra; ++itExtra, day = day << 1 ) {
203 if ( (*itExtra)->isOn() ) {
204 if ( startWeekOnMonday )
205 day2 |= day;
206 else {
207 if ( day == 1 )
208 day2 |= Event::SUN;
209 else
210 day2 |= day >> 1;
211 }
212 }
213 }
214 rpTmp.setDays( day2 );
215 }
216 break;
217 case Month:
218 if ( cmdExtra1->isOn() )
219 rpTmp.setType( ORecur::MonthlyDay );
220 else if ( cmdExtra2->isOn() )
221 rpTmp.setType( ORecur::MonthlyDate );
222 // figure out the montly day...
223 rpTmp.setPosition( week( start ) );
224 break;
225 case Year:
226 rpTmp.setType( ORecur::Yearly );
227 break;
228 }
229 break; // no need to keep looking!
230 }
231 }
232 rpTmp.setFrequency(spinFreq->value() );
233 rpTmp.setHasEndDate( !chkNoEnd->isChecked() );
234 if ( rpTmp.hasEndDate() ) {
235 rpTmp.setEndDate( end );
236 }
237 // timestamp it...
238// rpTmp.setCreateTime( ); current DateTime is already set -zecke
239 return rpTmp;
240}
241
242/**
243 * Return the end date of the recurrence. This is only
244 * valid if the recurrence rule does contain an enddate
245 */
246QDate ORecurranceWidget::endDate()const {
247 return end;
248}
249void ORecurranceWidget::slotSetRType(int rtype) {
250 // now call the right function based on the type...
251 currInterval = static_cast<repeatButtons>(rtype);
252 switch ( currInterval ) {
253 case None:
254 setupNone();
255 break;
256 case Day:
257 setupDaily();
258 break;
259 case Week:
260 setupWeekly();
261 slotWeekLabel();
262 break;
263 case Month:
264 setupMonthly();
265 cmdExtra2->setOn( TRUE );
266 slotMonthLabel( 1 );
267 break;
268 case Year:
269 setupYearly();
270 break;
271 }
272}
273void ORecurranceWidget::endDateChanged(int y, int m, int d) {
274 end.setYMD( y, m, d );
275 if ( end < start )
276 end = start;
277 cmdEnd->setText( TimeString::shortDate( end ) );
278 repeatPicker->setDate( end.year(), end.month(), end.day() );
279}
280void ORecurranceWidget::slotNoEnd( bool unused) {
281 // if the item was toggled, then go ahead and set it to the maximum date
282 if ( unused ) {
283 end.setYMD( 3000, 12, 31 );
284 cmdEnd->setText( tr("No End Date") );
285 } else {
286 end = start;
287 cmdEnd->setText( TimeString::shortDate(end) );
288 }
289}
290void ORecurranceWidget::setupRepeatLabel( const QString& s) {
291 lblVar1->setText( s );
292}
293void ORecurranceWidget::setupRepeatLabel( int x) {
294 // change the spelling based on the value of x
295 QString strVar2;
296
297 if ( x > 1 )
298 lblVar1->show();
299 else
300 lblVar1->hide();
301
302 switch ( currInterval ) {
303 case None:
304 break;
305 case Day:
306 if ( x > 1 )
307 strVar2 = tr( "days" );
308 else
309 strVar2 = tr( "day" );
310 break;
311 case Week:
312 if ( x > 1 )
313 strVar2 = tr( "weeks" );
314 else
315 strVar2 = tr( "week" );
316 break;
317 case Month:
318 if ( x > 1 )
319 strVar2 = tr( "months" );
320 else
321 strVar2 = tr( "month" );
322 break;
323 case Year:
324 if ( x > 1 )
325 strVar2 = tr( "years" );
326 else
327 strVar2 = tr( "year" );
328 break;
329 }
330 if ( !strVar2.isNull() )
331 lblVar2->setText( strVar2 );
332}
333void ORecurranceWidget::slotWeekLabel() {
334 QString str;
335 QListIterator<QToolButton> it( listExtra );
336 unsigned int i;
337 unsigned int keepMe;
338 bool bNeedCarriage = FALSE;
339 // don't do something we'll regret!!!
340 if ( currInterval != Week )
341 return;
342
343 if ( startWeekOnMonday )
344 keepMe = start.dayOfWeek() - 1;
345 else
346 keepMe = start.dayOfWeek() % 7;
347
348 QStringList list;
349 for ( i = 0; *it; ++it, i++ ) {
350 // a crazy check, if you are repeating weekly, the current day
351 // must be selected!!!
352 if ( i == keepMe && !( (*it)->isOn() ) )
353 (*it)->setOn( TRUE );
354 if ( (*it)->isOn() ) {
355 if ( startWeekOnMonday )
356 list.append( dayLabel[i] );
357 else {
358 if ( i == 0 )
359 list.append( dayLabel[6] );
360 else
361 list.append( dayLabel[i - 1] );
362 }
363 }
364 }
365 QStringList::Iterator itStr;
366 for ( i = 0, itStr = list.begin(); itStr != list.end(); ++itStr, i++ ) {
367 if ( i == 3 )
368 bNeedCarriage = TRUE;
369 else
370 bNeedCarriage = FALSE;
371 if ( str.isNull() )
372 str = *itStr;
373 else if ( i == list.count() - 1 ) {
374 if ( i < 2 )
375 str += tr(" and ") + *itStr;
376 else {
377 if ( bNeedCarriage )
378 str += tr( ",\nand " ) + *itStr;
379 else
380 str += tr( ", and " ) + *itStr;
381 }
382 } else {
383 if ( bNeedCarriage )
384 str += ",\n" + *itStr;
385 else
386 str += ", " + *itStr;
387 }
388 }
389 str = str.prepend( tr("on ") );
390
391 lblWeekVar->setText( str );
392}
393void ORecurranceWidget::slotMonthLabel(int type) {
394 QString str;
395 if ( currInterval != Month || type > 1 )
396 return;
397 if ( type == 1 )
398 str = strMonthDateTemplate.arg( numberPlacing(start.day()) );
399 else
400 str = strMonthDayTemplate.arg( numberPlacing(week(start)))
401 .arg( dayLabel[start.dayOfWeek() - 1] );
402 lblRepeat->setText( str );
403}
404void ORecurranceWidget::slotChangeStartOfWeek( bool onMonday ) {
405 startWeekOnMonday = onMonday;
406 // we need to make this unintrusive as possible...
407 int saveSpin = spinFreq->value();
408 char days = 0;
409 int day;
410 QListIterator<QToolButton> itExtra( listExtra );
411 for ( day = 1; *itExtra; ++itExtra, day = day << 1 ) {
412 if ( (*itExtra)->isOn() ) {
413 if ( !startWeekOnMonday )
414 days |= day;
415 else {
416 if ( day == 1 )
417 days |= ORecur::SUN;
418 else
419 days |= day >> 1;
420 }
421 }
422 }
423 setupWeekly();
424 spinFreq->setValue( saveSpin );
425 int buttons;
426 for ( day = 0x01, buttons = 0; buttons < 7;
427 day = day << 1, buttons++ ) {
428 if ( days & day ) {
429 if ( startWeekOnMonday )
430 fraExtra->setButton( buttons );
431 else {
432 if ( buttons == 7 )
433 fraExtra->setButton( 0 );
434 else
435 fraExtra->setButton( buttons + 1 );
436 }
437 }
438 }
439 slotWeekLabel();
440}
441void ORecurranceWidget::setupNone() {
442 lblRepeat->setText( tr("No Repeat") );
443 lblVar1->hide();
444 lblVar2->hide();
445 hideExtras();
446 cmdEnd->hide();
447 lblFreq->hide();
448 lblEvery->hide();
449 lblFreq->hide();
450 spinFreq->hide();
451 lblEnd->hide();
452 lblWeekVar->hide();
453}
454void ORecurranceWidget::setupDaily() {
455 hideExtras();
456 lblWeekVar->hide();
457 spinFreq->setValue( 1 );
458 lblFreq->setText( tr("day(s)") );
459 lblVar2->show();
460 showRepeatStuff();
461 lblRepeat->setText( strDayTemplate );
462 setupRepeatLabel( 1 );
463}
464void ORecurranceWidget::setupWeekly() {
465// reshow the buttons...
466 fraExtra->setTitle( tr("Repeat On") );
467 fraExtra->setExclusive( FALSE );
468 fraExtra->show();
469 if ( startWeekOnMonday ) {
470 cmdExtra1->setText( tr("Mon") );
471 cmdExtra2->setText( tr("Tue") );
472 cmdExtra3->setText( tr("Wed") );
473 cmdExtra4->setText( tr("Thu") );
474 cmdExtra5->setText( tr("Fri") );
475 cmdExtra6->setText( tr("Sat") );
476 cmdExtra7->setText( tr("Sun") );
477 } else {
478 cmdExtra1->setText( tr("Sun") );
479 cmdExtra2->setText( tr("Mon") );
480 cmdExtra3->setText( tr("Tue") );
481 cmdExtra4->setText( tr("Wed") );
482 cmdExtra5->setText( tr("Thu") );
483 cmdExtra6->setText( tr("Fri") );
484 cmdExtra7->setText( tr("Sat") );
485 }
486 // I hope clustering these improve performance....
487 cmdExtra1->setOn( FALSE );
488 cmdExtra2->setOn( FALSE );
489 cmdExtra3->setOn( FALSE );
490 cmdExtra4->setOn( FALSE );
491 cmdExtra5->setOn( FALSE );
492 cmdExtra6->setOn( FALSE );
493 cmdExtra7->setOn( FALSE );
494
495 cmdExtra1->show();
496 cmdExtra2->show();
497 cmdExtra3->show();
498 cmdExtra4->show();
499 cmdExtra5->show();
500 cmdExtra6->show();
501 cmdExtra7->show();
502
503 lblWeekVar->show();
504 spinFreq->setValue( 1 );
505 // might as well set the day too...
506 if ( startWeekOnMonday ) {
507 fraExtra->setButton( start.dayOfWeek() - 1 );
508 } else {
509 fraExtra->setButton( start.dayOfWeek() % 7 );
510 }
511 lblFreq->setText( tr("week(s)") );
512 lblVar2->show();
513 showRepeatStuff();
514 setupRepeatLabel( 1 );
515}
516void ORecurranceWidget::setupMonthly() {
517 hideExtras();
518 lblWeekVar->hide();
519 fraExtra->setTitle( tr("Repeat By") );
520 fraExtra->setExclusive( TRUE );
521 fraExtra->show();
522 cmdExtra1->setText( tr("Day") );
523 cmdExtra1->show();
524 cmdExtra2->setText( tr("Date") );
525 cmdExtra2->show();
526 spinFreq->setValue( 1 );
527 lblFreq->setText( tr("month(s)") );
528 lblVar2->show();
529 showRepeatStuff();
530 setupRepeatLabel( 1 );
531}
532void ORecurranceWidget::setupYearly() {
533hideExtras();
534 lblWeekVar->hide();
535 spinFreq->setValue( 1 );
536 lblFreq->setText( tr("year(s)") );
537 lblFreq->show();
538 lblFreq->show();
539 showRepeatStuff();
540 lblVar2->show();
541 QString strEvery = strYearTemplate.arg( start.monthName(start.month()) ).arg( numberPlacing(start.day()) );
542 lblRepeat->setText( strEvery );
543 setupRepeatLabel( 1 );
544
545}
546void ORecurranceWidget::init() {
547 QPopupMenu *m1 = new QPopupMenu( this );
548 repeatPicker = new DateBookMonth( m1, 0, TRUE );
549 m1->insertItem( repeatPicker );
550 cmdEnd->setPopup( m1 );
551 cmdEnd->setPopupDelay( 0 );
552
553 QObject::connect( repeatPicker, SIGNAL(dateClicked(int,int,int)),
554 this, SLOT(endDateChanged(int,int,int)) );
555 QObject::connect( qApp, SIGNAL(weekChanged(bool)),
556 this, SLOT(slotChangeStartOfWeek(bool)) );
557
558 listRTypeButtons.setAutoDelete( TRUE );
559 listRTypeButtons.append( cmdNone );
560 listRTypeButtons.append( cmdDay );
561 listRTypeButtons.append( cmdWeek );
562 listRTypeButtons.append( cmdMonth );
563 listRTypeButtons.append( cmdYear );
564
565 listExtra.setAutoDelete( TRUE );
566 listExtra.append( cmdExtra1 );
567 listExtra.append( cmdExtra2 );
568 listExtra.append( cmdExtra3 );
569 listExtra.append( cmdExtra4 );
570 listExtra.append( cmdExtra5 );
571 listExtra.append( cmdExtra6 );
572 listExtra.append( cmdExtra7 );
573}
574void ORecurranceWidget::hideExtras() {
575 // hide the extra buttons...
576 fraExtra->hide();
577 chkNoEnd->hide();
578 QListIterator<QToolButton> it( listExtra );
579 for ( ; *it; ++it ) {
580 (*it)->hide();
581 (*it)->setOn( FALSE );
582 }
583}
584void ORecurranceWidget::showRepeatStuff() {
585 cmdEnd->show();
586 chkNoEnd->show();
587 lblFreq->show();
588 lblEvery->show();
589 lblFreq->show();
590 spinFreq->show();
591 lblEnd->show();
592 lblRepeat->setText( tr("Every") );
593}
594
595
596static int week( const QDate &start )
597{
598 // figure out the week...
599 int stop = start.day(),
600 sentinel = start.dayOfWeek(),
601 dayOfWeek = QDate( start.year(), start.month(), 1 ).dayOfWeek(),
602 week = 1,
603 i;
604 for ( i = 1; i < stop; i++ ) {
605 if ( dayOfWeek++ == sentinel )
606 week++;
607 if ( dayOfWeek > 7 )
608 dayOfWeek = 0;
609 }
610 return week;
611}
612
613static QString numberPlacing( int x )
614{
615 // I hope this works in other languages besides english...
616 QString str = QString::number( x );
617 switch ( x % 10 ) {
618 case 1:
619 str += QWidget::tr( "st" );
620 break;
621 case 2:
622 str += QWidget::tr( "nd" );
623 break;
624 case 3:
625 str += QWidget::tr( "rd" );
626 break;
627 default:
628 str += QWidget::tr( "th" );
629 break;
630 }
631 return str;
632}
diff --git a/noncore/unsupported/libopie/orecurrancewidget.h b/noncore/unsupported/libopie/orecurrancewidget.h
new file mode 100644
index 0000000..37a57f0
--- a/dev/null
+++ b/noncore/unsupported/libopie/orecurrancewidget.h
@@ -0,0 +1,93 @@
1/*
2 * GPL and based on the widget from TT
3 */
4
5#ifndef OPIE_RECURRANCE_WIDGET_H
6#define OPIE_RECURRANCE_WIDGET_H
7
8#include <qlist.h>
9#include <qtoolbutton.h>
10#include <qcheckbox.h>
11#include <qdatetime.h>
12#include <qbuttongroup.h>
13
14#include <qpe/datebookmonth.h>
15
16#include "orecurrancebase.h"
17#include <opie/orecur.h>
18
19// FIXME spelling!!!! -zecke
20// FIXME spelling filenames
21
22/**
23 * A widget to let the user select rules for recurrences.
24 * This widget can take care of weekly, monthly, daily and yearly recurrence
25 * It is used inside todolist and datebook.
26 *
27 *
28 * @short Widget of selecting Recurrance
29 * @author Trolltech, Holger Freyther
30 * @version 0.9
31 */
32class ORecurranceWidget : public ORecurranceBase {
33 Q_OBJECT
34public:
35 ORecurranceWidget( bool startOnMonday,
36 const QDate& start, QWidget* parent = 0,
37 const char* name = 0, bool modal = TRUE,
38 WFlags fl = 0 );
39 ORecurranceWidget( bool startOnMonday,
40 const ORecur& rp, const QDate& start,
41 QWidget* parent = 0, const char* name =0,
42 bool modal = TRUE, WFlags = 0 );
43 ~ORecurranceWidget();
44 ORecur recurrence()const;
45 QDate endDate()const;
46
47public slots:
48 void slotSetRType( int );
49 /**
50 * set the new end date
51 */
52 void endDateChanged( int, int, int );
53 /**
54 * enable/disable end date
55 */
56 void slotNoEnd( bool unused );
57 void setStartDate( const QDate& );
58 void setRecurrence( const ORecur& recur, const QDate& start );
59 void setRecurrence( const ORecur& recur );
60
61private slots:
62 void setupRepeatLabel( const QString& );
63 void setupRepeatLabel( int );
64 void slotWeekLabel();
65 void slotMonthLabel( int );
66 void slotChangeStartOfWeek( bool onMonday );
67
68private:
69 void setupNone();
70 void setupDaily();
71 void setupWeekly();
72 void setupMonthly();
73 void setupYearly();
74
75 enum repeatButtons { None, Day, Week, Month, Year };
76 void init();
77 void hideExtras();
78 void showRepeatStuff();
79
80 QList<QToolButton> listRTypeButtons;
81 QList<QToolButton> listExtra;
82 QDate start; // only used in one spot...
83 QDate end;
84 repeatButtons currInterval;
85 bool startWeekOnMonday : 1;
86 DateBookMonth *repeatPicker;
87
88 class Private;
89 Private *d;
90
91};
92
93#endif
diff --git a/noncore/unsupported/libopie/otabbar.cpp b/noncore/unsupported/libopie/otabbar.cpp
new file mode 100644
index 0000000..52621ca
--- a/dev/null
+++ b/noncore/unsupported/libopie/otabbar.cpp
@@ -0,0 +1,81 @@
1/*
2                This file is part of the Opie Project
3
4              Copyright (c) 2002 Dan Williams <williamsdr@acm.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#include "otabbar.h"
33
34OTabBar::OTabBar( QWidget *parent , const char *name )
35 : QTabBar( parent, name )
36{
37}
38
39void OTabBar::paintLabel( QPainter* p, const QRect& br, QTab* t, bool has_focus ) const
40{
41
42 QRect r = br;
43 if ( t->iconset)
44 {
45 QIconSet::Mode mode = (t->enabled && isEnabled()) ? QIconSet::Normal : QIconSet::Disabled;
46 if ( mode == QIconSet::Normal && has_focus ) {
47 mode = QIconSet::Active;
48 }
49 QPixmap pixmap = t->iconset->pixmap( QIconSet::Small, mode );
50 int pixw = pixmap.width();
51 int pixh = pixmap.height();
52 r.setLeft( r.left() + pixw + 2 );
53 p->drawPixmap( br.left()+2, br.center().y()-pixh/2, pixmap );
54 }
55
56 QRect tr = r;
57 if ( t->id == currentTab() )
58 {
59 tr.setBottom( tr.bottom() - style().defaultFrameWidth() );
60 }
61
62 if ( t->enabled && isEnabled() )
63 {
64 p->setPen( colorGroup().foreground() );
65 p->drawText( tr, AlignCenter | ShowPrefix, t->label );
66 }
67 else if ( style() == MotifStyle )
68 {
69 p->setPen( palette().disabled().foreground() );
70 p->drawText( tr, AlignCenter | ShowPrefix, t->label );
71 }
72 else
73 {
74 p->setPen( colorGroup().light() );
75 QRect wr = tr;
76 wr.moveBy( 1, 1 );
77 p->drawText( wr, AlignCenter | ShowPrefix, t->label );
78 p->setPen( palette().disabled().foreground() );
79 p->drawText( tr, AlignCenter | ShowPrefix, t->label );
80 }
81}
diff --git a/noncore/unsupported/libopie/otabbar.h b/noncore/unsupported/libopie/otabbar.h
new file mode 100644
index 0000000..668187b
--- a/dev/null
+++ b/noncore/unsupported/libopie/otabbar.h
@@ -0,0 +1,80 @@
1/*
2                This file is part of the Opie Project
3
4              Copyright (c) 2002 Dan Williams <williamsdr@acm.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#ifndef OTABBAR_H
33#define OTABBAR_H
34
35#include <qtabbar.h>
36
37/**
38 * @class OTabBar
39 * @brief The OTabBar class is a derivative of QTabBar.
40 *
41 * OTabBar is a derivation of TrollTech's QTabBar which provides
42 * a row of tabs for selection. The only difference between this
43 * class and QTabBar is that there is no dotted line box around
44 * the label of the tab with the current focus.
45 */
46class OTabBar : public QTabBar
47{
48 Q_OBJECT
49
50public:
51/**
52 * @fn OTabBar( QWidget *parent = 0, const char *name = 0 )
53 * @brief Object constructor.
54 *
55 * @param parent Pointer to parent of this control.
56 * @param name Name of control.
57 *
58 * Constructs a new OTabBar control with parent and name.
59 */
60 // FIXME Allow WFlags? -zecke
61 OTabBar( QWidget * = 0, const char * = 0 );
62
63protected:
64/**
65 * @fn paintLabel( QPainter* p, const QRect& br , QTab* t, bool has_focus)const
66 * @brief Internal function to draw a tab's label.
67 *
68 * @param p Pointer to QPainter used for drawing.
69 * @param br QRect providing region to draw label in.
70 * @param t Tab to draw label for.
71 * @param has_focus Boolean value not used, retained for compatibility reasons.
72 */
73 void paintLabel( QPainter *, const QRect &, QTab *, bool ) const;
74
75private:
76 class Private;
77 Private *d;
78};
79
80#endif
diff --git a/noncore/unsupported/libopie/otabinfo.h b/noncore/unsupported/libopie/otabinfo.h
new file mode 100644
index 0000000..00bb06d
--- a/dev/null
+++ b/noncore/unsupported/libopie/otabinfo.h
@@ -0,0 +1,134 @@
1/*
2                This file is part of the Opie Project
3
4              Copyright (c) 2002 Dan Williams <williamsdr@acm.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#ifndef OTABINFO_H
33#define OTABINFO_H
34
35#include <qlist.h>
36#include <qstring.h>
37
38class QWidget;
39
40/**
41 * @class OTabInfo
42 * @brief The OTabInfo class is used internally by OTabWidget to keep track
43 * of widgets added to the control.
44 *
45 * OTabInfo provides the following information about a widget added to an
46 * OTabWidget control:
47 *
48 * ID - integer tab bar ID
49 * Control - QWidget pointer to child widget
50 * Label - QString text label for OTabWidget selection control
51 * Icon - QString name of icon file
52 */
53class OTabInfo
54{
55public:
56/**
57 * @fn OTabInfo()
58 * @brief Object constructor.
59 *
60 * @param parent Pointer to parent of this control.
61 * @param name Name of control.
62 * @param s Style of widget selection control.
63 * @param p Position of the widget selection control.
64 */
65 OTabInfo() : i( -1 ), c( 0 ), p( 0 ), l( QString::null ) {}
66
67/**
68 * @fn OTabInfo( int id, QWidget *control, const QString &icon, const QString &label )
69 * @brief Object constructor.
70 *
71 * @param id TabBar identifier for widget.
72 * @param control QWidget pointer to widget.
73 * @param icon QString name of icon file.
74 * @param label QString text label for OTabWidget selection control.
75 */
76 OTabInfo( int id, QWidget *control, const QString &icon, const QString &label )
77 : i( id ), c( control ), p( icon ), l( label ) {}
78
79/**
80 * @fn id()const
81 * @brief Returns TabBar ID.
82 */
83 int id() const { return i; }
84
85/**
86 * @fn label()const
87 * @brief Returns text label for widget.
88 */
89 const QString &label() const { return l; }
90
91/**
92 * @fn setLabel( const QString &label )
93 * @brief Set label for tab.
94 *
95 * @param label QString text label for OTabWidget selection control.
96 */
97 void setLabel( const QString &label ) { l = label; }
98
99/**
100 * @fn control()const
101 * @brief Returns pointer to widget.
102 */
103 QWidget *control() const { return c; }
104
105/**
106 * @fn icon()const
107 * @brief Returns name of icon file.
108 */
109 const QString &icon() const { return p; }
110
111/**
112 * @fn setIcon( const QString &icon )
113 * @brief Set icon for tab.
114 *
115 * @param icon QString name of icon file.
116 */
117 void setIcon( const QString &icon ) { p = icon; }
118
119private:
120 int i;
121 QWidget *c;
122 QString p;
123 QString l;
124 class Private;
125 Private *d;
126};
127
128/**
129 * @class OTabInfoList
130 * @brief A list of OTabInfo objects used by OTabWidget.
131 */
132typedef QList<OTabInfo> OTabInfoList;
133
134#endif
diff --git a/noncore/unsupported/libopie/otabwidget.cpp b/noncore/unsupported/libopie/otabwidget.cpp
new file mode 100644
index 0000000..52190b2
--- a/dev/null
+++ b/noncore/unsupported/libopie/otabwidget.cpp
@@ -0,0 +1,419 @@
1/*
2                This file is part of the Opie Project
3
4              Copyright (c) 2002 Dan Williams <williamsdr@acm.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#include "otabwidget.h"
33
34#include <qpe/applnk.h>
35#include <qpe/config.h>
36#include <qpe/resource.h>
37#include <opie/otabbar.h>
38
39#include <qcombobox.h>
40#include <qwidgetstack.h>
41
42OTabWidget::OTabWidget( QWidget *parent, const char *name, TabStyle s, TabPosition p )
43 : QWidget( parent, name )
44{
45 if ( s == Global )
46 {
47 Config config( "qpe" );
48 config.setGroup( "Appearance" );
49 s = ( TabStyle ) config.readNumEntry( "TabStyle", (int) IconTab );
50 if ( s <= Global || s > IconList)
51 {
52 s = IconTab;
53 }
54 QString pos = config.readEntry( "TabPosition", "Top");
55 if ( pos == "Bottom" )
56 {
57 p = Bottom;
58 }
59 else
60 {
61 p = Top;
62 }
63 }
64
65 widgetStack = new QWidgetStack( this, "widgetstack" );
66 widgetStack->setFrameStyle( QFrame::NoFrame );
67 widgetStack->setLineWidth( style().defaultFrameWidth() );
68
69 tabBarStack = new QWidgetStack( this, "tabbarstack" );
70
71 tabBar = new OTabBar( tabBarStack, "tabbar" );
72 tabBarStack->addWidget( tabBar, 0 );
73 connect( tabBar, SIGNAL( selected(int) ), this, SLOT( slotTabBarSelected(int) ) );
74
75 tabList = new QComboBox( false, tabBarStack, "tablist" );
76 tabBarStack->addWidget( tabList, 1 );
77 connect( tabList, SIGNAL( activated(int) ), this, SLOT( slotTabListSelected(int) ) );
78
79 tabBarPosition = p;
80 setTabStyle( s );
81 setTabPosition( p );
82
83 currTab= 0x0;
84}
85
86OTabWidget::~OTabWidget()
87{
88}
89
90void OTabWidget::addTab( QWidget *child, const QString &icon, const QString &label )
91{
92 QPixmap iconset = loadSmooth( icon );
93
94 QTab *tab = new QTab();
95 if ( tabBarStyle == IconTab )
96 {
97 tab->label = QString::null;
98 }
99 else
100 {
101 tab->label = label;
102 }
103 if ( tabBarStyle == IconTab || tabBarStyle == IconList )
104 {
105 tab->iconset = new QIconSet( iconset );
106 }
107 int tabid = tabBar->addTab( tab );
108
109 if ( tabBarStyle == IconTab || tabBarStyle == IconList )
110 {
111 tabList->insertItem( iconset, label, -1 );
112 }
113 else
114 {
115 tabList->insertItem( label );
116 }
117
118 widgetStack->addWidget( child, tabid );
119 widgetStack->raiseWidget( child );
120 widgetStack->setFrameStyle( QFrame::StyledPanel | QFrame::Raised );
121
122 OTabInfo *tabinfo = new OTabInfo( tabid, child, icon, label );
123 tabs.append( tabinfo );
124 selectTab( tabinfo );
125}
126
127void OTabWidget::removePage( QWidget *childwidget )
128{
129 if ( childwidget )
130 {
131 OTabInfo *tab = tabs.first();
132 while ( tab && tab->control() != childwidget )
133 {
134 tab = tabs.next();
135 }
136 if ( tab && tab->control() == childwidget )
137 {
138 tabBar->setTabEnabled( tab->id(), FALSE );
139 tabBar->removeTab( tabBar->tab( tab->id() ) );
140 int i = 0;
141 while ( i < tabList->count() && tabList->text( i ) != tab->label() )
142 {
143 i++;
144 }
145 if ( tabList->text( i ) == tab->label() )
146 {
147 tabList->removeItem( i );
148 }
149 widgetStack->removeWidget( childwidget );
150 tabs.remove( tab );
151 delete tab;
152 currTab = tabs.current();
153 if ( !currTab )
154 {
155 widgetStack->setFrameStyle( QFrame::NoFrame );
156 }
157
158 setUpLayout();
159 }
160 }
161}
162
163void OTabWidget::changeTab( QWidget *widget, const QString &iconset, const QString &label)
164{
165 OTabInfo *currtab = tabs.first();
166 while ( currtab && currtab->control() != widget )
167 {
168 currtab = tabs.next();
169 }
170 if ( currtab && currtab->control() == widget )
171 {
172 QTab *tab = tabBar->tab( currtab->id() );
173 QPixmap icon( loadSmooth( iconset ) );
174 tab->setText( label );
175 if ( tabBarStyle == IconTab )
176 tab->setIconSet( icon );
177 int i = 0;
178 while ( i < tabList->count() && tabList->text( i ) != currtab->label() )
179 {
180 i++;
181 }
182 if ( i < tabList->count() && tabList->text( i ) == currtab->label() )
183 {
184 if ( tabBarStyle == IconTab || tabBarStyle == IconList )
185 {
186 tabList->changeItem( icon, label, i );
187 }
188 else
189 {
190 tabList->changeItem( label, i );
191 }
192 }
193 currtab->setLabel( label );
194 currtab->setIcon( iconset );
195 }
196 setUpLayout();
197}
198
199void OTabWidget::setCurrentTab( QWidget *childwidget )
200{
201 OTabInfo *currtab = tabs.first();
202 while ( currtab && currtab->control() != childwidget )
203 {
204 currtab = tabs.next();
205 }
206 if ( currtab && currtab->control() == childwidget )
207 {
208 selectTab( currtab );
209 }
210}
211
212void OTabWidget::setCurrentTab( const QString &tabname )
213{
214 OTabInfo *newtab = tabs.first();
215 while ( newtab && newtab->label() != tabname )
216 {
217 newtab = tabs.next();
218 }
219 if ( newtab && newtab->label() == tabname )
220 {
221 selectTab( newtab );
222 }
223}
224
225void OTabWidget::setCurrentTab(int tabindex) {
226 OTabInfo *newtab = tabs.first();
227 while ( newtab && newtab->id() != tabindex )
228 {
229 newtab = tabs.next();
230 }
231 if ( newtab && newtab->id() == tabindex )
232 {
233 selectTab( newtab );
234 }
235}
236
237
238OTabWidget::TabStyle OTabWidget::tabStyle() const
239{
240 return tabBarStyle;
241}
242
243void OTabWidget::setTabStyle( TabStyle s )
244{
245 tabBarStyle = s;
246 if ( tabBarStyle == TextTab || tabBarStyle == IconTab )
247 {
248 QTab *currtab;
249 for ( OTabInfo *tabinfo = tabs.first(); tabinfo; tabinfo = tabs.next() )
250 {
251 currtab = tabBar->tab( tabinfo->id() );
252 if ( tabBarStyle == IconTab )
253 {
254 currtab->iconset = new QIconSet( loadSmooth( tabinfo->icon() ) );
255 if ( tabinfo == currTab )
256 currtab->setText( tabinfo->label() );
257 else
258 currtab->setText( QString::null );
259 }
260 else
261 {
262 currtab->iconset = 0x0;
263 currtab->setText( tabinfo->label() );
264 }
265 }
266 tabBarStack->raiseWidget( tabBar );
267 }
268 else if ( tabBarStyle == TextList || tabBarStyle == IconList )
269 {
270 tabList->clear();
271 for ( OTabInfo *tabinfo = tabs.first(); tabinfo; tabinfo = tabs.next() )
272 {
273 if ( tabBarStyle == IconList )
274 {
275 tabList->insertItem( loadSmooth( tabinfo->icon() ), tabinfo->label() );
276 }
277 else
278 {
279 tabList->insertItem( tabinfo->label() );
280 }
281 }
282 tabBarStack->raiseWidget( tabList );
283 }
284 setUpLayout();
285}
286
287OTabWidget::TabPosition OTabWidget::tabPosition() const
288{
289 return tabBarPosition;
290}
291
292void OTabWidget::setTabPosition( TabPosition p )
293{
294 tabBarPosition = p;
295 if ( tabBarPosition == Top )
296 {
297 tabBar->setShape( QTabBar::RoundedAbove );
298 }
299 else
300 {
301 tabBar->setShape( QTabBar::RoundedBelow );
302 }
303 setUpLayout();
304}
305
306void OTabWidget::slotTabBarSelected( int id )
307{
308 OTabInfo *newtab = tabs.first();
309 while ( newtab && newtab->id() != id )
310 {
311 newtab = tabs.next();
312 }
313 if ( newtab && newtab->id() == id )
314 {
315 selectTab( newtab );
316 }
317}
318
319void OTabWidget::slotTabListSelected( int index )
320{
321 OTabInfo *newtab = tabs.at( index );
322 if ( newtab )
323 {
324 selectTab( newtab );
325 }
326}
327
328QPixmap OTabWidget::loadSmooth( const QString &name )
329{
330 QPixmap p;
331 p.convertFromImage( Resource::loadImage( name ).smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ) );
332 return p;
333}
334
335void OTabWidget::selectTab( OTabInfo *tab )
336{
337 if ( tabBarStyle == IconTab )
338 {
339 if ( currTab )
340 {
341 tabBar->tab( currTab->id() )->setText( QString::null );
342 setUpLayout();
343 }
344 tabBar->tab( tab->id() )->setText( tab->label() );
345 tabBar->setCurrentTab( tab->id() );
346 setUpLayout();
347 tabBar->update();
348 }
349 else
350 {
351 tabBar->setCurrentTab( tab->id() );
352 }
353
354 widgetStack->raiseWidget( tab->control() );
355
356 emit currentChanged( tab->control() );
357
358 currTab = tab;
359}
360
361void OTabWidget::setUpLayout()
362{
363 tabBar->layoutTabs();
364 QSize t( tabBarStack->sizeHint() );
365 if ( tabBarStyle == IconTab )
366 {
367 if ( t.width() > width() )
368 t.setWidth( width() );
369 }
370 else
371 {
372 t.setWidth( width() );
373 }
374 int lw = widgetStack->lineWidth();
375 if ( tabBarPosition == Bottom )
376 {
377 tabBarStack->setGeometry( QMAX(0, lw-2), height() - t.height() - lw, t.width(), t.height() );
378 widgetStack->setGeometry( 0, 0, width(), height()-t.height()+QMAX(0, lw-2) );
379 }
380 else
381 {
382 tabBarStack->setGeometry( QMAX(0, lw-2), 0, t.width(), t.height() );
383 widgetStack->setGeometry( 0, t.height()-lw, width(), height()-t.height()+QMAX( 0, lw-2 ) );
384 }
385
386 if ( autoMask() )
387 updateMask();
388}
389
390QSize OTabWidget::sizeHint() const
391{
392 QSize s( widgetStack->sizeHint() );
393 QSize t( tabBarStack->sizeHint() );
394 return QSize( QMAX( s.width(), t.width() ), s.height() + t.height() );
395}
396
397void OTabWidget::resizeEvent( QResizeEvent * )
398{
399 setUpLayout();
400}
401
402int OTabWidget::currentTab()
403{
404 if ( currTab )
405 {
406 return currTab->id();
407 }
408 return -1;
409}
410
411QWidget* OTabWidget::currentWidget()const
412{
413 if ( currTab )
414 {
415 return currTab->control();
416 }
417
418 return 0;
419}
diff --git a/noncore/unsupported/libopie/otabwidget.h b/noncore/unsupported/libopie/otabwidget.h
new file mode 100644
index 0000000..047eaa1
--- a/dev/null
+++ b/noncore/unsupported/libopie/otabwidget.h
@@ -0,0 +1,285 @@
1/*
2                This file is part of the Opie Project
3
4              Copyright (c) 2002 Dan Williams <williamsdr@acm.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#ifndef OTABWIDGET_H
33#define OTABWIDGET_H
34
35#include "otabinfo.h"
36
37#include <qwidget.h>
38#include <qlist.h>
39
40class OTabBar;
41class QComboBox;
42class QPixmap;
43class QTabBar;
44class QWidgetStack;
45
46/**
47 * @class OTabWidget
48 * @brief The OTabWidget class provides a stack of widgets.
49 *
50 * OTabWidget is a derivation of TrollTech's QTabWidget which provides
51 * a stack of widgets. Widgets can be selected using either a tab bar or
52 * drop down list box.
53 *
54 * The normal way to use OTabWidget is to do the following in the
55 * constructor:
56 * - Create a OTabWidget.
57 * - Create a QWidget for each of the pages in the control, insert
58 * children into it, set up geometry management for it, and use addTab()
59 * to add the widget.
60 */
61class OTabWidget : public QWidget
62{
63 Q_OBJECT
64public:
65
66/**
67 * @enum TabStyle
68 * @brief Defines how the widget selection control is displayed.
69 *
70 * Valid values:
71 * - Global: use globally selected options (qpe.conf - TabStyle & TabPosition)
72 * - TextTab: Tabbed widget selection with text labels
73 * - IconTab: Tabbed widget selection with icon labels, text label for active widget
74 * (similar to Opie launcher)
75 * - TextList: Drop down list widget selection with text labels
76 * - IconList: Drop down list widget selection with icon & text labels
77 */
78 enum TabStyle { Global, TextTab, IconTab, TextList, IconList };
79
80/**
81 * @enum TabPosition
82 * @brief Defines where the widget selection control is drawn.
83 *
84 * Valid values:
85 * - Top: Widget selection control is drawn above widgets
86 * - Bottom: Widget selection control is drawn below widgets
87 */
88 enum TabPosition { Top, Bottom };
89
90/**
91 * @fn OTabWidget( QWidget *parent = 0, const char *name = 0, TabStyle s = Global, TabPosition p = Top )
92 * @brief Object constructor.
93 *
94 * @param parent Pointer to parent of this control.
95 * @param name Name of control.
96 * @param s Style of widget selection control.
97 * @param p Position of the widget selection control.
98 *
99 * Constructs a new OTabWidget control with parent and name. The style and position parameters
100 * determine how the widget selection control will be displayed.
101 */
102 // FIXME WFlags? -zecke
103 OTabWidget( QWidget * = 0, const char * = 0, TabStyle = Global, TabPosition = Top );
104
105/**
106 * @fn ~OTabWidget()
107 * @brief Object destructor.
108 */
109 ~OTabWidget();
110
111/**
112 * @fn addTab( QWidget *child, const QString &icon, const QString &label )
113 * @brief Add new widget to control.
114 *
115 * @param child Widget control.
116 * @param icon Path to icon.
117 * @param label Text label.
118 */
119 void addTab( QWidget *, const QString &, const QString & );
120
121/**
122 * @fn removePage( QWidget *widget )
123 * @brief Remove widget from control. Does not delete widget.
124 *
125 * @param widget Widget control to be removed.
126 */
127 /* ### Page vs. Tab.. yes the widget is a Page but then is addTab wrong -zecke */
128 void removePage( QWidget * );
129
130/**
131 * @fn changeTab( QWidget *widget, const QString &icon, const QString &label )
132 * @brief Change text and/or icon for existing tab
133 *
134 * @param child Widget control.
135 * @param icon Path to icon.
136 * @param label Text label.
137 */
138 void changeTab( QWidget *, const QString &, const QString & );
139
140/**
141 * @fn tabStyle()const
142 * @brief Returns current widget selection control style.
143 */
144 TabStyle tabStyle() const;
145
146/**
147 * @fn setTabStyle( TabStyle s )
148 * @brief Set the current widget selection control style.
149 *
150 * @param s New style to be used.
151 */
152 void setTabStyle( TabStyle );
153
154/**
155 * @fn tabPosition()const
156 * @brief Returns current widget selection control position.
157 */
158 TabPosition tabPosition() const;
159
160/**
161 * @fn setTabPosition( TabPosition p )
162 * @brief Set the current widget selection control position.
163 *
164 * @param p New position of widget selection control.
165 */
166 void setTabPosition( TabPosition );
167
168/**
169 * @fn setCurrentTab( QWidget *childwidget )
170 * @brief Selects and brings to top the desired widget by using widget pointer.
171 *
172 * @param childwidget Widget to select.
173 */
174 void setCurrentTab( QWidget * );
175
176/**
177 * @fn setCurrentTab( const QString &tabname )
178 * @brief Selects and brings to top the desired widget, by using label.
179 *
180 * @param tabname Text label for widget to select.
181 */
182 void setCurrentTab( const QString & );
183
184/**
185 * @fn setCurrentTab( int )
186 * @brief Selects and brings to top the desired widget, by using id.
187 *
188 * @param tab id for widget to select.
189 */
190 void setCurrentTab(int);
191
192/**
193 * @fn sizeHint()const
194 * @brief Reimplemented for internal purposes.
195 */
196 QSize sizeHint() const;
197
198/**
199 * @fn currentTab( )
200 * @brief returns current tab id.
201 */
202 // ### make const
203 int currentTab()/* const */;
204/**
205 * @brief returns the current page of the active tab
206 *
207 * @since 1.2
208 */
209 QWidget* currentWidget()const;
210
211protected:
212
213/**
214 * @fn resizeEvent( QResizeEvent * )
215 * @brief Reimplemented for internal purposes.
216 */
217 void resizeEvent( QResizeEvent * );
218
219private:
220 OTabInfoList tabs;
221 OTabInfo *currTab;
222
223 TabStyle tabBarStyle;
224 TabPosition tabBarPosition;
225
226 QWidgetStack *tabBarStack;
227 OTabBar *tabBar;
228 QComboBox *tabList;
229
230 QWidgetStack *widgetStack;
231 class Private;
232 Private* d;
233
234/**
235 * @fn loadSmooth( const QString &name )
236 * @brief Loads icon for widget.
237 *
238 * @param name Name of icon image file.
239 */
240 QPixmap loadSmooth( const QString & );
241
242/**
243 * @fn selectTab( OTabInfo *tab )
244 * @brief Internal function to select desired widget.
245 *
246 * @param tab Pointer to data for widget.
247 */
248 void selectTab( OTabInfo * );
249
250/**
251 * @fn setUpLayout()
252 * @brief Internal function to adjust layout.
253 */
254 void setUpLayout();
255
256
257signals:
258/**
259 * @fn currentChanged( QWidget *widget )
260 * @brief This signal is emitted whenever the widget has changed.
261 *
262 * @param widget Pointer to new current widget.
263 */
264 void currentChanged( QWidget * );
265
266private slots:
267
268/**
269 * @fn slotTabBarSelected( int id )
270 * @brief Slot which is called when a tab is selected.
271 *
272 * @param id ID of widget selected.
273 */
274 void slotTabBarSelected( int );
275
276/**
277 * @fn slotTabListSelected( int index )
278 * @brief Slot which is called when a drop down selection is made.
279 *
280 * @param id Index of widget selected.
281 */
282 void slotTabListSelected( int );
283};
284
285#endif
diff --git a/noncore/unsupported/libopie/oticker.cpp b/noncore/unsupported/libopie/oticker.cpp
new file mode 100644
index 0000000..b41cab6
--- a/dev/null
+++ b/noncore/unsupported/libopie/oticker.cpp
@@ -0,0 +1,132 @@
1/*
2                This file is part of the Opie Project
3 Copyright (c) 2002 L. Potter <ljp@llornkcor.com>
4 Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
5
6 =.
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = General Public License along with
26    --        :-=` this; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33#include <qpe/config.h>
34
35#include <stdlib.h>
36#include <stdio.h>
37
38#include "oticker.h"
39
40OTicker::OTicker( QWidget* parent )
41 : QLabel( parent ) {
42 // : QFrame( parent ) {
43 setTextFormat(Qt::RichText);
44 Config cfg("qpe");
45 cfg.setGroup("Appearance");
46 backgroundcolor = QColor( cfg.readEntry( "Background", "#E5E1D5" ) );
47 foregroundcolor= Qt::black;
48 updateTimerTime = 50;
49 scrollLength = 1;
50}
51
52OTicker::~OTicker() {
53}
54
55void OTicker::setBackgroundColor(const QColor& backcolor) {
56 backgroundcolor = backcolor;
57 update();
58}
59
60void OTicker::setForegroundColor(const QColor& backcolor) {
61 foregroundcolor = backcolor;
62 update();
63}
64
65void OTicker::setFrame(int frameStyle) {
66 setFrameStyle( frameStyle/*WinPanel | Sunken */);
67 update();
68}
69
70void OTicker::setText( const QString& text ) {
71 pos = 0; // reset it everytime the text is changed
72 scrollText = text;
73qDebug(scrollText);
74
75 int pixelLen = 0;
76 bool bigger = false;
77 int contWidth = contentsRect().width();
78 int contHeight = contentsRect().height();
79 int pixelTextLen = fontMetrics().width( text );
80 printf("<<<<<<<height %d, width %d, text width %d %d\n", contHeight, contWidth, pixelTextLen, scrollText.length());
81 if( pixelTextLen < contWidth)
82 {
83 pixelLen = contWidth;
84 }
85 else
86 {
87 bigger = true;
88 pixelLen = pixelTextLen;
89 }
90 QPixmap pm( pixelLen, contHeight);
91// pm.fill( QColor( 167, 212, 167 ));
92
93 pm.fill(backgroundcolor);
94 QPainter pmp( &pm );
95 pmp.setPen(foregroundcolor );
96 pmp.drawText( 0, 0, pixelTextLen, contHeight, AlignVCenter, scrollText );
97 pmp.end();
98 scrollTextPixmap = pm;
99
100 killTimers();
101 // qDebug("Scrollupdate %d", updateTimerTime);
102 if ( bigger /*pixelTextLen > contWidth*/ )
103 startTimer( updateTimerTime);
104 update();
105}
106
107
108void OTicker::timerEvent( QTimerEvent * ) {
109 pos = ( pos <= 0 ) ? scrollTextPixmap.width() : pos - scrollLength;//1;
110 repaint( FALSE );
111}
112
113void OTicker::drawContents( QPainter *p ) {
114 int pixelLen = scrollTextPixmap.width();
115 p->drawPixmap( pos, contentsRect().y(), scrollTextPixmap );
116 if ( pixelLen > contentsRect().width() ) // Scrolling
117 p->drawPixmap( pos - pixelLen, contentsRect().y(), scrollTextPixmap );
118}
119
120void OTicker::mouseReleaseEvent( QMouseEvent * ) {
121// qDebug("<<<<<<<>>>>>>>>>");
122 emit mousePressed();
123}
124
125void OTicker::setUpdateTime(int time) {
126 updateTimerTime=time;
127}
128
129void OTicker::setScrollLength(int len) {
130scrollLength=len;
131}
132
diff --git a/noncore/unsupported/libopie/oticker.h b/noncore/unsupported/libopie/oticker.h
new file mode 100644
index 0000000..45bf7ce
--- a/dev/null
+++ b/noncore/unsupported/libopie/oticker.h
@@ -0,0 +1,148 @@
1/*
2                This file is part of the Opie Project
3 Copyright (c) 2002 L. Potter <ljp@llornkcor.com>
4 Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
5
6 =.
7 .=l.
8           .>+-=
9 _;:,     .>    :=|. This program is free software; you can
10.> <`_,   >  .   <= redistribute it and/or modify it under
11:`=1 )Y*s>-.--   : the terms of the GNU General Public
12.="- .-=="i,     .._ License as published by the Free Software
13 - .   .-<_>     .<> Foundation; either version 2 of the License,
14     ._= =}       : or (at your option) any later version.
15    .%`+i>       _;_.
16    .i_,=:_.      -<s. This program is distributed in the hope that
17     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
18    : ..    .:,     . . . without even the implied warranty of
19    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
20  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
21..}^=.=       =       ; General Public License for more
22++=   -.     .`     .: details.
23 :     =  ...= . :.=-
24 -.   .:....=;==+<; You should have received a copy of the GNU
25  -_. . .   )=.  = General Public License along with
26    --        :-=` this; see the file COPYING.LIB.
27 If not, write to the Free Software Foundation,
28 Inc., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.
30
31*/
32
33#ifndef OTICKER_H
34#define OTICKER_H
35
36#include <qwidget.h>
37#include <qpainter.h>
38#include <qdrawutil.h>
39#include <qpixmap.h>
40#include <qstring.h>
41#include <qslider.h>
42#include <qlabel.h>
43#include <qframe.h>
44#include <qcolor.h>
45
46/**
47 * @class OTicker
48 * @brief The OTicker class provides a QLabel widget that scroll its contents
49 *
50 */
51class OTicker : public QLabel {
52 Q_OBJECT
53
54public:
55
56/*!
57 * @fn OTicker( QWidget* parent = 0 )
58 * @brief Object constructor.
59 *
60 * @param parent Pointer to parent of this control.
61
62 * Constructs a new OTicker control with parent
63 */
64 OTicker( QWidget* parent=0 );
65/*!
66 * @fn ~OTicker()
67 * @brief Object destructor.
68 */
69 ~OTicker();
70/*!
71 * @fn setText(const QString& )
72 * @brief sets text to be displayed
73 * @param text QString text to be displayed.
74 *
75 */
76 void setText( const QString& text ) ;
77/*!
78 * @fn setBackgroundColor(const QColor& color)
79 * @brief sets color of the ticker's background
80 * @param color QColor color to be set.
81 *
82 */
83 void setBackgroundColor(const QColor& color);
84/*!
85 * @fn setForegroundColor(const QColor& color)
86 * @brief sets color of text
87 * @param color QColor color of text
88 *
89 */
90 void setForegroundColor(const QColor& color);
91/*!
92 * @fn setFrame(int style)
93 * @brief sets frame style
94 * @param style int Frame style to be see. See Qt::WidgetFlags.
95 *
96 */
97 void setFrame(int style);
98/*!
99 * @fn setUpdateTime(int timeout)
100 * @brief sets time of update
101 * @param timeout int time in milliseconds between updates.
102 *
103 */
104 void setUpdateTime(int timeout);
105/*!
106 * @fn setScrollLength(int length)
107 * @brief sets amount of scrolling default is 1
108 * @param length int scroll length.
109 *
110 */
111 void setScrollLength(int length);
112signals:
113/*!
114 * @fn mousePressed()
115 * @brief signal mouse press event
116 *
117 */
118 void mousePressed();
119protected:
120/*!
121 * @fn timerEvent( QTimerEvent * e)
122 * @brief timer timeout event
123 * @param e QEvent see QEvent.
124 *
125 */
126 void timerEvent( QTimerEvent * e);
127/*!
128 * @fn drawContents( QPainter *p )
129 * @brief draws widget contents
130 * @param p QPainter. see QPainter
131 *
132 */
133 void drawContents( QPainter *p );
134/*!
135 * @fn mouseReleaseEvent( QMouseEvent *e)
136 * @brief mouse release event
137 * @param e QMouseEvent. see QMouseEvent.
138 *
139 */
140 void mouseReleaseEvent( QMouseEvent *e);
141private:
142 QColor backgroundcolor, foregroundcolor;
143 QString scrollText;
144 QPixmap scrollTextPixmap;
145 int pos, updateTimerTime, scrollLength;
146};
147
148#endif
diff --git a/noncore/unsupported/libopie/otimepicker.cpp b/noncore/unsupported/libopie/otimepicker.cpp
new file mode 100644
index 0000000..11b80ed
--- a/dev/null
+++ b/noncore/unsupported/libopie/otimepicker.cpp
@@ -0,0 +1,242 @@
1#include "otimepicker.h"
2
3#include <qlayout.h>
4#include <stdio.h>
5#include <qlineedit.h>
6
7
8/**
9 * Constructs the widget
10 * @param parent The parent of the OTimePicker
11 * @param name The name of the object
12 * @param fl Window Flags
13 */
14OTimePicker::OTimePicker(QWidget* parent, const char* name,
15 WFlags fl) :
16 QWidget(parent,name,fl)
17{
18
19 QVBoxLayout *vbox=new QVBoxLayout(this);
20
21 OClickableLabel *r;
22 QString s;
23
24 // Hour Row
25 QWidget *row=new QWidget(this);
26 QHBoxLayout *l=new QHBoxLayout(row);
27 vbox->addWidget(row);
28
29
30 for (int i=0; i<24; i++) {
31 r=new OClickableLabel(row);
32 hourLst.append(r);
33 s.sprintf("%.2d",i);
34 r->setText(s);
35 r->setToggleButton(true);
36 r->setAlignment(AlignHCenter | AlignVCenter);
37 l->addWidget(r);
38 connect(r, SIGNAL(toggled(bool)),
39 this, SLOT(slotHour(bool)));
40
41 if (i==11) { // Second row
42 row=new QWidget(this);
43 l=new QHBoxLayout(row);
44 vbox->addWidget(row);
45 }
46 }
47
48 // Minute Row
49 row=new QWidget(this);
50 l=new QHBoxLayout(row);
51 vbox->addWidget(row);
52
53 for (int i=0; i<60; i+=5) {
54 r=new OClickableLabel(row);
55 minuteLst.append(r);
56 s.sprintf("%.2d",i);
57 r->setText(s);
58 r->setToggleButton(true);
59 r->setAlignment(AlignHCenter | AlignVCenter);
60 l->addWidget(r);
61 connect(r, SIGNAL(toggled(bool)),
62 this, SLOT(slotMinute(bool)));
63 }
64}
65
66/**
67 * This method return the current time
68 * @return the time
69 */
70QTime OTimePicker::time()const {
71 return tm;
72}
73
74void OTimePicker::slotHour(bool b) {
75
76 OClickableLabel *r = (OClickableLabel *) sender();
77
78 if (b) {
79 QValueListIterator<OClickableLabel *> it;
80 for (it=hourLst.begin(); it!=hourLst.end(); it++) {
81 if (*it != r) (*it)->setOn(false);
82 else tm.setHMS((*it)->text().toInt(), tm.minute(), 0);
83 }
84 emit timeChanged(tm);
85 } else {
86 r->setOn(true);
87 }
88
89}
90
91void OTimePicker::slotMinute(bool b) {
92
93 OClickableLabel *r = (OClickableLabel *) sender();
94
95 if (b) {
96 QValueListIterator<OClickableLabel *> it;
97 for (it=minuteLst.begin(); it!=minuteLst.end(); it++) {
98 if (*it != r) (*it)->setOn(false);
99 else tm.setHMS(tm.hour(),(*it)->text().toInt(), 0);
100 }
101 emit timeChanged(tm);
102 } else {
103 r->setOn(true);
104 }
105
106}
107
108/**
109 * Method to set the time. No signal gets emitted during this method call
110 * Minutes must be within 5 minutes step starting at 0 ( 0,5,10,15,20... )
111 * @param t The time to be set
112 */
113void OTimePicker::setTime( const QTime& t) {
114 setTime( t.hour(), t.minute() );
115}
116
117/**
118 * Method to set the time. No signal gets emitted during this method call
119 * @param h The hour
120 * @param m The minute. Minutes need to set by 5 minute steps
121 */
122void OTimePicker::setTime( int h, int m ) {
123 setHour(h);
124 setMinute(m);
125}
126
127/*
128 * FIXME round minutes to the 5 minute arrangement -zecke
129 */
130/**
131 * Method to set the minutes
132 * @param m minutes
133 */
134void OTimePicker::setMinute(int m) {
135
136 QString minute;
137 minute.sprintf("%.2d",m);
138
139 QValueListIterator<OClickableLabel *> it;
140 for (it=minuteLst.begin(); it!=minuteLst.end(); it++) {
141 if ((*it)->text() == minute) (*it)->setOn(true);
142 else (*it)->setOn(false);
143 }
144
145 tm.setHMS(tm.hour(),m,0);
146}
147
148/**
149 * Method to set the hour
150 */
151void OTimePicker::setHour(int h) {
152
153 QString hour;
154 hour.sprintf("%.2d",h);
155
156 QValueListIterator<OClickableLabel *> it;
157 for (it=hourLst.begin(); it!=hourLst.end(); it++) {
158 if ((*it)->text() == hour) (*it)->setOn(true);
159 else (*it)->setOn(false);
160 }
161 tm.setHMS(h,tm.minute(),0);
162}
163
164
165/**
166 * This is a modal Dialog.
167 *
168 * @param parent The parent widget
169 * @param name The name of the object
170 * @param fl Possible window flags
171 */
172OTimePickerDialog::OTimePickerDialog ( QWidget* parent, const char* name, WFlags fl )
173 : OTimePickerDialogBase (parent , name, true , fl)
174{
175
176 connect ( m_timePicker, SIGNAL( timeChanged(const QTime&) ),
177 this, SLOT( setTime(const QTime&) ) );
178 connect ( minuteField, SIGNAL( textChanged(const QString&) ),
179 this, SLOT ( setMinute(const QString&) ) );
180 connect ( hourField, SIGNAL( textChanged(const QString&) ),
181 this, SLOT ( setHour(const QString&) ) );
182
183}
184
185/**
186 * @return the time
187 */
188QTime OTimePickerDialog::time()const
189{
190 return m_time;
191}
192
193/**
194 * Set the time to time
195 * @param time The time to be set
196 */
197void OTimePickerDialog::setTime( const QTime& time )
198{
199 m_time = time;
200
201 m_timePicker->setHour ( time.hour() );
202 m_timePicker->setMinute( time.minute() );
203
204 // Set Textfields
205 if ( time.hour() < 10 )
206 hourField->setText( "0" + QString::number( time.hour() ) );
207 else
208 hourField->setText( QString::number( time.hour() ) );
209
210 if ( time.minute() < 10 )
211 minuteField->setText( "0" + QString::number( time.minute() ) );
212 else
213 minuteField->setText( QString::number( time.minute() ) );
214
215}
216
217/**
218 * This method takes the current minute and tries to set hour
219 * to hour. This succeeds if the resulting date is valid
220 * @param hour The hour as a string
221 */
222void OTimePickerDialog::setHour ( const QString& hour )
223{
224 if ( QTime::isValid ( hour.toInt(), m_time.minute() , 00 ) ){
225 m_time.setHMS ( hour.toInt(), m_time.minute() , 00 );
226 setTime ( m_time );
227 }
228
229}
230
231/**
232 * Method to set a new minute. It tries to convert the string to int and
233 * if the resulting date is valid a new date is set.
234 * @see setHour
235 */
236void OTimePickerDialog::setMinute ( const QString& minute )
237{
238 if ( QTime::isValid ( m_time.hour(), minute.toInt(), 00 ) ){
239 m_time.setHMS ( m_time.hour(), minute.toInt(), 00 );
240 setTime ( m_time );
241 }
242}
diff --git a/noncore/unsupported/libopie/otimepicker.h b/noncore/unsupported/libopie/otimepicker.h
new file mode 100644
index 0000000..8df7d10
--- a/dev/null
+++ b/noncore/unsupported/libopie/otimepicker.h
@@ -0,0 +1,86 @@
1#ifndef OTIMEPICKER_H
2#define OTIMEPICKER_H
3
4#include <qwidget.h>
5#include <qvaluelist.h>
6#include <qdatetime.h>
7#include <qdialog.h>
8
9#include <opie/oclickablelabel.h>
10#include "otimepickerbase.h"
11
12/**
13 * A class to pick time. It uses clickable labels
14 * internally to allow a quick selection of a time.
15 * A time can be selected by two clicks of a user
16 *
17 * @short A widget to quickly pick a QTime
18 * @version 1.0
19 * @see QWidget
20 * @see QTime
21 * @author Hakan Ardo, Stefan Eilers
22 */
23class OTimePicker: public QWidget {
24 Q_OBJECT
25
26 public:
27 OTimePicker(QWidget* parent = 0, const char* name = 0,
28 WFlags fl = 0);
29
30 public slots:
31 void setHour(int h);
32 void setMinute(int m);
33 void setTime( const QTime& );
34 void setTime( int h, int m );
35
36 public:
37 QTime time()const;
38
39 private:
40 QValueList<OClickableLabel *> hourLst;
41 QValueList<OClickableLabel *> minuteLst;
42 QTime tm;
43 struct Private;
44 Private *d;
45
46 private slots:
47 void slotHour(bool b);
48 void slotMinute(bool b);
49
50 signals:
51 /**
52 * gets emitted when the time got changed by the user
53 */
54 void timeChanged(const QTime &);
55};
56
57/**
58 *
59 * @short A small dialog to pick a time
60 * @version 1.0
61 * @author Stefan Eilers
62 */
63
64class OTimePickerDialog: public OTimePickerDialogBase {
65 Q_OBJECT
66
67 public:
68 OTimePickerDialog ( QWidget* parent = 0, const char* name = NULL, WFlags fl = 0 );
69 /**
70 * @todo make it non line! See KDE guide for BC
71 */
72 ~OTimePickerDialog() { };
73
74 QTime time()const;
75
76 public slots:
77 void setTime( const QTime& time );
78 void setHour( const QString& hour );
79 void setMinute( const QString& minute );
80
81 private:
82 QTime m_time;
83 class Private;
84 Private* d;
85};
86#endif
diff --git a/noncore/unsupported/libopie/otimepickerbase.ui b/noncore/unsupported/libopie/otimepickerbase.ui
new file mode 100644
index 0000000..3e7f2fb
--- a/dev/null
+++ b/noncore/unsupported/libopie/otimepickerbase.ui
@@ -0,0 +1,292 @@
1<!DOCTYPE UI><UI>
2<class>OTimePickerDialogBase</class>
3<widget>
4 <class>QDialog</class>
5 <property stdset="1">
6 <name>name</name>
7 <cstring>OTimePickerDialogBase</cstring>
8 </property>
9 <property stdset="1">
10 <name>geometry</name>
11 <rect>
12 <x>0</x>
13 <y>0</y>
14 <width>210</width>
15 <height>137</height>
16 </rect>
17 </property>
18 <property stdset="1">
19 <name>sizePolicy</name>
20 <sizepolicy>
21 <hsizetype>3</hsizetype>
22 <vsizetype>1</vsizetype>
23 </sizepolicy>
24 </property>
25 <property stdset="1">
26 <name>caption</name>
27 <string>OTimePickerDialogBase</string>
28 </property>
29 <property>
30 <name>layoutMargin</name>
31 </property>
32 <property>
33 <name>layoutSpacing</name>
34 </property>
35 <vbox>
36 <property stdset="1">
37 <name>margin</name>
38 <number>5</number>
39 </property>
40 <property stdset="1">
41 <name>spacing</name>
42 <number>4</number>
43 </property>
44 <widget>
45 <class>QFrame</class>
46 <property stdset="1">
47 <name>name</name>
48 <cstring>Frame10</cstring>
49 </property>
50 <property stdset="1">
51 <name>sizePolicy</name>
52 <sizepolicy>
53 <hsizetype>1</hsizetype>
54 <vsizetype>7</vsizetype>
55 </sizepolicy>
56 </property>
57 <property stdset="1">
58 <name>frameShape</name>
59 <enum>NoFrame</enum>
60 </property>
61 <property stdset="1">
62 <name>frameShadow</name>
63 <enum>Raised</enum>
64 </property>
65 <property>
66 <name>layoutMargin</name>
67 </property>
68 <hbox>
69 <property stdset="1">
70 <name>margin</name>
71 <number>2</number>
72 </property>
73 <property stdset="1">
74 <name>spacing</name>
75 <number>6</number>
76 </property>
77 <spacer>
78 <property>
79 <name>name</name>
80 <cstring>Spacer4</cstring>
81 </property>
82 <property stdset="1">
83 <name>orientation</name>
84 <enum>Horizontal</enum>
85 </property>
86 <property stdset="1">
87 <name>sizeType</name>
88 <enum>MinimumExpanding</enum>
89 </property>
90 <property>
91 <name>sizeHint</name>
92 <size>
93 <width>20</width>
94 <height>20</height>
95 </size>
96 </property>
97 </spacer>
98 <widget>
99 <class>QFrame</class>
100 <property stdset="1">
101 <name>name</name>
102 <cstring>Frame4</cstring>
103 </property>
104 <property stdset="1">
105 <name>sizePolicy</name>
106 <sizepolicy>
107 <hsizetype>4</hsizetype>
108 <vsizetype>4</vsizetype>
109 </sizepolicy>
110 </property>
111 <property stdset="1">
112 <name>frameShape</name>
113 <enum>Box</enum>
114 </property>
115 <property stdset="1">
116 <name>frameShadow</name>
117 <enum>Sunken</enum>
118 </property>
119 <property>
120 <name>layoutMargin</name>
121 </property>
122 <property>
123 <name>layoutSpacing</name>
124 </property>
125 <hbox>
126 <property stdset="1">
127 <name>margin</name>
128 <number>4</number>
129 </property>
130 <property stdset="1">
131 <name>spacing</name>
132 <number>6</number>
133 </property>
134 <widget>
135 <class>QLabel</class>
136 <property stdset="1">
137 <name>name</name>
138 <cstring>TextLabel1</cstring>
139 </property>
140 <property stdset="1">
141 <name>text</name>
142 <string>Time:</string>
143 </property>
144 </widget>
145 <widget>
146 <class>QLineEdit</class>
147 <property stdset="1">
148 <name>name</name>
149 <cstring>hourField</cstring>
150 </property>
151 <property stdset="1">
152 <name>sizePolicy</name>
153 <sizepolicy>
154 <hsizetype>4</hsizetype>
155 <vsizetype>0</vsizetype>
156 </sizepolicy>
157 </property>
158 <property stdset="1">
159 <name>alignment</name>
160 <set>AlignHCenter</set>
161 </property>
162 <property>
163 <name>hAlign</name>
164 </property>
165 </widget>
166 <widget>
167 <class>QLabel</class>
168 <property stdset="1">
169 <name>name</name>
170 <cstring>TextLabel1_2</cstring>
171 </property>
172 <property stdset="1">
173 <name>font</name>
174 <font>
175 <bold>1</bold>
176 </font>
177 </property>
178 <property stdset="1">
179 <name>text</name>
180 <string>:</string>
181 </property>
182 </widget>
183 <widget>
184 <class>QLineEdit</class>
185 <property stdset="1">
186 <name>name</name>
187 <cstring>minuteField</cstring>
188 </property>
189 <property stdset="1">
190 <name>alignment</name>
191 <set>AlignHCenter</set>
192 </property>
193 <property>
194 <name>hAlign</name>
195 </property>
196 </widget>
197 </hbox>
198 </widget>
199 <spacer>
200 <property>
201 <name>name</name>
202 <cstring>Spacer5</cstring>
203 </property>
204 <property stdset="1">
205 <name>orientation</name>
206 <enum>Horizontal</enum>
207 </property>
208 <property stdset="1">
209 <name>sizeType</name>
210 <enum>MinimumExpanding</enum>
211 </property>
212 <property>
213 <name>sizeHint</name>
214 <size>
215 <width>20</width>
216 <height>20</height>
217 </size>
218 </property>
219 </spacer>
220 </hbox>
221 </widget>
222 <widget>
223 <class>QGroupBox</class>
224 <property stdset="1">
225 <name>name</name>
226 <cstring>GroupBox1</cstring>
227 </property>
228 <property stdset="1">
229 <name>sizePolicy</name>
230 <sizepolicy>
231 <hsizetype>3</hsizetype>
232 <vsizetype>3</vsizetype>
233 </sizepolicy>
234 </property>
235 <property stdset="1">
236 <name>margin</name>
237 <number>0</number>
238 </property>
239 <property stdset="1">
240 <name>title</name>
241 <string>Pick Time:</string>
242 </property>
243 <grid>
244 <property stdset="1">
245 <name>margin</name>
246 <number>11</number>
247 </property>
248 <property stdset="1">
249 <name>spacing</name>
250 <number>6</number>
251 </property>
252 <widget row="0" column="0" >
253 <class>OTimePicker</class>
254 <property stdset="1">
255 <name>name</name>
256 <cstring>m_timePicker</cstring>
257 </property>
258 <property stdset="1">
259 <name>sizePolicy</name>
260 <sizepolicy>
261 <hsizetype>3</hsizetype>
262 <vsizetype>3</vsizetype>
263 </sizepolicy>
264 </property>
265 </widget>
266 </grid>
267 </widget>
268 </vbox>
269</widget>
270<customwidgets>
271 <customwidget>
272 <class>OTimePicker</class>
273 <header location="local">otimepicker.h</header>
274 <sizehint>
275 <width>-1</width>
276 <height>-1</height>
277 </sizehint>
278 <container>0</container>
279 <sizepolicy>
280 <hordata>7</hordata>
281 <verdata>1</verdata>
282 </sizepolicy>
283 <pixmap>image0</pixmap>
284 </customwidget>
285</customwidgets>
286<images>
287 <image>
288 <name>image0</name>
289 <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1ddec44f503c0ae2a154410f53d0ed20e2bf6bdb656dd6861dd23d9a66591b0587fd1654235ebded6f0edcd53e419d87ae7b1f4f9b8f906d0bfe012317426a70b07bdc2f3ec77f8ed6b89559061a0343d06a124cc105596482585094bc0ae599b04646c9018926491b2205e140c485cace25755c175d0a967b622ff900b8cc9c7d29af594ea722d589167f813aa852ba07d94b9dce296e883fe7bb163f23896753</data>
290 </image>
291</images>
292</UI>
diff --git a/noncore/unsupported/libopie/owait.cpp b/noncore/unsupported/libopie/owait.cpp
new file mode 100644
index 0000000..a0f3834
--- a/dev/null
+++ b/noncore/unsupported/libopie/owait.cpp
@@ -0,0 +1,91 @@
1/* This file is part of the OPIE libraries
2 Copyright (C) 2003 Maximilian Reiss (harlekin@handhelds.org)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20#include <qlayout.h>
21#include <qpe/qpeapplication.h>
22#include <qpainter.h>
23
24#include "owait.h"
25
26#include <qpe/resource.h>
27
28static int frame = 0;
29
30/**
31 * This will construct a modal dialog.
32 *
33 * The default timer length is 10.
34 *
35 * @param parent The parent of the widget
36 * @param msg The name of the object
37 * @param dispIcon Display Icon?
38 */
39OWait::OWait(QWidget *parent, const char* msg, bool dispIcon )
40 :QDialog(parent, msg, TRUE,WStyle_Customize) {
41
42
43 QHBoxLayout *hbox = new QHBoxLayout( this );
44
45 m_lb = new QLabel( this );
46 m_lb->setBackgroundMode ( NoBackground );
47
48 hbox->addWidget( m_lb );
49 hbox->activate();
50
51 m_pix = Resource::loadPixmap( "BigBusy" );
52 m_aniSize = m_pix.height();
53 resize( m_aniSize, m_aniSize );
54
55 m_timerLength = 10;
56
57 m_waitTimer = new QTimer( this );
58 connect( m_waitTimer, SIGNAL( timeout() ), this, SLOT( hide() ) );
59}
60
61void OWait::timerEvent( QTimerEvent * ) {
62 frame = (++frame) % 4;
63 repaint();
64}
65
66void OWait::paintEvent( QPaintEvent * ) {
67 QPainter p( m_lb );
68 p.drawPixmap( 0, 0, m_pix, m_aniSize * frame, 0, m_aniSize, m_aniSize );
69}
70
71void OWait::show() {
72
73 move( ( ( qApp->desktop()->width() ) / 2 ) - ( m_aniSize / 2 ), ( ( qApp->desktop()->height() ) / 2 ) - ( m_aniSize / 2 ) );
74 startTimer( 300 );
75 m_waitTimer->start( m_timerLength * 1000, true );
76 QDialog::show();
77}
78
79void OWait::hide() {
80 killTimers();
81 m_waitTimer->stop();
82 frame = 0;
83 QDialog::hide();
84}
85
86void OWait::setTimerLength( int length ) {
87 m_timerLength = length;
88}
89
90OWait::~OWait() {
91}
diff --git a/noncore/unsupported/libopie/owait.h b/noncore/unsupported/libopie/owait.h
new file mode 100644
index 0000000..cbfc8d6
--- a/dev/null
+++ b/noncore/unsupported/libopie/owait.h
@@ -0,0 +1,77 @@
1/* This file is part of the OPIE libraries
2 Copyright (C) 2003 Maximilian Reiss (harlekin@handhelds.org)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20
21
22#ifndef WAITPOPUP_H
23#define WAITPOPUP_H
24
25#include <qdialog.h>
26#include <qpixmap.h>
27#include <qlabel.h>
28#include <qtimer.h>
29
30/**
31 * This class displays a animated waiting icon in the middle of the screen.
32 *
33 * @short modal hour glass dialog
34 * @see QDialog
35 * @author Maximilian Reiß
36 */
37class OWait : public QDialog {
38
39 Q_OBJECT
40
41public:
42 // FIXME Wflags -zecke?
43 OWait(QWidget *parent=0,const char* name=0, bool dispIcon=TRUE);
44 ~OWait();
45
46 /**
47 * reimplemented for control reasons
48 */
49 void show();
50
51 /**
52 * Set the time before the icon will be automaticly hidden
53 * The timer will be started once the widget will be shown.
54 * @param length - time in seconds
55 */
56 void setTimerLength( int length );
57
58 public slots:
59 /**
60 * reimplemented for control reasons
61 */
62 void hide();
63
64 private:
65 void timerEvent( QTimerEvent * ) ;
66 void paintEvent( QPaintEvent * );
67
68 QPixmap m_pix;
69 QLabel *m_lb;
70 QTimer *m_waitTimer;
71 int m_timerLength;
72 int m_aniSize;
73 class Private;
74 Private *d;
75};
76
77#endif
diff --git a/noncore/unsupported/libopie/pim/.cvsignore b/noncore/unsupported/libopie/pim/.cvsignore
new file mode 100644
index 0000000..aef62c4
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/.cvsignore
@@ -0,0 +1,2 @@
1config.in
2moc*
diff --git a/noncore/unsupported/libopie/pim/config.in b/noncore/unsupported/libopie/pim/config.in
new file mode 100644
index 0000000..95d3737
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/config.in
@@ -0,0 +1,2 @@
1menu "Pim"
2endmenu
diff --git a/noncore/unsupported/libopie/pim/libopie.pro b/noncore/unsupported/libopie/pim/libopie.pro
new file mode 100644
index 0000000..62f235d
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/libopie.pro
@@ -0,0 +1,64 @@
1TEMPLATE = lib
2CONFIG += qte warn_on release
3HEADERS = ofontmenu.h \
4 tododb.h \
5 todoevent.h todoresource.h \
6 todovcalresource.h xmltree.h \
7 colordialog.h colorpopupmenu.h \
8 oclickablelabel.h oprocctrl.h \
9 oprocess.h odevice.h \
10 otimepicker.h otabwidget.h \
11 otabbar.h otabinfo.h \
12 ofileselector/ofiledialog.h \
13 ofileselector/ofilelistview.h \
14 ofileselector/ofileselector.h \
15 ofileselector/ofileselectoritem.h \
16 ofileselector/ofileview.h \
17 ofileselector/olister.h \
18 ofileselector/olocallister.h \
19 ofileselector/ofileselectormain.h \
20 pim/opimrecord.h \
21 pim/otodo.h \
22 pim/orecordlist.h \
23 pim/opimaccesstemplate.h \
24 pim/opimaccessbackend.h \
25 pim/otodoaccess.h \
26 pim/otodacessbackend.h \
27 pim/ocontact.h \
28 pim/ocontactaccess.h \
29 pim/ocontactaccessbackend.h \
30 pim/ocontactaccessbackend_xml.h \
31 pim/orecord.h
32
33SOURCES = ofontmenu.cc \
34 xmltree.cc \
35 tododb.cpp todoevent.cpp \
36 todovcalresource.cpp colordialog.cpp \
37 colorpopupmenu.cpp oclickablelabel.cpp \
38 oprocctrl.cpp oprocess.cpp \
39 odevice.cpp otimepicker.cpp \
40 otabwidget.cpp otabbar.cpp \
41 ofileselector/ofiledialog.cpp \
42 ofileselector/ofilelistview.cpp \
43 ofileselector/ofileselector.cpp \
44 ofileselector/ofileselectoritem.cpp \
45 ofileselector/ofileview.cpp \
46 ofileselector/olister.cpp \
47 ofileselector/olocallister.cpp \
48 ofileselector/ofileselectormain.cpp \
49 pim/otodo.cpp \
50 pim/opimrecord.cpp \
51 pim/otodoaccess.cpp \
52 pim/otodoaccessbackend.cpp \
53 pim/ocontact.cpp \
54 pim/ocontactaccess.cpp \
55 pim/orecord.cpp
56
57TARGET = opie
58INCLUDEPATH += $(OPIEDIR)/include
59DESTDIR = $(OPIEDIR)/lib$(PROJMAK)
60#VERSION = 1.0.0
61
62INTERFACES = otimepickerbase.ui
63
64include ( $(OPIEDIR)/include.pro )
diff --git a/noncore/unsupported/libopie/pim/obackendfactory.h b/noncore/unsupported/libopie/pim/obackendfactory.h
new file mode 100644
index 0000000..4cdef8b
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/obackendfactory.h
@@ -0,0 +1,197 @@
1/*
2 * Class to manage Backends.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation;
10 * either version 2 of the License, or (at your option) any later
11 * version.
12 * =====================================================================
13 * ToDo: Use plugins
14 * =====================================================================
15 * Version: $Id$
16 * =====================================================================
17 * History:
18 * $Log$
19 * Revision 1.1 2004/11/16 21:46:07 mickeyl
20 * libopie1 goes into unsupported
21 *
22 * Revision 1.9 2003/12/22 10:19:26 eilers
23 * Finishing implementation of sql-backend for datebook. But I have to
24 * port the PIM datebook application to use it, before I could debug the
25 * whole stuff.
26 * Thus, PIM-Database backend is finished, but highly experimental. And some
27 * parts are still generic. For instance, the "queryByExample()" methods are
28 * not (or not fully) implemented. Todo: custom-entries not stored.
29 * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
30 * expression search in the database, which is not supported by sqlite !
31 * Therefore we need either an extended sqlite or a workaround which would
32 * be very slow and memory consuming..
33 *
34 * Revision 1.8 2003/09/22 14:31:16 eilers
35 * Added first experimental incarnation of sql-backend for addressbook.
36 * Some modifications to be able to compile the todo sql-backend.
37 * A lot of changes fill follow...
38 *
39 * Revision 1.7 2003/08/01 12:30:16 eilers
40 * Merging changes from BRANCH_1_0 to HEAD
41 *
42 * Revision 1.6.4.1 2003/06/30 14:34:19 eilers
43 * Patches from Zecke:
44 * Fixing and cleaning up extraMap handling
45 * Adding d_ptr for binary compatibility in the future
46 *
47 * Revision 1.6 2003/04/13 18:07:10 zecke
48 * More API doc
49 * QString -> const QString&
50 * QString = 0l -> QString::null
51 *
52 * Revision 1.5 2003/02/21 23:31:52 zecke
53 * Add XML datebookresource
54 * -clean up todoaccessxml header
55 * -implement some more stuff in the oeven tester
56 * -extend DefaultFactory to not crash and to use datebook
57 *
58 * -reading of OEvents is working nicely.. saving will be added
59 * tomorrow
60 * -fix spelling in ODateBookAcces
61 *
62 * Revision 1.4 2002/10/14 15:55:18 eilers
63 * Redeactivate SQL.. ;)
64 *
65 * Revision 1.3 2002/10/10 17:08:58 zecke
66 * The Cache is finally in place
67 * I tested it with my todolist and it 'works' for 10.000 todos the hits are awesome ;)
68 * The read ahead functionality does not make sense for XMLs backends because most of the stuff is already in memory. While using readahead on SQL makes things a lot faster....
69 * I still have to fully implement read ahead
70 * This change is bic but sc
71 *
72 * Revision 1.2 2002/10/08 09:27:36 eilers
73 * Fixed libopie.pro to include the new pim-API.
74 * The SQL-Stuff is currently deactivated. Otherwise everyone who wants to
75 * compile itself would need to install libsqlite, libopiesql...
76 * Therefore, the backend currently uses XML only..
77 *
78 * Revision 1.1 2002/10/07 17:35:01 eilers
79 * added OBackendFactory for advanced backend access
80 *
81 *
82 * =====================================================================
83 */
84#ifndef OPIE_BACKENDFACTORY_H_
85#define OPIE_BACKENDFACTORY_H_
86
87#include <qstring.h>
88#include <qasciidict.h>
89#include <qpe/config.h>
90
91#include "otodoaccessxml.h"
92#include "ocontactaccessbackend_xml.h"
93#include "odatebookaccessbackend_xml.h"
94
95#ifdef __USE_SQL
96#include "otodoaccesssql.h"
97#include "ocontactaccessbackend_sql.h"
98#include "odatebookaccessbackend_sql.h"
99#endif
100
101class OBackendPrivate;
102
103/**
104 * This class is our factory. It will give us the default implementations
105 * of at least Todolist, Contacts and Datebook. In the future this class will
106 * allow users to switch the backend with ( XML->SQLite ) without the need
107 * to recompile.#
108 * This class as the whole PIM Api is making use of templates
109 *
110 * <pre>
111 * OTodoAccessBackend* backend = OBackEndFactory<OTodoAccessBackend>::Default("todo", QString::null );
112 * backend->load();
113 * </pre>
114 *
115 * @author Stefan Eilers
116 * @version 0.1
117 */
118template<class T>
119class OBackendFactory
120{
121 public:
122 OBackendFactory() {};
123
124 enum BACKENDS {
125 TODO,
126 CONTACT,
127 DATE
128 };
129
130 /**
131 * Returns a backend implementation for backendName
132 * @param backendName the type of the backend
133 * @param appName will be passed on to the backend
134 */
135 static T* Default( const QString backendName, const QString& appName ){
136
137 // __asm__("int3");
138
139 Config config( "pimaccess" );
140 config.setGroup ( backendName );
141 QString backend = config.readEntry( "usebackend" );
142
143 qWarning("Selected backend for %s is: %s", backendName.latin1(), backend.latin1() );
144
145 QAsciiDict<int> dict ( 3 );
146 dict.setAutoDelete ( TRUE );
147
148 dict.insert( "todo", new int (TODO) );
149 dict.insert( "contact", new int (CONTACT) );
150 dict.insert( "datebook", new int(DATE) );
151
152 int *find = dict[ backendName ];
153 if (!find ) return 0;
154
155 switch ( *find ){
156 case TODO:
157#ifdef __USE_SQL
158 if ( backend == "sql" )
159 return (T*) new OTodoAccessBackendSQL("");
160#else
161 if ( backend == "sql" )
162 qWarning ("OBackendFactory:: sql Backend for TODO not implemented! Using XML instead!");
163#endif
164
165 return (T*) new OTodoAccessXML( appName );
166 case CONTACT:
167#ifdef __USE_SQL
168 if ( backend == "sql" )
169 return (T*) new OContactAccessBackend_SQL("");
170#else
171 if ( backend == "sql" )
172 qWarning ("OBackendFactory:: sql Backend for CONTACT not implemented! Using XML instead!");
173#endif
174
175 return (T*) new OContactAccessBackend_XML( appName );
176 case DATE:
177#ifdef __USE_SQL
178 if ( backend == "sql" )
179 return (T*) new ODateBookAccessBackend_SQL("");
180#else
181 if ( backend == "sql" )
182 qWarning("OBackendFactory:: sql Backend for DATEBOOK not implemented! Using XML instead!");
183#endif
184
185 return (T*) new ODateBookAccessBackend_XML( appName );
186 default:
187 return NULL;
188 }
189
190
191 }
192 private:
193 OBackendPrivate* d;
194};
195
196
197#endif
diff --git a/noncore/unsupported/libopie/pim/ocontact.cpp b/noncore/unsupported/libopie/pim/ocontact.cpp
new file mode 100644
index 0000000..fcf3b26
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontact.cpp
@@ -0,0 +1,1207 @@
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** Copyright (C) 2002-2003 by Stefan Eilers (eilers.stefan@epost.de)
4**
5** This file may be distributed and/or modified under the terms of the
6** GNU General Public License version 2 as published by the Free Software
7** Foundation and appearing in the file LICENSE.GPL included in the
8** packaging of this file.
9**
10** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12**
13** See http://www.trolltech.com/gpl/ for GPL licensing information.
14**
15** Contact info@trolltech.com if any conditions of this licensing are
16** not clear to you.
17**
18**********************************************************************/
19
20#define QTOPIA_INTERNAL_CONTACT_MRE
21
22#include "ocontact.h"
23#include "opimresolver.h"
24#include "oconversion.h"
25
26#include <qpe/stringutil.h>
27#include <qpe/timestring.h>
28#include <qpe/config.h>
29
30#include <qobject.h>
31#include <qregexp.h>
32#include <qstylesheet.h>
33#include <qfileinfo.h>
34#include <qmap.h>
35
36#include <stdio.h>
37
38/*!
39 \class Contact contact.h
40 \brief The Contact class holds the data of an address book entry.
41
42 This data includes information the name of the person, contact
43 information, and business information such as deparment and job title.
44
45 \ingroup qtopiaemb
46 \ingroup qtopiadesktop
47*/
48
49
50/*!
51 Creates a new, empty contact.
52*/
53OContact::OContact()
54 : OPimRecord(), mMap(), d( 0 )
55{
56}
57
58/*!
59 \internal
60 Creates a new contact. The properties of the contact are
61 set from \a fromMap.
62*/
63OContact::OContact( const QMap<int, QString> &fromMap ) :
64 OPimRecord(), mMap( fromMap ), d( 0 )
65{
66 QString cats = mMap[ Qtopia::AddressCategory ];
67 if ( !cats.isEmpty() )
68 setCategories( idsFromString( cats ) );
69
70 QString uidStr = find( Qtopia::AddressUid );
71
72 if ( uidStr.isEmpty() || (uidStr.toInt() == 0) ){
73 qWarning( "Invalid UID found. Generate new one.." );
74 setUid( uidGen().generate() );
75 }else
76 setUid( uidStr.toInt() );
77
78// if ( !uidStr.isEmpty() )
79 // setUid( uidStr.toInt() );
80}
81
82/*!
83 Destroys a contact.
84*/
85OContact::~OContact()
86{
87}
88
89/*! \fn void OContact::setTitle( const QString &str )
90 Sets the title of the contact to \a str.
91*/
92
93/*! \fn void OContact::setFirstName( const QString &str )
94 Sets the first name of the contact to \a str.
95*/
96
97/*! \fn void OContact::setMiddleName( const QString &str )
98 Sets the middle name of the contact to \a str.
99*/
100
101/*! \fn void OContact::setLastName( const QString &str )
102 Sets the last name of the contact to \a str.
103*/
104
105/*! \fn void OContact::setSuffix( const QString &str )
106 Sets the suffix of the contact to \a str.
107*/
108
109/*! \fn void OContact::setFileAs( const QString &str )
110 Sets the contact to filed as \a str.
111*/
112
113/*! \fn void OContact::setDefaultEmail( const QString &str )
114 Sets the default email of the contact to \a str.
115*/
116
117/*! \fn void OContact::setHomeStreet( const QString &str )
118 Sets the home street address of the contact to \a str.
119*/
120
121/*! \fn void OContact::setHomeCity( const QString &str )
122 Sets the home city of the contact to \a str.
123*/
124
125/*! \fn void OContact::setHomeState( const QString &str )
126 Sets the home state of the contact to \a str.
127*/
128
129/*! \fn void OContact::setHomeZip( const QString &str )
130 Sets the home zip code of the contact to \a str.
131*/
132
133/*! \fn void OContact::setHomeCountry( const QString &str )
134 Sets the home country of the contact to \a str.
135*/
136
137/*! \fn void OContact::setHomePhone( const QString &str )
138 Sets the home phone number of the contact to \a str.
139*/
140
141/*! \fn void OContact::setHomeFax( const QString &str )
142 Sets the home fax number of the contact to \a str.
143*/
144
145/*! \fn void OContact::setHomeMobile( const QString &str )
146 Sets the home mobile phone number of the contact to \a str.
147*/
148
149/*! \fn void OContact::setHomeWebpage( const QString &str )
150 Sets the home webpage of the contact to \a str.
151*/
152
153/*! \fn void OContact::setCompany( const QString &str )
154 Sets the company for contact to \a str.
155*/
156
157/*! \fn void OContact::setJobTitle( const QString &str )
158 Sets the job title of the contact to \a str.
159*/
160
161/*! \fn void OContact::setDepartment( const QString &str )
162 Sets the department for contact to \a str.
163*/
164
165/*! \fn void OContact::setOffice( const QString &str )
166 Sets the office for contact to \a str.
167*/
168
169/*! \fn void OContact::setBusinessStreet( const QString &str )
170 Sets the business street address of the contact to \a str.
171*/
172
173/*! \fn void OContact::setBusinessCity( const QString &str )
174 Sets the business city of the contact to \a str.
175*/
176
177/*! \fn void OContact::setBusinessState( const QString &str )
178 Sets the business state of the contact to \a str.
179*/
180
181/*! \fn void OContact::setBusinessZip( const QString &str )
182 Sets the business zip code of the contact to \a str.
183*/
184
185/*! \fn void OContact::setBusinessCountry( const QString &str )
186 Sets the business country of the contact to \a str.
187*/
188
189/*! \fn void OContact::setBusinessPhone( const QString &str )
190 Sets the business phone number of the contact to \a str.
191*/
192
193/*! \fn void OContact::setBusinessFax( const QString &str )
194 Sets the business fax number of the contact to \a str.
195*/
196
197/*! \fn void OContact::setBusinessMobile( const QString &str )
198 Sets the business mobile phone number of the contact to \a str.
199*/
200
201/*! \fn void OContact::setBusinessPager( const QString &str )
202 Sets the business pager number of the contact to \a str.
203*/
204
205/*! \fn void OContact::setBusinessWebpage( const QString &str )
206 Sets the business webpage of the contact to \a str.
207*/
208
209/*! \fn void OContact::setProfession( const QString &str )
210 Sets the profession of the contact to \a str.
211*/
212
213/*! \fn void OContact::setAssistant( const QString &str )
214 Sets the assistant of the contact to \a str.
215*/
216
217/*! \fn void OContact::setManager( const QString &str )
218 Sets the manager of the contact to \a str.
219*/
220
221/*! \fn void OContact::setSpouse( const QString &str )
222 Sets the spouse of the contact to \a str.
223*/
224
225/*! \fn void OContact::setGender( const QString &str )
226 Sets the gender of the contact to \a str.
227*/
228
229/*! \fn void OContact::setNickname( const QString &str )
230 Sets the nickname of the contact to \a str.
231*/
232
233/*! \fn void OContact::setNotes( const QString &str )
234 Sets the notes about the contact to \a str.
235*/
236
237/*! \fn QString OContact::title() const
238 Returns the title of the contact.
239*/
240
241/*! \fn QString OContact::firstName() const
242 Returns the first name of the contact.
243*/
244
245/*! \fn QString OContact::middleName() const
246 Returns the middle name of the contact.
247*/
248
249/*! \fn QString OContact::lastName() const
250 Returns the last name of the contact.
251*/
252
253/*! \fn QString OContact::suffix() const
254 Returns the suffix of the contact.
255*/
256
257/*! \fn QString OContact::fileAs() const
258 Returns the string the contact is filed as.
259*/
260
261/*! \fn QString OContact::defaultEmail() const
262 Returns the default email address of the contact.
263*/
264
265/*! \fn QString OContact::emails() const
266 Returns the list of email address for a contact separated by ';'s in a single
267 string.
268*/
269
270/*! \fn QString OContact::homeStreet() const
271 Returns the home street address of the contact.
272*/
273
274/*! \fn QString OContact::homeCity() const
275 Returns the home city of the contact.
276*/
277
278/*! \fn QString OContact::homeState() const
279 Returns the home state of the contact.
280*/
281
282/*! \fn QString OContact::homeZip() const
283 Returns the home zip of the contact.
284*/
285
286/*! \fn QString OContact::homeCountry() const
287 Returns the home country of the contact.
288*/
289
290/*! \fn QString OContact::homePhone() const
291 Returns the home phone number of the contact.
292*/
293
294/*! \fn QString OContact::homeFax() const
295 Returns the home fax number of the contact.
296*/
297
298/*! \fn QString OContact::homeMobile() const
299 Returns the home mobile number of the contact.
300*/
301
302/*! \fn QString OContact::homeWebpage() const
303 Returns the home webpage of the contact.
304*/
305
306/*! \fn QString OContact::company() const
307 Returns the company for the contact.
308*/
309
310/*! \fn QString OContact::department() const
311 Returns the department for the contact.
312*/
313
314/*! \fn QString OContact::office() const
315 Returns the office for the contact.
316*/
317
318/*! \fn QString OContact::jobTitle() const
319 Returns the job title of the contact.
320*/
321
322/*! \fn QString OContact::profession() const
323 Returns the profession of the contact.
324*/
325
326/*! \fn QString OContact::assistant() const
327 Returns the assistant of the contact.
328*/
329
330/*! \fn QString OContact::manager() const
331 Returns the manager of the contact.
332*/
333
334/*! \fn QString OContact::businessStreet() const
335 Returns the business street address of the contact.
336*/
337
338/*! \fn QString OContact::businessCity() const
339 Returns the business city of the contact.
340*/
341
342/*! \fn QString OContact::businessState() const
343 Returns the business state of the contact.
344*/
345
346/*! \fn QString OContact::businessZip() const
347 Returns the business zip of the contact.
348*/
349
350/*! \fn QString OContact::businessCountry() const
351 Returns the business country of the contact.
352*/
353
354/*! \fn QString OContact::businessPhone() const
355 Returns the business phone number of the contact.
356*/
357
358/*! \fn QString OContact::businessFax() const
359 Returns the business fax number of the contact.
360*/
361
362/*! \fn QString OContact::businessMobile() const
363 Returns the business mobile number of the contact.
364*/
365
366/*! \fn QString OContact::businessPager() const
367 Returns the business pager number of the contact.
368*/
369
370/*! \fn QString OContact::businessWebpage() const
371 Returns the business webpage of the contact.
372*/
373
374/*! \fn QString OContact::spouse() const
375 Returns the spouse of the contact.
376*/
377
378/*! \fn QString OContact::gender() const
379 Returns the gender of the contact.
380*/
381
382/*! \fn QString OContact::nickname() const
383 Returns the nickname of the contact.
384*/
385
386/*! \fn QString OContact::children() const
387 Returns the children of the contact.
388*/
389
390/*! \fn QString OContact::notes() const
391 Returns the notes relating to the the contact.
392*/
393
394/*! \fn QString OContact::groups() const
395 \internal
396 Returns the groups for the contact.
397*/
398
399/*! \fn QStringList OContact::groupList() const
400 \internal
401*/
402
403/*! \fn QString OContact::field(int) const
404 \internal
405*/
406
407/*! \fn void OContact::saveJournal( journal_action, const QString & = QString::null )
408 \internal
409*/
410
411/*! \fn void OContact::setUid( int id )
412 \internal
413 Sets the uid for this record to \a id.
414*/
415
416/*! \enum OContact::journal_action
417 \internal
418*/
419
420/*!
421 \internal
422*/
423QMap<int, QString> OContact::toMap() const
424{
425 QMap<int, QString> map = mMap;
426 QString cats = idsToString( categories() );
427 if ( !cats.isEmpty() )
428 map.insert( Qtopia::AddressCategory, cats );
429 return map;
430}
431
432/*!
433 Returns a rich text formatted QString representing the contents the contact.
434*/
435QString OContact::toRichText() const
436{
437 QString text;
438 QString value, comp, state;
439 QString str;
440 bool marker = false;
441
442 Config cfg("qpe");
443 cfg.setGroup("Appearance");
444 int addressformat = cfg.readNumEntry( "AddressFormat", Zip_City_State );
445
446 // name, jobtitle and company
447 if ( !(value = fullName()).isEmpty() )
448 text += "<b><h3><img src=\"addressbook/AddressBook\"> " + Qtopia::escapeString(value) + "</h3></b>";
449
450 if ( !(value = jobTitle()).isEmpty() )
451 text += Qtopia::escapeString(value) + " ";
452
453 comp = company();
454 if ( !(value = department()).isEmpty() ) {
455 text += Qtopia::escapeString(value);
456 if ( comp )
457 text += ", " + Qtopia::escapeString(comp);
458 }else if ( comp )
459 text += "<br>" + Qtopia::escapeString(comp);
460 text += "<br><hr>";
461
462 // defailt email
463 QString defEmail = defaultEmail();
464 if ( !defEmail.isEmpty() ){
465 text += "<b><img src=\"addressbook/email\"> " + QObject::tr("Default Email: ") + "</b>"
466 + Qtopia::escapeString(defEmail);
467 marker = true;
468 }
469
470 // business address
471 if ( !businessStreet().isEmpty() || !businessCity().isEmpty() ||
472 !businessZip().isEmpty() || !businessCountry().isEmpty() ) {
473 text += QObject::tr( "<br><b>Work Address:</b>" );
474 marker = true;
475 }
476
477 if ( !(value = businessStreet()).isEmpty() ){
478 text += "<br>" + Qtopia::escapeString(value);
479 marker = true;
480 }
481
482 switch( addressformat ){
483 case Zip_City_State:{ // Zip_Code City, State
484 state = businessState();
485 if ( !(value = businessZip()).isEmpty() ){
486 text += "<br>" + Qtopia::escapeString(value) + " ";
487 marker = true;
488
489 }
490 if ( !(value = businessCity()).isEmpty() ) {
491 marker = true;
492 if ( businessZip().isEmpty() && !businessStreet().isEmpty() )
493 text += "<br>";
494 text += Qtopia::escapeString(value);
495 if ( state )
496 text += ", " + Qtopia::escapeString(state);
497 } else if ( !state.isEmpty() ){
498 text += "<br>" + Qtopia::escapeString(state);
499 marker = true;
500 }
501 break;
502 }
503 case City_State_Zip:{ // City, State Zip_Code
504 state = businessState();
505 if ( !(value = businessCity()).isEmpty() ) {
506 marker = true;
507 text += "<br>" + Qtopia::escapeString(value);
508 if ( state )
509 text += ", " + Qtopia::escapeString(state);
510 } else if ( !state.isEmpty() ){
511 text += "<br>" + Qtopia::escapeString(state);
512 marker = true;
513 }
514 if ( !(value = businessZip()).isEmpty() ){
515 text += " " + Qtopia::escapeString(value);
516 marker = true;
517 }
518 break;
519 }
520 }
521
522 if ( !(value = businessCountry()).isEmpty() ){
523 text += "<br>" + Qtopia::escapeString(value);
524 marker = true;
525 }
526
527 // rest of Business data
528 str = office();
529 if ( !str.isEmpty() ){
530 text += "<br><b>" + QObject::tr("Office: ") + "</b>"
531 + Qtopia::escapeString(str);
532 marker = true;
533 }
534 str = businessWebpage();
535 if ( !str.isEmpty() ){
536 text += "<br><b><img src=\"addressbook/webpagework\"> " + QObject::tr("Business Web Page: ") + "</b>"
537 + Qtopia::escapeString(str);
538 marker = true;
539 }
540 str = businessPhone();
541 if ( !str.isEmpty() ){
542 text += "<br><b><img src=\"addressbook/phonework\"> " + QObject::tr("Business Phone: ") + "</b>"
543 + Qtopia::escapeString(str);
544 marker = true;
545 }
546 str = businessFax();
547 if ( !str.isEmpty() ){
548 text += "<br><b><img src=\"addressbook/faxwork\"> " + QObject::tr("Business Fax: ") + "</b>"
549 + Qtopia::escapeString(str);
550 marker = true;
551 }
552 str = businessMobile();
553 if ( !str.isEmpty() ){
554 text += "<br><b><img src=\"addressbook/mobilework\"> " + QObject::tr("Business Mobile: ") + "</b>"
555 + Qtopia::escapeString(str);
556 marker = true;
557 }
558 str = businessPager();
559 if ( !str.isEmpty() ){
560 text += "<br><b>" + QObject::tr("Business Pager: ") + "</b>"
561 + Qtopia::escapeString(str);
562 marker = true;
563 }
564
565 // text += "<br>";
566
567 // home address
568 if ( !homeStreet().isEmpty() || !homeCity().isEmpty() ||
569 !homeZip().isEmpty() || !homeCountry().isEmpty() ) {
570 text += QObject::tr( "<br><b>Home Address:</b>" );
571 marker = true;
572 }
573
574 if ( !(value = homeStreet()).isEmpty() ){
575 text += "<br>" + Qtopia::escapeString(value);
576 marker = true;
577 }
578
579 switch( addressformat ){
580 case Zip_City_State:{ // Zip_Code City, State
581 state = homeState();
582 if ( !(value = homeZip()).isEmpty() ){
583 text += "<br>" + Qtopia::escapeString(value) + " ";
584 marker = true;
585 }
586 if ( !(value = homeCity()).isEmpty() ) {
587 marker = true;
588 if ( homeZip().isEmpty() && !homeStreet().isEmpty() )
589 text += "<br>";
590 text += Qtopia::escapeString(value);
591 if ( !state.isEmpty() )
592 text += ", " + Qtopia::escapeString(state);
593 } else if (!state.isEmpty()) {
594 text += "<br>" + Qtopia::escapeString(state);
595 marker = true;
596 }
597 break;
598 }
599 case City_State_Zip:{ // City, State Zip_Code
600 state = homeState();
601 if ( !(value = homeCity()).isEmpty() ) {
602 marker = true;
603 text += "<br>" + Qtopia::escapeString(value);
604 if ( state )
605 text += ", " + Qtopia::escapeString(state);
606 } else if ( !state.isEmpty() ){
607 text += "<br>" + Qtopia::escapeString(state);
608 marker = true;
609 }
610 if ( !(value = homeZip()).isEmpty() ){
611 text += " " + Qtopia::escapeString(value);
612 marker = true;
613 }
614 break;
615 }
616 }
617
618 if ( !(value = homeCountry()).isEmpty() ){
619 text += "<br>" + Qtopia::escapeString(value);
620 marker = true;
621 }
622
623 // rest of Home data
624 str = homeWebpage();
625 if ( !str.isEmpty() ){
626 text += "<br><b><img src=\"addressbook/webpagehome\"> " + QObject::tr("Home Web Page: ") + "</b>"
627 + Qtopia::escapeString(str);
628 marker = true;
629 }
630 str = homePhone();
631 if ( !str.isEmpty() ){
632 text += "<br><b><img src=\"addressbook/phonehome\"> " + QObject::tr("Home Phone: ") + "</b>"
633 + Qtopia::escapeString(str);
634 marker = true;
635 }
636 str = homeFax();
637 if ( !str.isEmpty() ){
638 text += "<br><b><img src=\"addressbook/faxhome\"> " + QObject::tr("Home Fax: ") + "</b>"
639 + Qtopia::escapeString(str);
640 marker = true;
641 }
642 str = homeMobile();
643 if ( !str.isEmpty() ){
644 text += "<br><b><img src=\"addressbook/mobilehome\"> " + QObject::tr("Home Mobile: ") + "</b>"
645 + Qtopia::escapeString(str);
646 marker = true;
647 }
648
649 if ( marker )
650 text += "<br><hr>";
651
652 // the rest...
653 str = emails();
654 if ( !str.isEmpty() && ( str != defEmail ) )
655 text += "<br><b>" + QObject::tr("All Emails: ") + "</b>"
656 + Qtopia::escapeString(str);
657 str = profession();
658 if ( !str.isEmpty() )
659 text += "<br><b>" + QObject::tr("Profession: ") + "</b>"
660 + Qtopia::escapeString(str);
661 str = assistant();
662 if ( !str.isEmpty() )
663 text += "<br><b>" + QObject::tr("Assistant: ") + "</b>"
664 + Qtopia::escapeString(str);
665 str = manager();
666 if ( !str.isEmpty() )
667 text += "<br><b>" + QObject::tr("Manager: ") + "</b>"
668 + Qtopia::escapeString(str);
669 str = gender();
670 if ( !str.isEmpty() && str.toInt() != 0 ) {
671 text += "<br>";
672 if ( str.toInt() == 1 )
673 str = QObject::tr( "Male" );
674 else if ( str.toInt() == 2 )
675 str = QObject::tr( "Female" );
676 text += "<b>" + QObject::tr("Gender: ") + "</b>" + str;
677 }
678 str = spouse();
679 if ( !str.isEmpty() )
680 text += "<br><b>" + QObject::tr("Spouse: ") + "</b>"
681 + Qtopia::escapeString(str);
682 if ( birthday().isValid() ){
683 str = TimeString::numberDateString( birthday() );
684 text += "<br><b>" + QObject::tr("Birthday: ") + "</b>"
685 + Qtopia::escapeString(str);
686 }
687 if ( anniversary().isValid() ){
688 str = TimeString::numberDateString( anniversary() );
689 text += "<br><b>" + QObject::tr("Anniversary: ") + "</b>"
690 + Qtopia::escapeString(str);
691 }
692 str = children();
693 if ( !str.isEmpty() )
694 text += "<br><b>" + QObject::tr("Children: ") + "</b>"
695 + Qtopia::escapeString(str);
696
697 str = nickname();
698 if ( !str.isEmpty() )
699 text += "<br><b>" + QObject::tr("Nickname: ") + "</b>"
700 + Qtopia::escapeString(str);
701
702 // categories
703 if ( categoryNames("Contacts").count() ){
704 text += "<br><b>" + QObject::tr( "Category:") + "</b> ";
705 text += categoryNames("Contacts").join(", ");
706 }
707
708 // notes last
709 if ( !(value = notes()).isEmpty() ) {
710 text += "<br><hr><b>" + QObject::tr( "Notes:") + "</b> ";
711 QRegExp reg("\n");
712
713 //QString tmp = Qtopia::escapeString(value);
714 QString tmp = QStyleSheet::convertFromPlainText(value);
715 //tmp.replace( reg, "<br>" );
716 text += "<br>" + tmp + "<br>";
717 }
718 return text;
719}
720
721/*!
722 \internal
723*/
724void OContact::insert( int key, const QString &v )
725{
726 QString value = v.stripWhiteSpace();
727 if ( value.isEmpty() )
728 mMap.remove( key );
729 else
730 mMap.insert( key, value );
731}
732
733/*!
734 \internal
735*/
736void OContact::replace( int key, const QString & v )
737{
738 QString value = v.stripWhiteSpace();
739 if ( value.isEmpty() )
740 mMap.remove( key );
741 else
742 mMap.replace( key, value );
743}
744
745/*!
746 \internal
747*/
748QString OContact::find( int key ) const
749{
750 return mMap[key];
751}
752
753/*!
754 \internal
755*/
756QString OContact::displayAddress( const QString &street,
757 const QString &city,
758 const QString &state,
759 const QString &zip,
760 const QString &country ) const
761{
762 QString s = street;
763 if ( !street.isEmpty() )
764 s+= "\n";
765 s += city;
766 if ( !city.isEmpty() && !state.isEmpty() )
767 s += ", ";
768 s += state;
769 if ( !state.isEmpty() && !zip.isEmpty() )
770 s += " ";
771 s += zip;
772 if ( !country.isEmpty() && !s.isEmpty() )
773 s += "\n";
774 s += country;
775 return s;
776}
777
778/*!
779 \internal
780*/
781QString OContact::displayBusinessAddress() const
782{
783 return displayAddress( businessStreet(), businessCity(),
784 businessState(), businessZip(),
785 businessCountry() );
786}
787
788/*!
789 \internal
790*/
791QString OContact::displayHomeAddress() const
792{
793 return displayAddress( homeStreet(), homeCity(),
794 homeState(), homeZip(),
795 homeCountry() );
796}
797
798/*!
799 Returns the full name of the contact
800*/
801QString OContact::fullName() const
802{
803 QString title = find( Qtopia::Title );
804 QString firstName = find( Qtopia::FirstName );
805 QString middleName = find( Qtopia::MiddleName );
806 QString lastName = find( Qtopia::LastName );
807 QString suffix = find( Qtopia::Suffix );
808
809 QString name = title;
810 if ( !firstName.isEmpty() ) {
811 if ( !name.isEmpty() )
812 name += " ";
813 name += firstName;
814 }
815 if ( !middleName.isEmpty() ) {
816 if ( !name.isEmpty() )
817 name += " ";
818 name += middleName;
819 }
820 if ( !lastName.isEmpty() ) {
821 if ( !name.isEmpty() )
822 name += " ";
823 name += lastName;
824 }
825 if ( !suffix.isEmpty() ) {
826 if ( !name.isEmpty() )
827 name += " ";
828 name += suffix;
829 }
830 return name.simplifyWhiteSpace();
831}
832
833/*!
834 Returns a list of the names of the children of the contact.
835*/
836QStringList OContact::childrenList() const
837{
838 return QStringList::split( " ", find( Qtopia::Children ) );
839}
840
841/*! \fn void OContact::insertEmail( const QString &email )
842
843 Insert \a email into the email list. Ensures \a email can only be added
844 once. If there is no default email address set, it sets it to the \a email.
845*/
846
847/*! \fn void OContact::removeEmail( const QString &email )
848
849 Removes the \a email from the email list. If the default email was \a email,
850 then the default email address is assigned to the first email in the
851 email list
852*/
853
854/*! \fn void OContact::clearEmails()
855
856 Clears the email list.
857 */
858
859/*! \fn void OContact::insertEmails( const QStringList &emailList )
860
861 Appends the \a emailList to the exiting email list
862 */
863
864/*!
865 Returns a list of email addresses belonging to the contact, including
866 the default email address.
867*/
868QStringList OContact::emailList() const
869{
870 QString emailStr = emails();
871
872 QStringList r;
873 if ( !emailStr.isEmpty() ) {
874 qDebug(" emailstr ");
875 QStringList l = QStringList::split( emailSeparator(), emailStr );
876 for ( QStringList::ConstIterator it = l.begin();it != l.end();++it )
877 r += (*it).simplifyWhiteSpace();
878 }
879
880 return r;
881}
882
883/*!
884 \overload
885
886 Generates the string for the contact to be filed as from the first,
887 middle and last name of the contact.
888*/
889void OContact::setFileAs()
890{
891 QString lastName, firstName, middleName, fileas;
892
893 lastName = find( Qtopia::LastName );
894 firstName = find( Qtopia::FirstName );
895 middleName = find( Qtopia::MiddleName );
896 if ( !lastName.isEmpty() && !firstName.isEmpty()
897 && !middleName.isEmpty() )
898 fileas = lastName + ", " + firstName + " " + middleName;
899 else if ( !lastName.isEmpty() && !firstName.isEmpty() )
900 fileas = lastName + ", " + firstName;
901 else if ( !lastName.isEmpty() || !firstName.isEmpty() ||
902 !middleName.isEmpty() )
903 fileas = firstName + ( firstName.isEmpty() ? "" : " " )
904 + middleName + ( middleName.isEmpty() ? "" : " " )
905 + lastName;
906
907 replace( Qtopia::FileAs, fileas );
908}
909
910/*!
911 \internal
912 Appends the contact information to \a buf.
913*/
914void OContact::save( QString &buf ) const
915{
916 static const QStringList SLFIELDS = fields();
917 // I'm expecting "<Contact " in front of this...
918 for ( QMap<int, QString>::ConstIterator it = mMap.begin();
919 it != mMap.end(); ++it ) {
920 const QString &value = it.data();
921 int key = it.key();
922 if ( !value.isEmpty() ) {
923 if ( key == Qtopia::AddressCategory || key == Qtopia::AddressUid)
924 continue;
925
926 key -= Qtopia::AddressCategory+1;
927 buf += SLFIELDS[key];
928 buf += "=\"" + Qtopia::escapeString(value) + "\" ";
929 }
930 }
931 buf += customToXml();
932 if ( categories().count() > 0 )
933 buf += "Categories=\"" + idsToString( categories() ) + "\" ";
934 buf += "Uid=\"" + QString::number( uid() ) + "\" ";
935 // You need to close this yourself
936}
937
938
939/*!
940 \internal
941 Returns the list of fields belonging to a contact
942 Never change order of this list ! It has to be regarding
943 enum AddressBookFields !!
944*/
945QStringList OContact::fields()
946{
947 QStringList list;
948
949 list.append( "Title" ); // Not Used!
950 list.append( "FirstName" );
951 list.append( "MiddleName" );
952 list.append( "LastName" );
953 list.append( "Suffix" );
954 list.append( "FileAs" );
955
956 list.append( "JobTitle" );
957 list.append( "Department" );
958 list.append( "Company" );
959 list.append( "BusinessPhone" );
960 list.append( "BusinessFax" );
961 list.append( "BusinessMobile" );
962
963 list.append( "DefaultEmail" );
964 list.append( "Emails" );
965
966 list.append( "HomePhone" );
967 list.append( "HomeFax" );
968 list.append( "HomeMobile" );
969
970 list.append( "BusinessStreet" );
971 list.append( "BusinessCity" );
972 list.append( "BusinessState" );
973 list.append( "BusinessZip" );
974 list.append( "BusinessCountry" );
975 list.append( "BusinessPager" );
976 list.append( "BusinessWebPage" );
977
978 list.append( "Office" );
979 list.append( "Profession" );
980 list.append( "Assistant" );
981 list.append( "Manager" );
982
983 list.append( "HomeStreet" );
984 list.append( "HomeCity" );
985 list.append( "HomeState" );
986 list.append( "HomeZip" );
987 list.append( "HomeCountry" );
988 list.append( "HomeWebPage" );
989
990 list.append( "Spouse" );
991 list.append( "Gender" );
992 list.append( "Birthday" );
993 list.append( "Anniversary" );
994 list.append( "Nickname" );
995 list.append( "Children" );
996
997 list.append( "Notes" );
998 list.append( "Groups" );
999
1000 return list;
1001}
1002
1003
1004/*!
1005 Sets the list of email address for contact to those contained in \a str.
1006 Email address should be separated by ';'s.
1007*/
1008void OContact::setEmails( const QString &str )
1009{
1010 replace( Qtopia::Emails, str );
1011 if ( str.isEmpty() )
1012 setDefaultEmail( QString::null );
1013}
1014
1015/*!
1016 Sets the list of children for the contact to those contained in \a str.
1017*/
1018void OContact::setChildren( const QString &str )
1019{
1020 replace( Qtopia::Children, str );
1021}
1022
1023/*!
1024 \overload
1025 Returns TRUE if the contact matches the regular expression \a regexp.
1026 Otherwise returns FALSE.
1027*/
1028bool OContact::match( const QRegExp &r ) const
1029{
1030 setLastHitField( -1 );
1031 bool match;
1032 match = false;
1033 QMap<int, QString>::ConstIterator it;
1034 for ( it = mMap.begin(); it != mMap.end(); ++it ) {
1035 if ( (*it).find( r ) > -1 ) {
1036 setLastHitField( it.key() );
1037 match = true;
1038 break;
1039 }
1040 }
1041 return match;
1042}
1043
1044
1045QString OContact::toShortText() const
1046{
1047 return ( fullName() );
1048}
1049QString OContact::type() const
1050{
1051 return QString::fromLatin1( "OContact" );
1052}
1053
1054
1055
1056class QString OContact::recordField( int pos ) const
1057{
1058 QStringList SLFIELDS = fields(); // ?? why this ? (se)
1059 return SLFIELDS[pos];
1060}
1061
1062// In future releases, we should store birthday and anniversary
1063// internally as QDate instead of QString !
1064// QString is always too complicate to interprete (DD.MM.YY, DD/MM/YY, MM/DD/YY, etc..)(se)
1065
1066/*! \fn void OContact::setBirthday( const QDate& date )
1067 Sets the birthday for the contact to \a date. If date is null
1068 the current stored date will be removed.
1069*/
1070void OContact::setBirthday( const QDate &v )
1071{
1072 if ( v.isNull() ){
1073 qWarning( "Remove Birthday");
1074 replace( Qtopia::Birthday, QString::null );
1075 return;
1076 }
1077
1078 if ( v.isValid() )
1079 replace( Qtopia::Birthday, OConversion::dateToString( v ) );
1080
1081}
1082
1083
1084/*! \fn void OContact::setAnniversary( const QDate &date )
1085 Sets the anniversary of the contact to \a date. If date is
1086 null, the current stored date will be removed.
1087*/
1088void OContact::setAnniversary( const QDate &v )
1089{
1090 if ( v.isNull() ){
1091 qWarning( "Remove Anniversary");
1092 replace( Qtopia::Anniversary, QString::null );
1093 return;
1094 }
1095
1096 if ( v.isValid() )
1097 replace( Qtopia::Anniversary, OConversion::dateToString( v ) );
1098}
1099
1100/*! \fn QDate OContact::birthday() const
1101 Returns the birthday of the contact.
1102*/
1103QDate OContact::birthday() const
1104{
1105 QString str = find( Qtopia::Birthday );
1106 // qWarning ("Birthday %s", str.latin1() );
1107 if ( !str.isEmpty() )
1108 return OConversion::dateFromString ( str );
1109 else
1110 return QDate();
1111}
1112
1113
1114/*! \fn QDate OContact::anniversary() const
1115 Returns the anniversary of the contact.
1116*/
1117QDate OContact::anniversary() const
1118{
1119 QDate empty;
1120 QString str = find( Qtopia::Anniversary );
1121 // qWarning ("Anniversary %s", str.latin1() );
1122 if ( !str.isEmpty() )
1123 return OConversion::dateFromString ( str );
1124 else
1125 return empty;
1126}
1127
1128
1129void OContact::insertEmail( const QString &v )
1130{
1131 //qDebug("insertEmail %s", v.latin1());
1132 QString e = v.simplifyWhiteSpace();
1133 QString def = defaultEmail();
1134
1135 // if no default, set it as the default email and don't insert
1136 if ( def.isEmpty() ) {
1137 setDefaultEmail( e ); // will insert into the list for us
1138 return;
1139 }
1140
1141 // otherwise, insert assuming doesn't already exist
1142 QString emailsStr = find( Qtopia::Emails );
1143 if ( emailsStr.contains( e ))
1144 return;
1145 if ( !emailsStr.isEmpty() )
1146 emailsStr += emailSeparator();
1147 emailsStr += e;
1148 replace( Qtopia::Emails, emailsStr );
1149}
1150
1151void OContact::removeEmail( const QString &v )
1152{
1153 QString e = v.simplifyWhiteSpace();
1154 QString def = defaultEmail();
1155 QString emailsStr = find( Qtopia::Emails );
1156 QStringList emails = emailList();
1157
1158 // otherwise, must first contain it
1159 if ( !emailsStr.contains( e ) )
1160 return;
1161
1162 // remove it
1163 //qDebug(" removing email from list %s", e.latin1());
1164 emails.remove( e );
1165 // reset the string
1166 emailsStr = emails.join(emailSeparator()); // Sharp's brain dead separator
1167 replace( Qtopia::Emails, emailsStr );
1168
1169 // if default, then replace the default email with the first one
1170 if ( def == e ) {
1171 //qDebug("removeEmail is default; setting new default");
1172 if ( !emails.count() )
1173 clearEmails();
1174 else // setDefaultEmail will remove e from the list
1175 setDefaultEmail( emails.first() );
1176 }
1177}
1178void OContact::clearEmails()
1179{
1180 mMap.remove( Qtopia::DefaultEmail );
1181 mMap.remove( Qtopia::Emails );
1182}
1183void OContact::setDefaultEmail( const QString &v )
1184{
1185 QString e = v.simplifyWhiteSpace();
1186
1187 //qDebug("OContact::setDefaultEmail %s", e.latin1());
1188 replace( Qtopia::DefaultEmail, e );
1189
1190 if ( !e.isEmpty() )
1191 insertEmail( e );
1192
1193}
1194
1195void OContact::insertEmails( const QStringList &v )
1196{
1197 for ( QStringList::ConstIterator it = v.begin(); it != v.end(); ++it )
1198 insertEmail( *it );
1199}
1200int OContact::rtti() {
1201 return OPimResolver::AddressBook;
1202}
1203void OContact::setUid( int i )
1204{
1205 OPimRecord::setUid(i);
1206 replace( Qtopia::AddressUid , QString::number(i));
1207}
diff --git a/noncore/unsupported/libopie/pim/ocontact.h b/noncore/unsupported/libopie/pim/ocontact.h
new file mode 100644
index 0000000..1d46b81
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontact.h
@@ -0,0 +1,240 @@
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** Copyright (C) 2002-2003 by Stefan Eilers (eilers.stefan@epost.de)
4**
5** This file may be distributed and/or modified under the terms of the
6** GNU General Public License version 2 as published by the Free Software
7** Foundation and appearing in the file LICENSE.GPL included in the
8** packaging of this file.
9**
10** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12**
13** See http://www.trolltech.com/gpl/ for GPL licensing information.
14**
15** Contact info@trolltech.com if any conditions of this licensing are
16** not clear to you.
17**
18**********************************************************************/
19
20#ifndef __OCONTACT_H__
21#define __OCONTACT_H__
22
23#include <opie/opimrecord.h>
24#include <qpe/recordfields.h>
25
26#include <qdatetime.h>
27#include <qstringlist.h>
28
29#if defined(QPC_TEMPLATEDLL)
30// MOC_SKIP_BEGIN
31QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<int, QString>;
32// MOC_SKIP_END
33#endif
34
35class OContactPrivate;
36
37/**
38 * OContact class represents a specialised PIM Record for contacts.
39 * It does store all kind of persopn related information.
40 *
41 * @short Contact Container
42 * @author TT, Stefan Eiler, Holger Freyther
43 */
44class QPC_EXPORT OContact : public OPimRecord
45{
46 friend class DataSet;
47public:
48 OContact();
49 OContact( const QMap<int, QString> &fromMap );
50 virtual ~OContact();
51
52 enum DateFormat{
53 Zip_City_State = 0,
54 City_State_Zip
55 };
56
57 /*
58 * do we need to inline them
59 * if yes do we need to inline them this way?
60 * -zecke
61 */
62 void setTitle( const QString &v ) { replace( Qtopia::Title, v ); }
63 void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); }
64 void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); }
65 void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); }
66 void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); }
67 void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); }
68 void setFileAs();
69
70 // default email address
71 void setDefaultEmail( const QString &v );
72 // inserts email to list and ensure's doesn't already exist
73 void insertEmail( const QString &v );
74 void removeEmail( const QString &v );
75 void clearEmails();
76 void insertEmails( const QStringList &v );
77
78 // home
79 void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); }
80 void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); }
81 void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); }
82 void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); }
83 void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); }
84 void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); }
85 void setHomeFax( const QString &v ) { replace( Qtopia::HomeFax, v ); }
86 void setHomeMobile( const QString &v ) { replace( Qtopia::HomeMobile, v ); }
87 void setHomeWebpage( const QString &v ) { replace( Qtopia::HomeWebPage, v ); }
88
89 // business
90 void setCompany( const QString &v ) { replace( Qtopia::Company, v ); }
91 void setBusinessStreet( const QString &v ) { replace( Qtopia::BusinessStreet, v ); }
92 void setBusinessCity( const QString &v ) { replace( Qtopia::BusinessCity, v ); }
93 void setBusinessState( const QString &v ) { replace( Qtopia::BusinessState, v ); }
94 void setBusinessZip( const QString &v ) { replace( Qtopia::BusinessZip, v ); }
95 void setBusinessCountry( const QString &v ) { replace( Qtopia::BusinessCountry, v ); }
96 void setBusinessWebpage( const QString &v ) { replace( Qtopia::BusinessWebPage, v ); }
97 void setJobTitle( const QString &v ) { replace( Qtopia::JobTitle, v ); }
98 void setDepartment( const QString &v ) { replace( Qtopia::Department, v ); }
99 void setOffice( const QString &v ) { replace( Qtopia::Office, v ); }
100 void setBusinessPhone( const QString &v ) { replace( Qtopia::BusinessPhone, v ); }
101 void setBusinessFax( const QString &v ) { replace( Qtopia::BusinessFax, v ); }
102 void setBusinessMobile( const QString &v ) { replace( Qtopia::BusinessMobile, v ); }
103 void setBusinessPager( const QString &v ) { replace( Qtopia::BusinessPager, v ); }
104 void setProfession( const QString &v ) { replace( Qtopia::Profession, v ); }
105 void setAssistant( const QString &v ) { replace( Qtopia::Assistant, v ); }
106 void setManager( const QString &v ) { replace( Qtopia::Manager, v ); }
107
108 // personal
109 void setSpouse( const QString &v ) { replace( Qtopia::Spouse, v ); }
110 void setGender( const QString &v ) { replace( Qtopia::Gender, v ); }
111 void setBirthday( const QDate &v );
112 void setAnniversary( const QDate &v );
113 void setNickname( const QString &v ) { replace( Qtopia::Nickname, v ); }
114 void setChildren( const QString &v );
115
116 // other
117 void setNotes( const QString &v ) { replace( Qtopia::Notes, v); }
118
119 virtual bool match( const QRegExp &regexp ) const;
120
121// // custom
122// void setCustomField( const QString &key, const QString &v )
123// { replace(Custom- + key, v ); }
124
125 // name
126 QString fullName() const;
127 QString title() const { return find( Qtopia::Title ); }
128 QString firstName() const { return find( Qtopia::FirstName ); }
129 QString middleName() const { return find( Qtopia::MiddleName ); }
130 QString lastName() const { return find( Qtopia::LastName ); }
131 QString suffix() const { return find( Qtopia::Suffix ); }
132 QString fileAs() const { return find( Qtopia::FileAs ); }
133
134 // email
135 QString defaultEmail() const { return find( Qtopia::DefaultEmail ); }
136 QStringList emailList() const;
137
138 // home
139 /*
140 * OPimAddress address(enum Location)const;
141 * would be some how nicer...
142 * -zecke
143 */
144 QString homeStreet() const { return find( Qtopia::HomeStreet ); }
145 QString homeCity() const { return find( Qtopia::HomeCity ); }
146 QString homeState() const { return find( Qtopia::HomeState ); }
147 QString homeZip() const { return find( Qtopia::HomeZip ); }
148 QString homeCountry() const { return find( Qtopia::HomeCountry ); }
149 QString homePhone() const { return find( Qtopia::HomePhone ); }
150 QString homeFax() const { return find( Qtopia::HomeFax ); }
151 QString homeMobile() const { return find( Qtopia::HomeMobile ); }
152 QString homeWebpage() const { return find( Qtopia::HomeWebPage ); }
153 /** Multi line string containing all non-empty address info in the form
154 * Street
155 * City, State Zip
156 * Country
157 */
158 QString displayHomeAddress() const;
159
160 // business
161 QString company() const { return find( Qtopia::Company ); }
162 QString businessStreet() const { return find( Qtopia::BusinessStreet ); }
163 QString businessCity() const { return find( Qtopia::BusinessCity ); }
164 QString businessState() const { return find( Qtopia::BusinessState ); }
165 QString businessZip() const { return find( Qtopia::BusinessZip ); }
166 QString businessCountry() const { return find( Qtopia::BusinessCountry ); }
167 QString businessWebpage() const { return find( Qtopia::BusinessWebPage ); }
168 QString jobTitle() const { return find( Qtopia::JobTitle ); }
169 QString department() const { return find( Qtopia::Department ); }
170 QString office() const { return find( Qtopia::Office ); }
171 QString businessPhone() const { return find( Qtopia::BusinessPhone ); }
172 QString businessFax() const { return find( Qtopia::BusinessFax ); }
173 QString businessMobile() const { return find( Qtopia::BusinessMobile ); }
174 QString businessPager() const { return find( Qtopia::BusinessPager ); }
175 QString profession() const { return find( Qtopia::Profession ); }
176 QString assistant() const { return find( Qtopia::Assistant ); }
177 QString manager() const { return find( Qtopia::Manager ); }
178 /** Multi line string containing all non-empty address info in the form
179 * Street
180 * City, State Zip
181 * Country
182 */
183 QString displayBusinessAddress() const;
184
185 //personal
186 QString spouse() const { return find( Qtopia::Spouse ); }
187 QString gender() const { return find( Qtopia::Gender ); }
188 QDate birthday() const;
189 QDate anniversary() const;
190 QString nickname() const { return find( Qtopia::Nickname ); }
191 QString children() const { return find( Qtopia::Children ); }
192 QStringList childrenList() const;
193
194 // other
195 QString notes() const { return find( Qtopia::Notes ); }
196 QString groups() const { return find( Qtopia::Groups ); }
197 QStringList groupList() const;
198
199 QString toRichText() const;
200 QMap<int, QString> toMap() const;
201 QString field( int key ) const { return find( key ); }
202
203
204 void setUid( int i );
205
206 QString toShortText()const;
207 QString type()const;
208 class QString recordField(int) const;
209
210 // Why private ? (eilers,se)
211 QString emailSeparator() const { return " "; }
212
213 // the emails should be seperated by a comma
214 void setEmails( const QString &v );
215 QString emails() const { return find( Qtopia::Emails ); }
216 static int rtti();
217
218private:
219 // The XML Backend needs some access to the private functions
220 friend class OContactAccessBackend_XML;
221
222 void insert( int key, const QString &value );
223 void replace( int key, const QString &value );
224 QString find( int key ) const;
225 static QStringList fields();
226
227 void save( QString &buf ) const;
228
229 QString displayAddress( const QString &street,
230 const QString &city,
231 const QString &state,
232 const QString &zip,
233 const QString &country ) const;
234
235 QMap<int, QString> mMap;
236 OContactPrivate *d;
237};
238
239
240#endif
diff --git a/noncore/unsupported/libopie/pim/ocontactaccess.cpp b/noncore/unsupported/libopie/pim/ocontactaccess.cpp
new file mode 100644
index 0000000..63b93ee
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontactaccess.cpp
@@ -0,0 +1,176 @@
1/*
2 * Class to manage the Contacts.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * Info: This class could just work with a change in the header-file
13 * of the Contact class ! Therefore our libopie only compiles
14 * with our version of libqpe
15 * =====================================================================
16 * ToDo: XML-Backend: Automatic reload if something was changed...
17 *
18 *
19 * =====================================================================
20 * Version: $Id$
21 * =====================================================================
22 * History:
23 * $Log$
24 * Revision 1.1 2004/11/16 21:46:07 mickeyl
25 * libopie1 goes into unsupported
26 *
27 * Revision 1.9 2004/03/02 12:14:22 alwin
28 * run the optimize_connect script
29 * the whole cvs is tagged with "before_optimize_connect" if there are problems you
30 * can check the diff (but it had compiled and run here)
31 *
32 * Revision 1.8 2003/05/08 13:55:09 tille
33 * search stuff
34 * and match, toRichText & toShortText in oevent
35 *
36 * Revision 1.7 2002/11/13 14:14:51 eilers
37 * Added sorted for Contacts..
38 *
39 * Revision 1.6 2002/11/01 15:10:42 eilers
40 * Added regExp-search in database for all fields in a contact.
41 *
42 * Revision 1.5 2002/10/16 10:52:40 eilers
43 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
44 *
45 * Revision 1.4 2002/10/14 16:21:54 eilers
46 * Some minor interface updates
47 *
48 * Revision 1.3 2002/10/07 17:34:24 eilers
49 * added OBackendFactory for advanced backend access
50 *
51 * Revision 1.2 2002/10/02 16:18:11 eilers
52 * debugged and seems to work almost perfectly ..
53 *
54 * Revision 1.1 2002/09/27 17:11:44 eilers
55 * Added API for accessing the Contact-Database ! It is compiling, but
56 * please do not expect that anything is working !
57 * I will debug that stuff in the next time ..
58 * Please read README_COMPILE for compiling !
59 *
60 *
61 */
62
63#include "ocontactaccess.h"
64#include "obackendfactory.h"
65
66#include <qasciidict.h>
67#include <qdatetime.h>
68#include <qfile.h>
69#include <qregexp.h>
70#include <qlist.h>
71#include <qcopchannel_qws.h>
72
73//#include <qpe/qcopenvelope_qws.h>
74#include <qpe/global.h>
75
76#include <errno.h>
77#include <fcntl.h>
78#include <unistd.h>
79#include <stdlib.h>
80
81#include "ocontactaccessbackend_xml.h"
82
83
84OContactAccess::OContactAccess ( const QString appname, const QString ,
85 OContactAccessBackend* end, bool autosync ):
86 OPimAccessTemplate<OContact>( end )
87{
88 /* take care of the backend. If there is no one defined, we
89 * will use the XML-Backend as default (until we have a cute SQL-Backend..).
90 */
91 if( end == 0 ) {
92 qWarning ("Using BackendFactory !");
93 end = OBackendFactory<OContactAccessBackend>::Default( "contact", appname );
94 }
95 // Set backend locally and in template
96 m_backEnd = end;
97 OPimAccessTemplate<OContact>::setBackEnd (end);
98
99
100 /* Connect signal of external db change to function */
101 QCopChannel *dbchannel = new QCopChannel( "QPE/PIM", this );
102 connect( dbchannel, SIGNAL(received(const QCString&,const QByteArray&)),
103 this, SLOT(copMessage(const QCString&,const QByteArray&)) );
104 if ( autosync ){
105 QCopChannel *syncchannel = new QCopChannel( "QPE/Sync", this );
106 connect( syncchannel, SIGNAL(received(const QCString&,const QByteArray&)),
107 this, SLOT(copMessage(const QCString&,const QByteArray&)) );
108 }
109
110
111}
112OContactAccess::~OContactAccess ()
113{
114 /* The user may forget to save the changed database, therefore try to
115 * do it for him..
116 */
117 save();
118 // delete m_backEnd; is done by template..
119}
120
121
122bool OContactAccess::save ()
123{
124 /* If the database was changed externally, we could not save the
125 * Data. This will remove added items which is unacceptable !
126 * Therefore: Reload database and merge the data...
127 */
128 if ( OPimAccessTemplate<OContact>::wasChangedExternally() )
129 reload();
130
131 bool status = OPimAccessTemplate<OContact>::save();
132 if ( !status ) return false;
133
134 /* Now tell everyone that new data is available.
135 */
136 QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" );
137
138 return true;
139}
140
141const uint OContactAccess::querySettings()
142{
143 return ( m_backEnd->querySettings() );
144}
145
146bool OContactAccess::hasQuerySettings ( int querySettings ) const
147{
148 return ( m_backEnd->hasQuerySettings ( querySettings ) );
149}
150ORecordList<OContact> OContactAccess::sorted( bool ascending, int sortOrder, int sortFilter, int cat ) const
151{
152 QArray<int> matchingContacts = m_backEnd -> sorted( ascending, sortOrder, sortFilter, cat );
153 return ( ORecordList<OContact>(matchingContacts, this) );
154}
155
156
157bool OContactAccess::wasChangedExternally()const
158{
159 return ( m_backEnd->wasChangedExternally() );
160}
161
162
163void OContactAccess::copMessage( const QCString &msg, const QByteArray & )
164{
165 if ( msg == "addressbookUpdated()" ){
166 qWarning ("OContactAccess: Received addressbokUpdated()");
167 emit signalChanged ( this );
168 } else if ( msg == "flush()" ) {
169 qWarning ("OContactAccess: Received flush()");
170 save ();
171 } else if ( msg == "reload()" ) {
172 qWarning ("OContactAccess: Received reload()");
173 reload ();
174 emit signalChanged ( this );
175 }
176}
diff --git a/noncore/unsupported/libopie/pim/ocontactaccess.h b/noncore/unsupported/libopie/pim/ocontactaccess.h
new file mode 100644
index 0000000..a7a099f
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontactaccess.h
@@ -0,0 +1,196 @@
1/*
2 * Class to manage the Contacts.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
6 *
7 * =====================================================================
8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation;
11 * either version 2 of the License, or (at your option) any later
12 * version.
13 * =====================================================================
14 * ToDo: Define enum for query settings
15 * =====================================================================
16 * Version: $Id$
17 * =====================================================================
18 * History:
19 * $Log$
20 * Revision 1.1 2004/11/16 21:46:07 mickeyl
21 * libopie1 goes into unsupported
22 *
23 * Revision 1.10 2003/12/22 10:19:26 eilers
24 * Finishing implementation of sql-backend for datebook. But I have to
25 * port the PIM datebook application to use it, before I could debug the
26 * whole stuff.
27 * Thus, PIM-Database backend is finished, but highly experimental. And some
28 * parts are still generic. For instance, the "queryByExample()" methods are
29 * not (or not fully) implemented. Todo: custom-entries not stored.
30 * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
31 * expression search in the database, which is not supported by sqlite !
32 * Therefore we need either an extended sqlite or a workaround which would
33 * be very slow and memory consuming..
34 *
35 * Revision 1.9 2003/08/01 12:30:16 eilers
36 * Merging changes from BRANCH_1_0 to HEAD
37 *
38 * Revision 1.8.2.1 2003/06/30 14:34:19 eilers
39 * Patches from Zecke:
40 * Fixing and cleaning up extraMap handling
41 * Adding d_ptr for binary compatibility in the future
42 *
43 * Revision 1.8 2003/05/08 13:55:09 tille
44 * search stuff
45 * and match, toRichText & toShortText in oevent
46 *
47 * Revision 1.7 2003/04/13 18:07:10 zecke
48 * More API doc
49 * QString -> const QString&
50 * QString = 0l -> QString::null
51 *
52 * Revision 1.6 2003/01/02 14:27:12 eilers
53 * Improved query by example: Search by date is possible.. First step
54 * for a today plugin for birthdays..
55 *
56 * Revision 1.5 2002/11/13 14:14:51 eilers
57 * Added sorted for Contacts..
58 *
59 * Revision 1.4 2002/11/01 15:10:42 eilers
60 * Added regExp-search in database for all fields in a contact.
61 *
62 * Revision 1.3 2002/10/16 10:52:40 eilers
63 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
64 *
65 * Revision 1.2 2002/10/14 16:21:54 eilers
66 * Some minor interface updates
67 *
68 * Revision 1.1 2002/09/27 17:11:44 eilers
69 * Added API for accessing the Contact-Database ! It is compiling, but
70 * please do not expect that anything is working !
71 * I will debug that stuff in the next time ..
72 * Please read README_COMPILE for compiling !
73 *
74 * =====================================================================
75 */
76#ifndef _OCONTACTACCESS_H
77#define _OCONTACTACCESS_H
78
79#include <qobject.h>
80
81#include <qpe/qcopenvelope_qws.h>
82
83#include <qvaluelist.h>
84#include <qfileinfo.h>
85
86#include "ocontact.h"
87#include "ocontactaccessbackend.h"
88#include "opimaccesstemplate.h"
89
90/**
91 * Class to access the contacts database.
92 * This is just a frontend for the real database handling which is
93 * done by the backend.
94 * This class is used to access the Contacts on a system. This class as any OPIE PIM
95 * class is backend independent.
96 * @author Stefan Eilers, Holger Freyther
97 * @see OPimAccessTemplate
98 */
99class OContactAccess: public QObject, public OPimAccessTemplate<OContact>
100{
101 Q_OBJECT
102
103 public:
104 /**
105 * Create Database with contacts (addressbook).
106 * @param appname Name of application which wants access to the database
107 * (i.e. "todolist")
108 * @param filename The name of the database file. If not set, the default one
109 * is used.
110 * @param backend Pointer to an alternative Backend. If not set, we will use
111 * the default backend.
112 * @param handlesync If <b>true</b> the database stores the current state
113 * automatically if it receives the signals <i>flush()</i> and <i>reload()</i>
114 * which are used before and after synchronisation. If the application wants
115 * to react itself, it should be disabled by setting it to <b>false</b>
116 * @see OContactAccessBackend
117 */
118 OContactAccess (const QString appname, const QString filename = 0l,
119 OContactAccessBackend* backend = 0l, bool handlesync = true);
120 ~OContactAccess ();
121
122 /** Constants for query.
123 * Use this constants to set the query parameters.
124 * Note: <i>query_IgnoreCase</i> just make sense with one of the other attributes !
125 * @see queryByExample()
126 */
127 enum QuerySettings {
128 WildCards = 0x0001,
129 IgnoreCase = 0x0002,
130 RegExp = 0x0004,
131 ExactMatch = 0x0008,
132 MatchOne = 0x0010, // Only one Entry must match
133 DateDiff = 0x0020, // Find all entries from today until given date
134 DateYear = 0x0040, // The year matches
135 DateMonth = 0x0080, // The month matches
136 DateDay = 0x0100, // The day matches
137 };
138
139
140 /** Return all Contacts in a sorted manner.
141 * @param ascending true: Sorted in acending order.
142 * @param sortOrder Currently not implemented. Just defined to stay compatible to otodoaccess
143 * @param sortFilter Currently not implemented. Just defined to stay compatible to otodoaccess
144 * @param cat Currently not implemented. Just defined to stay compatible to otodoaccess
145 */
146 List sorted( bool ascending, int sortOrder, int sortFilter, int cat ) const;
147
148 /** Return all possible settings.
149 * @return All settings provided by the current backend
150 * (i.e.: query_WildCards & query_IgnoreCase)
151 */
152 const uint querySettings();
153
154 /** Check whether settings are correct.
155 * @return <i>true</i> if the given settings are correct and possible.
156 */
157 bool hasQuerySettings ( int querySettings ) const;
158
159 /**
160 * if the resource was changed externally.
161 * You should use the signal instead of polling possible changes !
162 */
163 bool wasChangedExternally()const;
164
165
166 /** Save contacts database.
167 * Save is more a "commit". After calling this function, all changes are public available.
168 * @return true if successful
169 */
170 bool save();
171
172 signals:
173 /* Signal is emitted if the database was changed. Therefore
174 * we may need to reload to stay consistent.
175 * @param which Pointer to the database who created this event. This pointer
176 * is useful if an application has to handle multiple databases at the same time.
177 * @see reload()
178 */
179 void signalChanged ( const OContactAccess *which );
180
181
182 private:
183 // class OContactAccessPrivate;
184 // OContactAccessPrivate* d;
185 OContactAccessBackend *m_backEnd;
186 bool m_loading:1;
187
188 private slots:
189 void copMessage( const QCString &msg, const QByteArray &data );
190
191 private:
192 class Private;
193 Private *d;
194
195};
196#endif
diff --git a/noncore/unsupported/libopie/pim/ocontactaccessbackend.h b/noncore/unsupported/libopie/pim/ocontactaccessbackend.h
new file mode 100644
index 0000000..cfeeff2
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontactaccessbackend.h
@@ -0,0 +1,131 @@
1/**
2 * The class responsible for managing a backend.
3 * The implementation of this abstract class contains
4 * the complete database handling.
5 *
6 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
7 * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
8 *
9 * =====================================================================
10 *This program is free software; you can redistribute it and/or
11 *modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation;
13 * either version 2 of the License, or (at your option) any later
14 * version.
15 * =====================================================================
16 * ToDo: Define enum for query settings
17 * =====================================================================
18 * Version: $Id$
19 * =====================================================================
20 * History:
21 * $Log$
22 * Revision 1.1 2004/11/16 21:46:07 mickeyl
23 * libopie1 goes into unsupported
24 *
25 * Revision 1.7 2004/02/19 02:05:37 zecke
26 * Add notes for API fixes and BC stuff
27 *
28 * Revision 1.6 2003/08/01 12:30:16 eilers
29 * Merging changes from BRANCH_1_0 to HEAD
30 *
31 * Revision 1.5.4.1 2003/06/30 14:34:19 eilers
32 * Patches from Zecke:
33 * Fixing and cleaning up extraMap handling
34 * Adding d_ptr for binary compatibility in the future
35 *
36 * Revision 1.5 2003/04/13 18:07:10 zecke
37 * More API doc
38 * QString -> const QString&
39 * QString = 0l -> QString::null
40 *
41 * Revision 1.4 2002/11/13 14:14:51 eilers
42 * Added sorted for Contacts..
43 *
44 * Revision 1.3 2002/11/01 15:10:42 eilers
45 * Added regExp-search in database for all fields in a contact.
46 *
47 * Revision 1.2 2002/10/07 17:34:24 eilers
48 * added OBackendFactory for advanced backend access
49 *
50 * Revision 1.1 2002/09/27 17:11:44 eilers
51 * Added API for accessing the Contact-Database ! It is compiling, but
52 * please do not expect that anything is working !
53 * I will debug that stuff in the next time ..
54 * Please read README_COMPILE for compiling !
55 *
56 * =====================================================================
57 *
58 */
59
60#ifndef _OCONTACTACCESSBACKEND_H_
61#define _OCONTACTACCESSBACKEND_H_
62
63#include "ocontact.h"
64#include "opimaccessbackend.h"
65
66#include <qregexp.h>
67
68/**
69 * This class represents the interface of all Contact Backends.
70 * Derivates of this class will be used to access the contacts.
71 * As implementation currently XML and vCard exist. This class needs to be implemented
72 * if you want to provide your own storage.
73 * In all queries a list of uids is passed on instead of loading the actual record!
74 *
75 * @see OContactAccessBackend_VCard
76 * @see OContactAccessBackend_XML
77 */
78class OContactAccessBackend: public OPimAccessBackend<OContact> {
79 public:
80 /**
81 * @todo make non line in regard to BC guide of KDE
82 */
83 OContactAccessBackend() {}
84 /**
85 * @todo make non inline in regard to the BC guide of KDE
86 */
87 virtual ~OContactAccessBackend() {}
88
89
90 /**
91 * Return if database was changed externally.
92 * This may just make sense on file based databases like a XML-File.
93 * It is used to prevent to overwrite the current database content
94 * if the file was already changed by something else !
95 * If this happens, we have to reload before save our data.
96 * If we use real databases, this should be handled by the database
97 * management system themselve, therefore this function should always return false in
98 * this case. It is not our problem to handle this conflict ...
99 * @return <i>true</i> if the database was changed and if save without reload will
100 * be dangerous. <i>false</i> if the database was not changed or it is save to write
101 * in this situation.
102 */
103 virtual bool wasChangedExternally() = 0;
104
105 virtual QArray<int> matchRegexp( const QRegExp &r ) const = 0;
106
107 /**
108 * Return all possible settings.
109 * @return All settings provided by the current backend
110 * (i.e.: query_WildCards & query_IgnoreCase)
111 */
112 virtual const uint querySettings() = 0;
113
114 /**
115 * Check whether settings are correct.
116 * @return <i>true</i> if the given settings are correct and possible.
117 */
118 virtual bool hasQuerySettings (uint querySettings) const = 0;
119
120 /**
121 * FIXME!!!
122 * Returns a sorted list of records either ascendinf or descending for a giving criteria and category
123 */
124 virtual QArray<int> sorted( bool ascending, int sortOrder, int sortFilter, int cat ) = 0;
125
126
127private:
128 class Private;
129 Private *d;
130};
131#endif
diff --git a/noncore/unsupported/libopie/pim/ocontactaccessbackend_sql.cpp b/noncore/unsupported/libopie/pim/ocontactaccessbackend_sql.cpp
new file mode 100644
index 0000000..669483d
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontactaccessbackend_sql.cpp
@@ -0,0 +1,948 @@
1/*
2 * SQL Backend for the OPIE-Contact Database.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * =====================================================================
13 * Version: $Id$
14 * =====================================================================
15 * History:
16 * $Log$
17 * Revision 1.1 2004/11/16 21:46:07 mickeyl
18 * libopie1 goes into unsupported
19 *
20 * Revision 1.5 2004/03/14 13:50:35 alwin
21 * namespace correction
22 *
23 * Revision 1.4 2003/12/22 10:19:26 eilers
24 * Finishing implementation of sql-backend for datebook. But I have to
25 * port the PIM datebook application to use it, before I could debug the
26 * whole stuff.
27 * Thus, PIM-Database backend is finished, but highly experimental. And some
28 * parts are still generic. For instance, the "queryByExample()" methods are
29 * not (or not fully) implemented. Todo: custom-entries not stored.
30 * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
31 * expression search in the database, which is not supported by sqlite !
32 * Therefore we need either an extended sqlite or a workaround which would
33 * be very slow and memory consuming..
34 *
35 * Revision 1.3 2003/12/08 15:18:10 eilers
36 * Committing unfinished sql implementation before merging to libopie2 starts..
37 *
38 * Revision 1.2 2003/09/29 07:44:26 eilers
39 * Improvement of PIM-SQL Databases, but search queries are still limited.
40 * Addressbook: Changed table layout. Now, we just need 1/3 of disk-space.
41 * Todo: Started to add new attributes. Some type conversions missing.
42 *
43 * Revision 1.1 2003/09/22 14:31:16 eilers
44 * Added first experimental incarnation of sql-backend for addressbook.
45 * Some modifications to be able to compile the todo sql-backend.
46 * A lot of changes fill follow...
47 *
48 */
49
50#include "ocontactaccessbackend_sql.h"
51
52#include <qarray.h>
53#include <qdatetime.h>
54#include <qstringlist.h>
55
56#include <qpe/global.h>
57#include <qpe/recordfields.h>
58
59#include <opie/ocontactfields.h>
60#include <opie/oconversion.h>
61#include <opie2/osqldriver.h>
62#include <opie2/osqlresult.h>
63#include <opie2/osqlmanager.h>
64#include <opie2/osqlquery.h>
65
66using namespace Opie::DB;
67
68
69// If defined, we use a horizontal table ( uid, attr1, attr2, attr3, ..., attrn ) instead
70// vertical like "uid, type, value".
71// DON'T DEACTIVATE THIS DEFINE IN PRODUCTIVE ENVIRONMENTS !!
72#define __STORE_HORIZONTAL_
73
74// Distinct loading is not very fast. If I expect that every person has just
75// one (and always one) 'Last Name', I can request all uid's for existing lastnames,
76// which is faster..
77// But this may not be true for all entries, like company contacts..
78// The current AddressBook application handles this problem, but other may not.. (eilers)
79#define __USE_SUPERFAST_LOADQUERY
80
81
82/*
83 * Implementation of used query types
84 * CREATE query
85 * LOAD query
86 * INSERT
87 * REMOVE
88 * CLEAR
89 */
90namespace {
91 /**
92 * CreateQuery for the Todolist Table
93 */
94 class CreateQuery : public OSQLQuery {
95 public:
96 CreateQuery();
97 ~CreateQuery();
98 QString query()const;
99 };
100
101 /**
102 * Clears (delete) a Table
103 */
104 class ClearQuery : public OSQLQuery {
105 public:
106 ClearQuery();
107 ~ClearQuery();
108 QString query()const;
109
110 };
111
112
113 /**
114 * LoadQuery
115 * this one queries for all uids
116 */
117 class LoadQuery : public OSQLQuery {
118 public:
119 LoadQuery();
120 ~LoadQuery();
121 QString query()const;
122 };
123
124 /**
125 * inserts/adds a OContact to the table
126 */
127 class InsertQuery : public OSQLQuery {
128 public:
129 InsertQuery(const OContact& );
130 ~InsertQuery();
131 QString query()const;
132 private:
133 OContact m_contact;
134 };
135
136
137 /**
138 * removes one from the table
139 */
140 class RemoveQuery : public OSQLQuery {
141 public:
142 RemoveQuery(int uid );
143 ~RemoveQuery();
144 QString query()const;
145 private:
146 int m_uid;
147 };
148
149 /**
150 * a find query for noncustom elements
151 */
152 class FindQuery : public OSQLQuery {
153 public:
154 FindQuery(int uid);
155 FindQuery(const QArray<int>& );
156 ~FindQuery();
157 QString query()const;
158 private:
159 QString single()const;
160 QString multi()const;
161 QArray<int> m_uids;
162 int m_uid;
163 };
164
165 /**
166 * a find query for custom elements
167 */
168 class FindCustomQuery : public OSQLQuery {
169 public:
170 FindCustomQuery(int uid);
171 FindCustomQuery(const QArray<int>& );
172 ~FindCustomQuery();
173 QString query()const;
174 private:
175 QString single()const;
176 QString multi()const;
177 QArray<int> m_uids;
178 int m_uid;
179 };
180
181
182
183 // We using three tables to store the information:
184 // 1. addressbook : It contains General information about the contact (non custom)
185 // 2. custom_data : Not official supported entries
186 // All tables are connected by the uid of the contact.
187 // Maybe I should add a table for meta-information ?
188 CreateQuery::CreateQuery() : OSQLQuery() {}
189 CreateQuery::~CreateQuery() {}
190 QString CreateQuery::query()const {
191 QString qu;
192#ifdef __STORE_HORIZONTAL_
193
194 qu += "create table addressbook( uid PRIMARY KEY ";
195
196 QStringList fieldList = OContactFields::untrfields( false );
197 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
198 qu += QString( ",\"%1\" VARCHAR(10)" ).arg( *it );
199 }
200 qu += " );";
201
202 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
203
204#else
205
206 qu += "create table addressbook( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id));";
207 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
208 // qu += "create table dates( uid PRIMARY KEY, type, day, month, year, hour, minute, second );";
209
210#endif // __STORE_HORIZONTAL_
211 return qu;
212 }
213
214 ClearQuery::ClearQuery()
215 : OSQLQuery() {}
216 ClearQuery::~ClearQuery() {}
217 QString ClearQuery::query()const {
218 QString qu = "drop table addressbook;";
219 qu += "drop table custom_data;";
220 // qu += "drop table dates;";
221 return qu;
222 }
223
224
225 LoadQuery::LoadQuery() : OSQLQuery() {}
226 LoadQuery::~LoadQuery() {}
227 QString LoadQuery::query()const {
228 QString qu;
229#ifdef __STORE_HORIZONTAL_
230 qu += "select uid from addressbook";
231#else
232# ifndef __USE_SUPERFAST_LOADQUERY
233 qu += "select distinct uid from addressbook";
234# else
235 qu += "select uid from addressbook where type = 'Last Name'";
236# endif // __USE_SUPERFAST_LOADQUERY
237#endif // __STORE_HORIZONTAL_
238
239 return qu;
240 }
241
242
243 InsertQuery::InsertQuery( const OContact& contact )
244 : OSQLQuery(), m_contact( contact ) {
245 }
246
247 InsertQuery::~InsertQuery() {
248 }
249
250 /*
251 * converts from a OContact to a query
252 */
253 QString InsertQuery::query()const{
254
255#ifdef __STORE_HORIZONTAL_
256 QString qu;
257 qu += "insert into addressbook VALUES( " +
258 QString::number( m_contact.uid() );
259
260 // Get all information out of the contact-class
261 // Remember: The category is stored in contactMap, too !
262 QMap<int, QString> contactMap = m_contact.toMap();
263
264 QStringList fieldList = OContactFields::untrfields( false );
265 QMap<QString, int> translate = OContactFields::untrFieldsToId();
266 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
267 // Convert Column-String to Id and get value for this id..
268 // Hmmm.. Maybe not very cute solution..
269 int id = translate[*it];
270 switch ( id ){
271 case Qtopia::Birthday:{
272 // These entries should stored in a special format
273 // year-month-day
274 QDate day = m_contact.birthday();
275 if ( day.isValid() ){
276 qu += QString(",\"%1-%2-%3\"")
277 .arg( day.year() )
278 .arg( day.month() )
279 .arg( day.day() );
280 } else {
281 qu += ",\"\"";
282 }
283 }
284 break;
285 case Qtopia::Anniversary:{
286 // These entries should stored in a special format
287 // year-month-day
288 QDate day = m_contact.anniversary();
289 if ( day.isValid() ){
290 qu += QString(",\"%1-%2-%3\"")
291 .arg( day.year() )
292 .arg( day.month() )
293 .arg( day.day() );
294 } else {
295 qu += ",\"\"";
296 }
297 }
298 break;
299
300 default:
301 qu += QString( ",\"%1\"" ).arg( contactMap[id] );
302 }
303 }
304 qu += " );";
305
306
307#else
308 // Get all information out of the contact-class
309 // Remember: The category is stored in contactMap, too !
310 QMap<int, QString> contactMap = m_contact.toMap();
311
312 QMap<QString, QString> addressbook_db;
313
314 // Get the translation from the ID to the String
315 QMap<int, QString> transMap = OContactFields::idToUntrFields();
316
317 for( QMap<int, QString>::Iterator it = contactMap.begin();
318 it != contactMap.end(); ++it ){
319 switch ( it.key() ){
320 case Qtopia::Birthday:{
321 // These entries should stored in a special format
322 // year-month-day
323 QDate day = m_contact.birthday();
324 addressbook_db.insert( transMap[it.key()],
325 QString("%1-%2-%3")
326 .arg( day.year() )
327 .arg( day.month() )
328 .arg( day.day() ) );
329 }
330 break;
331 case Qtopia::Anniversary:{
332 // These entries should stored in a special format
333 // year-month-day
334 QDate day = m_contact.anniversary();
335 addressbook_db.insert( transMap[it.key()],
336 QString("%1-%2-%3")
337 .arg( day.year() )
338 .arg( day.month() )
339 .arg( day.day() ) );
340 }
341 break;
342 case Qtopia::AddressUid: // Ignore UID
343 break;
344 default: // Translate id to String
345 addressbook_db.insert( transMap[it.key()], it.data() );
346 break;
347 }
348
349 }
350
351 // Now convert this whole stuff into a SQL String, beginning with
352 // the addressbook table..
353 QString qu;
354 // qu += "begin transaction;";
355 int id = 0;
356 for( QMap<QString, QString>::Iterator it = addressbook_db.begin();
357 it != addressbook_db.end(); ++it ){
358 qu += "insert into addressbook VALUES("
359 + QString::number( m_contact.uid() )
360 + ","
361 + QString::number( id++ )
362 + ",'"
363 + it.key() //.latin1()
364 + "',"
365 + "0" // Priority for future enhancements
366 + ",'"
367 + it.data() //.latin1()
368 + "');";
369 }
370
371 #endif //__STORE_HORIZONTAL_
372 // Now add custom data..
373#ifdef __STORE_HORIZONTAL_
374 int id = 0;
375#endif
376 id = 0;
377 QMap<QString, QString> customMap = m_contact.toExtraMap();
378 for( QMap<QString, QString>::Iterator it = customMap.begin();
379 it != customMap.end(); ++it ){
380 qu += "insert into custom_data VALUES("
381 + QString::number( m_contact.uid() )
382 + ","
383 + QString::number( id++ )
384 + ",'"
385 + it.key() //.latin1()
386 + "',"
387 + "0" // Priority for future enhancements
388 + ",'"
389 + it.data() //.latin1()
390 + "');";
391 }
392 // qu += "commit;";
393 qWarning("add %s", qu.latin1() );
394 return qu;
395 }
396
397
398 RemoveQuery::RemoveQuery(int uid )
399 : OSQLQuery(), m_uid( uid ) {}
400 RemoveQuery::~RemoveQuery() {}
401 QString RemoveQuery::query()const {
402 QString qu = "DELETE from addressbook where uid = "
403 + QString::number(m_uid) + ";";
404 qu += "DELETE from custom_data where uid = "
405 + QString::number(m_uid) + ";";
406 return qu;
407 }
408
409
410
411
412 FindQuery::FindQuery(int uid)
413 : OSQLQuery(), m_uid( uid ) {
414 }
415 FindQuery::FindQuery(const QArray<int>& ints)
416 : OSQLQuery(), m_uids( ints ){
417 }
418 FindQuery::~FindQuery() {
419 }
420 QString FindQuery::query()const{
421 // if ( m_uids.count() == 0 )
422 return single();
423 }
424 /*
425 else
426 return multi();
427 }
428 QString FindQuery::multi()const {
429 QString qu = "select uid, type, value from addressbook where";
430 for (uint i = 0; i < m_uids.count(); i++ ) {
431 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
432 }
433 qu.remove( qu.length()-2, 2 ); // Hmmmm..
434 return qu;
435 }
436 */
437#ifdef __STORE_HORIZONTAL_
438 QString FindQuery::single()const{
439 QString qu = "select *";
440 qu += " from addressbook where uid = " + QString::number(m_uid);
441
442 // qWarning("find query: %s", qu.latin1() );
443 return qu;
444 }
445#else
446 QString FindQuery::single()const{
447 QString qu = "select uid, type, value from addressbook where uid = ";
448 qu += QString::number(m_uid);
449 return qu;
450 }
451#endif
452
453
454 FindCustomQuery::FindCustomQuery(int uid)
455 : OSQLQuery(), m_uid( uid ) {
456 }
457 FindCustomQuery::FindCustomQuery(const QArray<int>& ints)
458 : OSQLQuery(), m_uids( ints ){
459 }
460 FindCustomQuery::~FindCustomQuery() {
461 }
462 QString FindCustomQuery::query()const{
463 // if ( m_uids.count() == 0 )
464 return single();
465 }
466 QString FindCustomQuery::single()const{
467 QString qu = "select uid, type, value from custom_data where uid = ";
468 qu += QString::number(m_uid);
469 return qu;
470 }
471
472};
473
474
475/* --------------------------------------------------------------------------- */
476
477OContactAccessBackend_SQL::OContactAccessBackend_SQL ( const QString& /* appname */,
478 const QString& filename ):
479 OContactAccessBackend(), m_changed(false), m_driver( NULL )
480{
481 qWarning("C'tor OContactAccessBackend_SQL starts");
482 QTime t;
483 t.start();
484
485 /* Expecting to access the default filename if nothing else is set */
486 if ( filename.isEmpty() ){
487 m_fileName = Global::applicationFileName( "addressbook","addressbook.db" );
488 } else
489 m_fileName = filename;
490
491 // Get the standart sql-driver from the OSQLManager..
492 OSQLManager man;
493 m_driver = man.standard();
494 m_driver->setUrl( m_fileName );
495
496 load();
497
498 qWarning("C'tor OContactAccessBackend_SQL ends: %d ms", t.elapsed() );
499}
500
501OContactAccessBackend_SQL::~OContactAccessBackend_SQL ()
502{
503 if( m_driver )
504 delete m_driver;
505}
506
507bool OContactAccessBackend_SQL::load ()
508{
509 if (!m_driver->open() )
510 return false;
511
512 // Don't expect that the database exists.
513 // It is save here to create the table, even if it
514 // do exist. ( Is that correct for all databases ?? )
515 CreateQuery creat;
516 OSQLResult res = m_driver->query( &creat );
517
518 update();
519
520 return true;
521
522}
523
524bool OContactAccessBackend_SQL::reload()
525{
526 return load();
527}
528
529bool OContactAccessBackend_SQL::save()
530{
531 return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
532}
533
534
535void OContactAccessBackend_SQL::clear ()
536{
537 ClearQuery cle;
538 OSQLResult res = m_driver->query( &cle );
539
540 reload();
541}
542
543bool OContactAccessBackend_SQL::wasChangedExternally()
544{
545 return false;
546}
547
548QArray<int> OContactAccessBackend_SQL::allRecords() const
549{
550
551 // FIXME: Think about cute handling of changed tables..
552 // Thus, we don't have to call update here...
553 if ( m_changed )
554 ((OContactAccessBackend_SQL*)this)->update();
555
556 return m_uids;
557}
558
559bool OContactAccessBackend_SQL::add ( const OContact &newcontact )
560{
561 InsertQuery ins( newcontact );
562 OSQLResult res = m_driver->query( &ins );
563
564 if ( res.state() == OSQLResult::Failure )
565 return false;
566
567 int c = m_uids.count();
568 m_uids.resize( c+1 );
569 m_uids[c] = newcontact.uid();
570
571 return true;
572}
573
574
575bool OContactAccessBackend_SQL::remove ( int uid )
576{
577 RemoveQuery rem( uid );
578 OSQLResult res = m_driver->query(&rem );
579
580 if ( res.state() == OSQLResult::Failure )
581 return false;
582
583 m_changed = true;
584
585 return true;
586}
587
588bool OContactAccessBackend_SQL::replace ( const OContact &contact )
589{
590 if ( !remove( contact.uid() ) )
591 return false;
592
593 return add( contact );
594}
595
596
597OContact OContactAccessBackend_SQL::find ( int uid ) const
598{
599 qWarning("OContactAccessBackend_SQL::find()");
600 QTime t;
601 t.start();
602
603 OContact retContact( requestNonCustom( uid ) );
604 retContact.setExtraMap( requestCustom( uid ) );
605
606 qWarning("OContactAccessBackend_SQL::find() needed: %d ms", t.elapsed() );
607 return retContact;
608}
609
610
611
612QArray<int> OContactAccessBackend_SQL::queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() )
613{
614 QString qu = "SELECT uid FROM addressbook WHERE";
615
616 QMap<int, QString> queryFields = query.toMap();
617 QStringList fieldList = OContactFields::untrfields( false );
618 QMap<QString, int> translate = OContactFields::untrFieldsToId();
619
620 // Convert every filled field to a SQL-Query
621 bool isAnyFieldSelected = false;
622 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
623 int id = translate[*it];
624 QString queryStr = queryFields[id];
625 if ( !queryStr.isEmpty() ){
626 isAnyFieldSelected = true;
627 switch( id ){
628 default:
629 // Switching between case sensitive and insensitive...
630 // LIKE is not case sensitive, GLOB is case sensitive
631 // Do exist a better solution to switch this ?
632 if ( settings & OContactAccess::IgnoreCase )
633 qu += "(\"" + *it + "\"" + " LIKE " + "'"
634 + queryStr.replace(QRegExp("\\*"),"%") + "'" + ") AND ";
635 else
636 qu += "(\"" + *it + "\"" + " GLOB " + "'"
637 + queryStr + "'" + ") AND ";
638
639 }
640 }
641 }
642 // Skip trailing "AND"
643 if ( isAnyFieldSelected )
644 qu = qu.left( qu.length() - 4 );
645
646 qWarning( "queryByExample query: %s", qu.latin1() );
647
648 // Execute query and return the received uid's
649 OSQLRawQuery raw( qu );
650 OSQLResult res = m_driver->query( &raw );
651 if ( res.state() != OSQLResult::Success ){
652 QArray<int> empty;
653 return empty;
654 }
655
656 QArray<int> list = extractUids( res );
657
658 return list;
659}
660
661QArray<int> OContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
662{
663 QArray<int> nix(0);
664 return nix;
665}
666
667const uint OContactAccessBackend_SQL::querySettings()
668{
669 return OContactAccess::IgnoreCase
670 || OContactAccess::WildCards;
671}
672
673bool OContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const
674{
675 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
676 * may be added with any of the other settings. IgnoreCase should never used alone.
677 * Wildcards, RegExp, ExactMatch should never used at the same time...
678 */
679
680 // Step 1: Check whether the given settings are supported by this backend
681 if ( ( querySettings & (
682 OContactAccess::IgnoreCase
683 | OContactAccess::WildCards
684 // | OContactAccess::DateDiff
685 // | OContactAccess::DateYear
686 // | OContactAccess::DateMonth
687 // | OContactAccess::DateDay
688 // | OContactAccess::RegExp
689 // | OContactAccess::ExactMatch
690 ) ) != querySettings )
691 return false;
692
693 // Step 2: Check whether the given combinations are ok..
694
695 // IngoreCase alone is invalid
696 if ( querySettings == OContactAccess::IgnoreCase )
697 return false;
698
699 // WildCards, RegExp and ExactMatch should never used at the same time
700 switch ( querySettings & ~( OContactAccess::IgnoreCase
701 | OContactAccess::DateDiff
702 | OContactAccess::DateYear
703 | OContactAccess::DateMonth
704 | OContactAccess::DateDay
705 )
706 ){
707 case OContactAccess::RegExp:
708 return ( true );
709 case OContactAccess::WildCards:
710 return ( true );
711 case OContactAccess::ExactMatch:
712 return ( true );
713 case 0: // one of the upper removed bits were set..
714 return ( true );
715 default:
716 return ( false );
717 }
718
719}
720
721QArray<int> OContactAccessBackend_SQL::sorted( bool asc, int , int , int )
722{
723 QTime t;
724 t.start();
725
726#ifdef __STORE_HORIZONTAL_
727 QString query = "SELECT uid FROM addressbook ";
728 query += "ORDER BY \"Last Name\" ";
729#else
730 QString query = "SELECT uid FROM addressbook WHERE type = 'Last Name' ";
731 query += "ORDER BY upper( value )";
732#endif
733
734 if ( !asc )
735 query += "DESC";
736
737 // qWarning("sorted query is: %s", query.latin1() );
738
739 OSQLRawQuery raw( query );
740 OSQLResult res = m_driver->query( &raw );
741 if ( res.state() != OSQLResult::Success ){
742 QArray<int> empty;
743 return empty;
744 }
745
746 QArray<int> list = extractUids( res );
747
748 qWarning("sorted needed %d ms!", t.elapsed() );
749 return list;
750}
751
752
753void OContactAccessBackend_SQL::update()
754{
755 qWarning("Update starts");
756 QTime t;
757 t.start();
758
759 // Now load the database set and extract the uid's
760 // which will be held locally
761
762 LoadQuery lo;
763 OSQLResult res = m_driver->query(&lo);
764 if ( res.state() != OSQLResult::Success )
765 return;
766
767 m_uids = extractUids( res );
768
769 m_changed = false;
770
771 qWarning("Update ends %d ms", t.elapsed() );
772}
773
774QArray<int> OContactAccessBackend_SQL::extractUids( OSQLResult& res ) const
775{
776 qWarning("extractUids");
777 QTime t;
778 t.start();
779 OSQLResultItem::ValueList list = res.results();
780 OSQLResultItem::ValueList::Iterator it;
781 QArray<int> ints(list.count() );
782 qWarning(" count = %d", list.count() );
783
784 int i = 0;
785 for (it = list.begin(); it != list.end(); ++it ) {
786 ints[i] = (*it).data("uid").toInt();
787 i++;
788 }
789 qWarning("extractUids ready: count2 = %d needs %d ms", i, t.elapsed() );
790
791 return ints;
792
793}
794
795#ifdef __STORE_HORIZONTAL_
796QMap<int, QString> OContactAccessBackend_SQL::requestNonCustom( int uid ) const
797{
798 QTime t;
799 t.start();
800
801 QMap<int, QString> nonCustomMap;
802
803 int t2needed = 0;
804 int t3needed = 0;
805 QTime t2;
806 t2.start();
807 FindQuery query( uid );
808 OSQLResult res_noncustom = m_driver->query( &query );
809 t2needed = t2.elapsed();
810
811 OSQLResultItem resItem = res_noncustom.first();
812
813 QTime t3;
814 t3.start();
815 // Now loop through all columns
816 QStringList fieldList = OContactFields::untrfields( false );
817 QMap<QString, int> translate = OContactFields::untrFieldsToId();
818 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
819 // Get data for the selected column and store it with the
820 // corresponding id into the map..
821
822 int id = translate[*it];
823 QString value = resItem.data( (*it) );
824
825 // qWarning("Reading %s... found: %s", (*it).latin1(), value.latin1() );
826
827 switch( id ){
828 case Qtopia::Birthday:
829 case Qtopia::Anniversary:{
830 // Birthday and Anniversary are encoded special ( yyyy-mm-dd )
831 QStringList list = QStringList::split( '-', value );
832 QStringList::Iterator lit = list.begin();
833 int year = (*lit).toInt();
834 int month = (*(++lit)).toInt();
835 int day = (*(++lit)).toInt();
836 if ( ( day != 0 ) && ( month != 0 ) && ( year != 0 ) ){
837 QDate date( year, month, day );
838 nonCustomMap.insert( id, OConversion::dateToString( date ) );
839 }
840 }
841 break;
842 case Qtopia::AddressCategory:
843 qWarning("Category is: %s", value.latin1() );
844 default:
845 nonCustomMap.insert( id, value );
846 }
847 }
848
849 // First insert uid
850 nonCustomMap.insert( Qtopia::AddressUid, resItem.data( "uid" ) );
851 t3needed = t3.elapsed();
852
853 // qWarning("Adding UID: %s", resItem.data( "uid" ).latin1() );
854 qWarning("RequestNonCustom needed: insg.:%d ms, query: %d ms, mapping: %d ms",
855 t.elapsed(), t2needed, t3needed );
856
857 return nonCustomMap;
858}
859#else
860
861QMap<int, QString> OContactAccessBackend_SQL::requestNonCustom( int uid ) const
862{
863 QTime t;
864 t.start();
865
866 QMap<int, QString> nonCustomMap;
867
868 int t2needed = 0;
869 QTime t2;
870 t2.start();
871 FindQuery query( uid );
872 OSQLResult res_noncustom = m_driver->query( &query );
873 t2needed = t2.elapsed();
874
875 if ( res_noncustom.state() == OSQLResult::Failure ) {
876 qWarning("OSQLResult::Failure in find query !!");
877 QMap<int, QString> empty;
878 return empty;
879 }
880
881 int t3needed = 0;
882 QTime t3;
883 t3.start();
884 QMap<QString, int> translateMap = OContactFields::untrFieldsToId();
885
886 OSQLResultItem::ValueList list = res_noncustom.results();
887 OSQLResultItem::ValueList::Iterator it = list.begin();
888 for ( ; it != list.end(); ++it ) {
889 if ( (*it).data("type") != "" ){
890 int typeId = translateMap[(*it).data( "type" )];
891 switch( typeId ){
892 case Qtopia::Birthday:
893 case Qtopia::Anniversary:{
894 // Birthday and Anniversary are encoded special ( yyyy-mm-dd )
895 QStringList list = QStringList::split( '-', (*it).data( "value" ) );
896 QStringList::Iterator lit = list.begin();
897 int year = (*lit).toInt();
898 qWarning("1. %s", (*lit).latin1());
899 int month = (*(++lit)).toInt();
900 qWarning("2. %s", (*lit).latin1());
901 int day = (*(++lit)).toInt();
902 qWarning("3. %s", (*lit).latin1());
903 qWarning( "RequestNonCustom->Converting:%s to Year: %d, Month: %d, Day: %d ", (*it).data( "value" ).latin1(), year, month, day );
904 QDate date( year, month, day );
905 nonCustomMap.insert( typeId, OConversion::dateToString( date ) );
906 }
907 break;
908 default:
909 nonCustomMap.insert( typeId,
910 (*it).data( "value" ) );
911 }
912 }
913 }
914 // Add UID to Map..
915 nonCustomMap.insert( Qtopia::AddressUid, QString::number( uid ) );
916 t3needed = t3.elapsed();
917
918 qWarning("RequestNonCustom needed: insg.:%d ms, query: %d ms, mapping: %d ms", t.elapsed(), t2needed, t3needed );
919 return nonCustomMap;
920}
921
922#endif // __STORE_HORIZONTAL_
923
924QMap<QString, QString> OContactAccessBackend_SQL::requestCustom( int uid ) const
925{
926 QTime t;
927 t.start();
928
929 QMap<QString, QString> customMap;
930
931 FindCustomQuery query( uid );
932 OSQLResult res_custom = m_driver->query( &query );
933
934 if ( res_custom.state() == OSQLResult::Failure ) {
935 qWarning("OSQLResult::Failure in find query !!");
936 QMap<QString, QString> empty;
937 return empty;
938 }
939
940 OSQLResultItem::ValueList list = res_custom.results();
941 OSQLResultItem::ValueList::Iterator it = list.begin();
942 for ( ; it != list.end(); ++it ) {
943 customMap.insert( (*it).data( "type" ), (*it).data( "value" ) );
944 }
945
946 qWarning("RequestCustom needed: %d ms", t.elapsed() );
947 return customMap;
948}
diff --git a/noncore/unsupported/libopie/pim/ocontactaccessbackend_sql.h b/noncore/unsupported/libopie/pim/ocontactaccessbackend_sql.h
new file mode 100644
index 0000000..8cd92e8
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontactaccessbackend_sql.h
@@ -0,0 +1,110 @@
1/*
2 * SQL Backend for the OPIE-Contact Database.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 *
13 *
14 * =====================================================================
15 * Version: $Id$
16 * =====================================================================
17 * History:
18 * $Log$
19 * Revision 1.1 2004/11/16 21:46:07 mickeyl
20 * libopie1 goes into unsupported
21 *
22 * Revision 1.3 2004/03/14 13:50:35 alwin
23 * namespace correction
24 *
25 * Revision 1.2 2003/12/08 15:18:11 eilers
26 * Committing unfinished sql implementation before merging to libopie2 starts..
27 *
28 * Revision 1.1 2003/09/22 14:31:16 eilers
29 * Added first experimental incarnation of sql-backend for addressbook.
30 * Some modifications to be able to compile the todo sql-backend.
31 * A lot of changes fill follow...
32 *
33 *
34 */
35
36#ifndef _OContactAccessBackend_SQL_
37#define _OContactAccessBackend_SQL_
38
39#include "ocontactaccessbackend.h"
40#include "ocontactaccess.h"
41
42#include <qlist.h>
43#include <qdict.h>
44
45namespace Opie { namespace DB {
46class OSQLDriver;
47class OSQLResult;
48class OSQLResultItem;
49
50}}
51
52/* the default xml implementation */
53/**
54 * This class is the SQL implementation of a Contact backend
55 * it does implement everything available for OContact.
56 * @see OPimAccessBackend for more information of available methods
57 */
58class OContactAccessBackend_SQL : public OContactAccessBackend {
59 public:
60 OContactAccessBackend_SQL ( const QString& appname, const QString& filename = QString::null );
61
62 ~OContactAccessBackend_SQL ();
63
64 bool save();
65
66 bool load ();
67
68 void clear ();
69
70 bool wasChangedExternally();
71
72 QArray<int> allRecords() const;
73
74 OContact find ( int uid ) const;
75 // FIXME: Add lookahead-cache support !
76 //OContact find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
77
78 QArray<int> queryByExample ( const OContact &query, int settings,
79 const QDateTime& d );
80
81 QArray<int> matchRegexp( const QRegExp &r ) const;
82
83 const uint querySettings();
84
85 bool hasQuerySettings (uint querySettings) const;
86
87 // Currently only asc implemented..
88 QArray<int> sorted( bool asc, int , int , int );
89 bool add ( const OContact &newcontact );
90
91 bool replace ( const OContact &contact );
92
93 bool remove ( int uid );
94 bool reload();
95
96 private:
97 QArray<int> extractUids( Opie::DB::OSQLResult& res ) const;
98 QMap<int, QString> requestNonCustom( int uid ) const;
99 QMap<QString, QString> requestCustom( int uid ) const;
100 void update();
101
102 protected:
103 bool m_changed;
104 QString m_fileName;
105 QArray<int> m_uids;
106
107 Opie::DB::OSQLDriver* m_driver;
108};
109
110#endif
diff --git a/noncore/unsupported/libopie/pim/ocontactaccessbackend_vcard.cpp b/noncore/unsupported/libopie/pim/ocontactaccessbackend_vcard.cpp
new file mode 100644
index 0000000..a795b56
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontactaccessbackend_vcard.cpp
@@ -0,0 +1,649 @@
1/*
2 * VCard Backend for the OPIE-Contact Database.
3 *
4 * Copyright (C) 2000 Trolltech AS. All rights reserved.
5 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
6 *
7 * =====================================================================
8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 * =====================================================================
13 * ToDo:
14 *
15 * =====================================================================
16 * Version: $Id$
17 * =====================================================================
18 * History:
19 * $Log$
20 * Revision 1.1 2004/11/16 21:46:07 mickeyl
21 * libopie1 goes into unsupported
22 *
23 * Revision 1.11 2003/08/01 12:30:16 eilers
24 * Merging changes from BRANCH_1_0 to HEAD
25 *
26 * Revision 1.10.4.3 2003/07/23 08:54:37 eilers
27 * Default email was added to the list of all emails, which already contains
28 * the default email..
29 * This closes bug #1045
30 *
31 * Revision 1.10.4.2 2003/07/23 08:44:45 eilers
32 * Importing of Notes in vcard files wasn't implemented.
33 * Closes bug #1044
34 *
35 * Revision 1.10.4.1 2003/06/02 13:37:49 eilers
36 * Fixing memory leak
37 *
38 * Revision 1.10 2003/04/13 18:07:10 zecke
39 * More API doc
40 * QString -> const QString&
41 * QString = 0l -> QString::null
42 *
43 * Revision 1.9 2003/03/21 10:33:09 eilers
44 * Merged speed optimized xml backend for contacts to main.
45 * Added QDateTime to querybyexample. For instance, it is now possible to get
46 * all Birthdays/Anniversaries between two dates. This should be used
47 * to show all birthdays in the datebook..
48 * This change is sourcecode backward compatible but you have to upgrade
49 * the binaries for today-addressbook.
50 *
51 * Revision 1.8 2003/02/21 16:52:49 zecke
52 * -Remove old Todo classes they're deprecated and today I already using the
53 * new API
54 * -Guard against self assignment in OTodo
55 * -Add test apps for OPIM
56 * -Opiefied Event classes
57 * -Added TimeZone handling and pinning of TimeZones to OEvent
58 * -Adjust ORecur and the widget to better timezone behaviour
59 *
60 * Revision 1.7 2003/02/16 22:25:46 zecke
61 * 0000276 Fix for that bug.. or better temp workaround
62 * A Preferred Number is HOME|VOICE
63 * A CellPhone is HOME|VOICE|CELL the type & HOME|VOICE test
64 * triggers both
65 * and the cell phone number overrides the other entries..
66 *
67 * as a temp I check that it's not equal to HOME|VOICE|CELL before setting the
68 * number
69 *
70 * The right and final fix would be to reorder the if statement to make it
71 * if else based and the less common thing put to the bottom
72 *
73 * OTodoAccessVcal fix the date for beaming
74 *
75 * Revision 1.6 2003/01/13 15:49:31 eilers
76 * Fixing crash when businesscard.vcf is missing..
77 *
78 * Revision 1.5 2002/12/07 13:26:22 eilers
79 * Fixing bug in storing anniversary..
80 *
81 * Revision 1.4 2002/11/13 14:14:51 eilers
82 * Added sorted for Contacts..
83 *
84 * Revision 1.3 2002/11/11 16:41:09 kergoth
85 * no default arguments in implementation
86 *
87 * Revision 1.2 2002/11/10 15:41:53 eilers
88 * Bugfixes..
89 *
90 * Revision 1.1 2002/11/09 14:34:52 eilers
91 * Added VCard Backend.
92 *
93 */
94#include "ocontactaccessbackend_vcard.h"
95#include "../../library/backend/vobject_p.h"
96#include "../../library/backend/qfiledirect_p.h"
97
98#include <qpe/timeconversion.h>
99
100#include <qfile.h>
101
102OContactAccessBackend_VCard::OContactAccessBackend_VCard ( const QString& , const QString& filename ):
103 m_dirty( false ),
104 m_file( filename )
105{
106 load();
107}
108
109
110bool OContactAccessBackend_VCard::load ()
111{
112 m_map.clear();
113 m_dirty = false;
114
115 VObject* obj = 0l;
116
117 if ( QFile::exists(m_file) ){
118 obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
119 if ( !obj )
120 return false;
121 }else{
122 qWarning("File \"%s\" not found !", m_file.latin1() );
123 return false;
124 }
125
126 while ( obj ) {
127 OContact con = parseVObject( obj );
128 /*
129 * if uid is 0 assign a new one
130 * this at least happens on
131 * Nokia6210
132 */
133 if ( con.uid() == 0 ){
134 con.setUid( 1 );
135 qWarning("assigned new uid %d",con.uid() );
136 }
137
138 m_map.insert( con.uid(), con );
139
140 VObject *t = obj;
141 obj = nextVObjectInList(obj);
142 cleanVObject( t );
143 }
144
145 return true;
146
147}
148bool OContactAccessBackend_VCard::reload()
149{
150 return load();
151}
152bool OContactAccessBackend_VCard::save()
153{
154 if (!m_dirty )
155 return true;
156
157 QFileDirect file( m_file );
158 if (!file.open(IO_WriteOnly ) )
159 return false;
160
161 VObject *obj;
162 obj = newVObject( VCCalProp );
163 addPropValue( obj, VCVersionProp, "1.0" );
164
165 VObject *vo;
166 for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
167 vo = createVObject( *it );
168 writeVObject( file.directHandle() , vo );
169 cleanVObject( vo );
170 }
171 cleanStrTbl();
172 deleteVObject( obj );
173
174 m_dirty = false;
175 return true;
176
177
178}
179void OContactAccessBackend_VCard::clear ()
180{
181 m_map.clear();
182 m_dirty = true; // ??? sure ? (se)
183}
184
185bool OContactAccessBackend_VCard::add ( const OContact& newcontact )
186{
187 m_map.insert( newcontact.uid(), newcontact );
188 m_dirty = true;
189 return true;
190}
191
192bool OContactAccessBackend_VCard::remove ( int uid )
193{
194 m_map.remove( uid );
195 m_dirty = true;
196 return true;
197}
198
199bool OContactAccessBackend_VCard::replace ( const OContact &contact )
200{
201 m_map.replace( contact.uid(), contact );
202 m_dirty = true;
203 return true;
204}
205
206OContact OContactAccessBackend_VCard::find ( int uid ) const
207{
208 return m_map[uid];
209}
210
211QArray<int> OContactAccessBackend_VCard::allRecords() const
212{
213 QArray<int> ar( m_map.count() );
214 QMap<int, OContact>::ConstIterator it;
215 int i = 0;
216 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
217 ar[i] = it.key();
218 i++;
219 }
220 return ar;
221}
222
223// Not implemented
224QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int, const QDateTime& )
225{
226 QArray<int> ar(0);
227 return ar;
228}
229
230// Not implemented
231QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const
232{
233 QArray<int> ar(0);
234 return ar;
235}
236
237const uint OContactAccessBackend_VCard::querySettings()
238{
239 return 0; // No search possible
240}
241
242bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const
243{
244 return false; // No search possible, therefore all settings invalid ;)
245}
246
247bool OContactAccessBackend_VCard::wasChangedExternally()
248{
249 return false; // Don't expect concurrent access
250}
251
252// Not implemented
253QArray<int> OContactAccessBackend_VCard::sorted( bool , int, int, int )
254{
255 QArray<int> ar(0);
256 return ar;
257}
258
259// *** Private stuff ***
260
261
262OContact OContactAccessBackend_VCard::parseVObject( VObject *obj )
263{
264 OContact c;
265
266 VObjectIterator it;
267 initPropIterator( &it, obj );
268 while( moreIteration( &it ) ) {
269 VObject *o = nextVObject( &it );
270 QCString name = vObjectName( o );
271 QCString value = vObjectStringZValue( o );
272 if ( name == VCNameProp ) {
273 VObjectIterator nit;
274 initPropIterator( &nit, o );
275 while( moreIteration( &nit ) ) {
276 VObject *o = nextVObject( &nit );
277 QCString name = vObjectTypeInfo( o );
278 QString value = vObjectStringZValue( o );
279 if ( name == VCNamePrefixesProp )
280 c.setTitle( value );
281 else if ( name == VCNameSuffixesProp )
282 c.setSuffix( value );
283 else if ( name == VCFamilyNameProp )
284 c.setLastName( value );
285 else if ( name == VCGivenNameProp )
286 c.setFirstName( value );
287 else if ( name == VCAdditionalNamesProp )
288 c.setMiddleName( value );
289 }
290 }
291 else if ( name == VCAdrProp ) {
292 bool work = TRUE; // default address is work address
293 QString street;
294 QString city;
295 QString region;
296 QString postal;
297 QString country;
298
299 VObjectIterator nit;
300 initPropIterator( &nit, o );
301 while( moreIteration( &nit ) ) {
302 VObject *o = nextVObject( &nit );
303 QCString name = vObjectName( o );
304 QString value = vObjectStringZValue( o );
305 if ( name == VCHomeProp )
306 work = FALSE;
307 else if ( name == VCWorkProp )
308 work = TRUE;
309 else if ( name == VCStreetAddressProp )
310 street = value;
311 else if ( name == VCCityProp )
312 city = value;
313 else if ( name == VCRegionProp )
314 region = value;
315 else if ( name == VCPostalCodeProp )
316 postal = value;
317 else if ( name == VCCountryNameProp )
318 country = value;
319 }
320 if ( work ) {
321 c.setBusinessStreet( street );
322 c.setBusinessCity( city );
323 c.setBusinessCountry( country );
324 c.setBusinessZip( postal );
325 c.setBusinessState( region );
326 } else {
327 c.setHomeStreet( street );
328 c.setHomeCity( city );
329 c.setHomeCountry( country );
330 c.setHomeZip( postal );
331 c.setHomeState( region );
332 }
333 }
334 else if ( name == VCTelephoneProp ) {
335 enum {
336 HOME = 0x01,
337 WORK = 0x02,
338 VOICE = 0x04,
339 CELL = 0x08,
340 FAX = 0x10,
341 PAGER = 0x20,
342 UNKNOWN = 0x80
343 };
344 int type = 0;
345
346 VObjectIterator nit;
347 initPropIterator( &nit, o );
348 while( moreIteration( &nit ) ) {
349 VObject *o = nextVObject( &nit );
350 QCString name = vObjectTypeInfo( o );
351 if ( name == VCHomeProp )
352 type |= HOME;
353 else if ( name == VCWorkProp )
354 type |= WORK;
355 else if ( name == VCVoiceProp )
356 type |= VOICE;
357 else if ( name == VCCellularProp )
358 type |= CELL;
359 else if ( name == VCFaxProp )
360 type |= FAX;
361 else if ( name == VCPagerProp )
362 type |= PAGER;
363 else if ( name == VCPreferredProp )
364 ;
365 else
366 type |= UNKNOWN;
367 }
368 if ( (type & UNKNOWN) != UNKNOWN ) {
369 if ( ( type & (HOME|WORK) ) == 0 ) // default
370 type |= HOME;
371 if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default
372 type |= VOICE;
373
374 qWarning("value %s %d", value.data(), type );
375 if ( (type & (VOICE|HOME) ) == (VOICE|HOME) && (type & (CELL|HOME) ) != (CELL|HOME) )
376 c.setHomePhone( value );
377 if ( ( type & (FAX|HOME) ) == (FAX|HOME) )
378 c.setHomeFax( value );
379 if ( ( type & (CELL|HOME) ) == (CELL|HOME) )
380 c.setHomeMobile( value );
381 if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) && (type & (CELL|WORK) ) != (CELL|WORK) )
382 c.setBusinessPhone( value );
383 if ( ( type & (FAX|WORK) ) == (FAX|WORK) )
384 c.setBusinessFax( value );
385 if ( ( type & (CELL|WORK) ) == (CELL|WORK) )
386 c.setBusinessMobile( value );
387 if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) )
388 c.setBusinessPager( value );
389 }
390 }
391 else if ( name == VCEmailAddressProp ) {
392 QString email = vObjectStringZValue( o );
393 bool valid = TRUE;
394 VObjectIterator nit;
395 initPropIterator( &nit, o );
396 while( moreIteration( &nit ) ) {
397 VObject *o = nextVObject( &nit );
398 QCString name = vObjectTypeInfo( o );
399 if ( name != VCInternetProp && name != VCHomeProp &&
400 name != VCWorkProp &&
401 name != VCPreferredProp )
402 // ### preffered should map to default email
403 valid = FALSE;
404 }
405 if ( valid ) {
406 c.insertEmail( email );
407 }
408 }
409 else if ( name == VCURLProp ) {
410 VObjectIterator nit;
411 initPropIterator( &nit, o );
412 while( moreIteration( &nit ) ) {
413 VObject *o = nextVObject( &nit );
414 QCString name = vObjectTypeInfo( o );
415 if ( name == VCHomeProp )
416 c.setHomeWebpage( value );
417 else if ( name == VCWorkProp )
418 c.setBusinessWebpage( value );
419 }
420 }
421 else if ( name == VCOrgProp ) {
422 VObjectIterator nit;
423 initPropIterator( &nit, o );
424 while( moreIteration( &nit ) ) {
425 VObject *o = nextVObject( &nit );
426 QCString name = vObjectName( o );
427 QString value = vObjectStringZValue( o );
428 if ( name == VCOrgNameProp )
429 c.setCompany( value );
430 else if ( name == VCOrgUnitProp )
431 c.setDepartment( value );
432 else if ( name == VCOrgUnit2Prop )
433 c.setOffice( value );
434 }
435 }
436 else if ( name == VCTitleProp ) {
437 c.setJobTitle( value );
438 }
439 else if ( name == "X-Qtopia-Profession" ) {
440 c.setProfession( value );
441 }
442 else if ( name == "X-Qtopia-Manager" ) {
443 c.setManager( value );
444 }
445 else if ( name == "X-Qtopia-Assistant" ) {
446 c.setAssistant( value );
447 }
448 else if ( name == "X-Qtopia-Spouse" ) {
449 c.setSpouse( value );
450 }
451 else if ( name == "X-Qtopia-Gender" ) {
452 c.setGender( value );
453 }
454 else if ( name == "X-Qtopia-Anniversary" ) {
455 c.setAnniversary( convVCardDateToDate( value ) );
456 }
457 else if ( name == "X-Qtopia-Nickname" ) {
458 c.setNickname( value );
459 }
460 else if ( name == "X-Qtopia-Children" ) {
461 c.setChildren( value );
462 }
463 else if ( name == VCBirthDateProp ) {
464 // Reading Birthdate regarding RFC 2425 (5.8.4)
465 c.setBirthday( convVCardDateToDate( value ) );
466
467 }
468 else if ( name == VCCommentProp ) {
469 c.setNotes( value );
470 }
471#if 0
472 else {
473 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
474 VObjectIterator nit;
475 initPropIterator( &nit, o );
476 while( moreIteration( &nit ) ) {
477 VObject *o = nextVObject( &nit );
478 QCString name = vObjectName( o );
479 QString value = vObjectStringZValue( o );
480 printf(" subprop: %s = %s\n", name.data(), value.latin1() );
481 }
482 }
483#endif
484 }
485 c.setFileAs();
486 return c;
487}
488
489
490VObject* OContactAccessBackend_VCard::createVObject( const OContact &c )
491{
492 VObject *vcard = newVObject( VCCardProp );
493 safeAddPropValue( vcard, VCVersionProp, "2.1" );
494 safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) );
495 safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) );
496
497 // full name
498 safeAddPropValue( vcard, VCFullNameProp, c.fullName() );
499
500 // name properties
501 VObject *name = safeAddProp( vcard, VCNameProp );
502 safeAddPropValue( name, VCFamilyNameProp, c.lastName() );
503 safeAddPropValue( name, VCGivenNameProp, c.firstName() );
504 safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() );
505 safeAddPropValue( name, VCNamePrefixesProp, c.title() );
506 safeAddPropValue( name, VCNameSuffixesProp, c.suffix() );
507
508 // home properties
509 VObject *home_adr= safeAddProp( vcard, VCAdrProp );
510 safeAddProp( home_adr, VCHomeProp );
511 safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() );
512 safeAddPropValue( home_adr, VCCityProp, c.homeCity() );
513 safeAddPropValue( home_adr, VCRegionProp, c.homeState() );
514 safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() );
515 safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() );
516
517 VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() );
518 safeAddProp( home_phone, VCHomeProp );
519 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() );
520 safeAddProp( home_phone, VCHomeProp );
521 safeAddProp( home_phone, VCCellularProp );
522 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() );
523 safeAddProp( home_phone, VCHomeProp );
524 safeAddProp( home_phone, VCFaxProp );
525
526 VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() );
527 safeAddProp( url, VCHomeProp );
528
529 // work properties
530 VObject *work_adr= safeAddProp( vcard, VCAdrProp );
531 safeAddProp( work_adr, VCWorkProp );
532 safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() );
533 safeAddPropValue( work_adr, VCCityProp, c.businessCity() );
534 safeAddPropValue( work_adr, VCRegionProp, c.businessState() );
535 safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() );
536 safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() );
537
538 VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() );
539 safeAddProp( work_phone, VCWorkProp );
540 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() );
541 safeAddProp( work_phone, VCWorkProp );
542 safeAddProp( work_phone, VCCellularProp );
543 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() );
544 safeAddProp( work_phone, VCWorkProp );
545 safeAddProp( work_phone, VCFaxProp );
546 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() );
547 safeAddProp( work_phone, VCWorkProp );
548 safeAddProp( work_phone, VCPagerProp );
549
550 url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() );
551 safeAddProp( url, VCWorkProp );
552
553 VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() );
554 safeAddProp( title, VCWorkProp );
555
556
557 QStringList emails = c.emailList();
558 // emails.prepend( c.defaultEmail() ); Fix for bugreport #1045
559 for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) {
560 VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it );
561 safeAddProp( email, VCInternetProp );
562 }
563
564 safeAddPropValue( vcard, VCNoteProp, c.notes() );
565
566 // Exporting Birthday regarding RFC 2425 (5.8.4)
567 if ( c.birthday().isValid() ){
568 qWarning("Exporting birthday as: %s", convDateToVCardDate( c.birthday() ).latin1() );
569 safeAddPropValue( vcard, VCBirthDateProp, convDateToVCardDate( c.birthday() ) );
570 }
571
572 if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) {
573 VObject *org = safeAddProp( vcard, VCOrgProp );
574 safeAddPropValue( org, VCOrgNameProp, c.company() );
575 safeAddPropValue( org, VCOrgUnitProp, c.department() );
576 safeAddPropValue( org, VCOrgUnit2Prop, c.office() );
577 }
578
579 // some values we have to export as custom fields
580 safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() );
581 safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() );
582 safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() );
583
584 safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() );
585 safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() );
586 if ( c.anniversary().isValid() ){
587 qWarning("Exporting anniversary as: %s", convDateToVCardDate( c.anniversary() ).latin1() );
588 safeAddPropValue( vcard, "X-Qtopia-Anniversary", convDateToVCardDate( c.anniversary() ) );
589 }
590 safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() );
591 safeAddPropValue( vcard, "X-Qtopia-Children", c.children() );
592
593 return vcard;
594}
595
596QString OContactAccessBackend_VCard::convDateToVCardDate( const QDate& d ) const
597{
598 QString str_rfc2425 = QString("%1-%2-%3")
599 .arg( d.year() )
600 .arg( d.month(), 2 )
601 .arg( d.day(), 2 );
602 // Now replace spaces with "0"...
603 int pos = 0;
604 while ( ( pos = str_rfc2425.find (' ') ) > 0 )
605 str_rfc2425.replace( pos, 1, "0" );
606
607 return str_rfc2425;
608}
609
610QDate OContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr )
611{
612 int monthPos = datestr.find('-');
613 int dayPos = datestr.find('-', monthPos+1 );
614 int sep_ignore = 1;
615 if ( monthPos == -1 || dayPos == -1 ) {
616 qDebug("fromString didn't find - in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
617 // Ok.. No "-" found, therefore we will try to read other format ( YYYYMMDD )
618 if ( datestr.length() == 8 ){
619 monthPos = 4;
620 dayPos = 6;
621 sep_ignore = 0;
622 qDebug("Try with follwing positions str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
623 } else {
624 return QDate();
625 }
626 }
627 int y = datestr.left( monthPos ).toInt();
628 int m = datestr.mid( monthPos + sep_ignore, dayPos - monthPos - sep_ignore ).toInt();
629 int d = datestr.mid( dayPos + sep_ignore ).toInt();
630 qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, dayPos);
631 QDate date ( y,m,d );
632 return date;
633}
634
635VObject* OContactAccessBackend_VCard::safeAddPropValue( VObject *o, const char *prop, const QString &value )
636{
637 VObject *ret = 0;
638 if ( o && !value.isEmpty() )
639 ret = addPropValue( o, prop, value.latin1() );
640 return ret;
641}
642
643VObject* OContactAccessBackend_VCard::safeAddProp( VObject *o, const char *prop)
644{
645 VObject *ret = 0;
646 if ( o )
647 ret = addProp( o, prop );
648 return ret;
649}
diff --git a/noncore/unsupported/libopie/pim/ocontactaccessbackend_vcard.h b/noncore/unsupported/libopie/pim/ocontactaccessbackend_vcard.h
new file mode 100644
index 0000000..6dbc718
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontactaccessbackend_vcard.h
@@ -0,0 +1,99 @@
1/*
2 * VCard Backend for the OPIE-Contact Database.
3 *
4 * Copyright (C) 2000 Trolltech AS. All rights reserved.
5 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
6 *
7 * =====================================================================
8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 * =====================================================================
13 * ToDo:
14 *
15 * =====================================================================
16 * Version: $Id$
17 * =====================================================================
18 * History:
19 * $Log$
20 * Revision 1.1 2004/11/16 21:46:07 mickeyl
21 * libopie1 goes into unsupported
22 *
23 * Revision 1.6 2003/04/13 18:07:10 zecke
24 * More API doc
25 * QString -> const QString&
26 * QString = 0l -> QString::null
27 *
28 * Revision 1.5 2003/03/21 10:33:09 eilers
29 * Merged speed optimized xml backend for contacts to main.
30 * Added QDateTime to querybyexample. For instance, it is now possible to get
31 * all Birthdays/Anniversaries between two dates. This should be used
32 * to show all birthdays in the datebook..
33 * This change is sourcecode backward compatible but you have to upgrade
34 * the binaries for today-addressbook.
35 *
36 * Revision 1.4 2002/12/07 13:26:22 eilers
37 * Fixing bug in storing anniversary..
38 *
39 * Revision 1.3 2002/11/13 14:14:51 eilers
40 * Added sorted for Contacts..
41 *
42 * Revision 1.2 2002/11/10 15:41:53 eilers
43 * Bugfixes..
44 *
45 * Revision 1.1 2002/11/09 14:34:52 eilers
46 * Added VCard Backend.
47 *
48 */
49#ifndef __OCONTACTACCESSBACKEND_VCARD_H_
50#define __OCONTACTACCESSBACKEND_VCARD_H_
51
52#include <opie/ocontact.h>
53
54#include "ocontactaccessbackend.h"
55
56class VObject;
57
58/**
59 * This is the vCard 2.1 implementation of the Contact Storage
60 * @see OContactAccessBackend_XML
61 * @see OPimAccessBackend
62 */
63class OContactAccessBackend_VCard : public OContactAccessBackend {
64 public:
65 OContactAccessBackend_VCard ( const QString& appname, const QString& filename = QString::null );
66
67 bool load ();
68 bool reload();
69 bool save();
70 void clear ();
71
72 bool add ( const OContact& newcontact );
73 bool remove ( int uid );
74 bool replace ( const OContact& contact );
75
76 OContact find ( int uid ) const;
77 QArray<int> allRecords() const;
78 QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() );
79 QArray<int> matchRegexp( const QRegExp &r ) const;
80
81 const uint querySettings();
82 bool hasQuerySettings (uint querySettings) const;
83 QArray<int> sorted( bool ascending, int sortOrder, int sortFilter, int cat );
84 bool wasChangedExternally();
85
86private:
87 OContact parseVObject( VObject* obj );
88 VObject* createVObject( const OContact& c );
89 QString convDateToVCardDate( const QDate& c ) const;
90 QDate convVCardDateToDate( const QString& datestr );
91 VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value );
92 VObject *safeAddProp( VObject* o, const char* prop);
93
94 bool m_dirty : 1;
95 QString m_file;
96 QMap<int, OContact> m_map;
97};
98
99#endif
diff --git a/noncore/unsupported/libopie/pim/ocontactaccessbackend_xml.cpp b/noncore/unsupported/libopie/pim/ocontactaccessbackend_xml.cpp
new file mode 100644
index 0000000..7ceaf5b
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontactaccessbackend_xml.cpp
@@ -0,0 +1,824 @@
1/*
2 * XML Backend for the OPIE-Contact Database.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 *
13 * =====================================================================
14 * Version: $Id$
15 * =====================================================================
16 * History:
17 * $Log$
18 * Revision 1.1 2004/11/16 21:46:07 mickeyl
19 * libopie1 goes into unsupported
20 *
21 * Revision 1.10 2004/03/01 15:44:36 chicken
22 * fix includes
23 *
24 * Revision 1.9 2003/09/22 14:31:16 eilers
25 * Added first experimental incarnation of sql-backend for addressbook.
26 * Some modifications to be able to compile the todo sql-backend.
27 * A lot of changes fill follow...
28 *
29 * Revision 1.8 2003/08/30 15:28:26 eilers
30 * Removed some unimportant debug output which causes slow down..
31 *
32 * Revision 1.7 2003/08/01 12:30:16 eilers
33 * Merging changes from BRANCH_1_0 to HEAD
34 *
35 * Revision 1.6 2003/07/07 16:19:47 eilers
36 * Fixing serious bug in hasQuerySettings()
37 *
38 * Revision 1.5 2003/04/13 18:07:10 zecke
39 * More API doc
40 * QString -> const QString&
41 * QString = 0l -> QString::null
42 *
43 * Revision 1.4 2003/03/21 14:32:54 mickeyl
44 * g++ compliance fix: default arguments belong into the declaration, but not the definition
45 *
46 * Revision 1.3 2003/03/21 12:26:28 eilers
47 * Fixing small bug: If we search a birthday from today to today, it returned
48 * every contact ..
49 *
50 * Revision 1.2 2003/03/21 10:33:09 eilers
51 * Merged speed optimized xml backend for contacts to main.
52 * Added QDateTime to querybyexample. For instance, it is now possible to get
53 * all Birthdays/Anniversaries between two dates. This should be used
54 * to show all birthdays in the datebook..
55 * This change is sourcecode backward compatible but you have to upgrade
56 * the binaries for today-addressbook.
57 *
58 * Revision 1.1.2.2 2003/02/11 12:17:28 eilers
59 * Speed optimization. Removed the sequential search loops.
60 *
61 * Revision 1.1.2.1 2003/02/10 15:31:38 eilers
62 * Writing offsets to debug output..
63 *
64 * Revision 1.1 2003/02/09 15:05:01 eilers
65 * Nothing happened.. Just some cleanup before I will start..
66 *
67 * Revision 1.12 2003/01/03 16:58:03 eilers
68 * Reenable debug output
69 *
70 * Revision 1.11 2003/01/03 12:31:28 eilers
71 * Bugfix for calculating data diffs..
72 *
73 * Revision 1.10 2003/01/02 14:27:12 eilers
74 * Improved query by example: Search by date is possible.. First step
75 * for a today plugin for birthdays..
76 *
77 * Revision 1.9 2002/12/08 12:48:57 eilers
78 * Moved journal-enum from ocontact into i the xml-backend..
79 *
80 * Revision 1.8 2002/11/14 17:04:24 eilers
81 * Sorting will now work if fullname is identical on some entries
82 *
83 * Revision 1.7 2002/11/13 15:02:46 eilers
84 * Small Bug in sorted fixed
85 *
86 * Revision 1.6 2002/11/13 14:14:51 eilers
87 * Added sorted for Contacts..
88 *
89 * Revision 1.5 2002/11/01 15:10:42 eilers
90 * Added regExp-search in database for all fields in a contact.
91 *
92 * Revision 1.4 2002/10/16 10:52:40 eilers
93 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
94 *
95 * Revision 1.3 2002/10/14 16:21:54 eilers
96 * Some minor interface updates
97 *
98 * Revision 1.2 2002/10/07 17:34:24 eilers
99 * added OBackendFactory for advanced backend access
100 *
101 * Revision 1.1 2002/09/27 17:11:44 eilers
102 * Added API for accessing the Contact-Database ! It is compiling, but
103 * please do not expect that anything is working !
104 * I will debug that stuff in the next time ..
105 * Please read README_COMPILE for compiling !
106 *
107 *
108 */
109
110#include "ocontactaccessbackend_xml.h"
111
112#include <qasciidict.h>
113#include <qfile.h>
114#include <qfileinfo.h>
115#include <qregexp.h>
116#include <qarray.h>
117#include <qmap.h>
118
119#include <qpe/global.h>
120
121#include <opie/xmltree.h>
122#include "ocontactaccessbackend.h"
123#include "ocontactaccess.h"
124
125#include <stdlib.h>
126#include <errno.h>
127
128using namespace Opie;
129
130
131OContactAccessBackend_XML::OContactAccessBackend_XML ( const QString& appname, const QString& filename ):
132 m_changed( false )
133{
134 // Just m_contactlist should call delete if an entry
135 // is removed.
136 m_contactList.setAutoDelete( true );
137 m_uidToContact.setAutoDelete( false );
138
139 m_appName = appname;
140
141 /* Set journalfile name ... */
142 m_journalName = getenv("HOME");
143 m_journalName +="/.abjournal" + appname;
144
145 /* Expecting to access the default filename if nothing else is set */
146 if ( filename.isEmpty() ){
147 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
148 } else
149 m_fileName = filename;
150
151 /* Load Database now */
152 load ();
153}
154
155bool OContactAccessBackend_XML::save()
156{
157
158 if ( !m_changed )
159 return true;
160
161 QString strNewFile = m_fileName + ".new";
162 QFile f( strNewFile );
163 if ( !f.open( IO_WriteOnly|IO_Raw ) )
164 return false;
165
166 int total_written;
167 int idx_offset = 0;
168 QString out;
169
170 // Write Header
171 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
172 " <Groups>\n"
173 " </Groups>\n"
174 " <Contacts>\n";
175 QCString cstr = out.utf8();
176 f.writeBlock( cstr.data(), cstr.length() );
177 idx_offset += cstr.length();
178 out = "";
179
180 // Write all contacts
181 QListIterator<OContact> it( m_contactList );
182 for ( ; it.current(); ++it ) {
183 // qWarning(" Uid %d at Offset: %x", (*it)->uid(), idx_offset );
184 out += "<Contact ";
185 (*it)->save( out );
186 out += "/>\n";
187 cstr = out.utf8();
188 total_written = f.writeBlock( cstr.data(), cstr.length() );
189 idx_offset += cstr.length();
190 if ( total_written != int(cstr.length()) ) {
191 f.close();
192 QFile::remove( strNewFile );
193 return false;
194 }
195 out = "";
196 }
197 out += " </Contacts>\n</AddressBook>\n";
198
199 // Write Footer
200 cstr = out.utf8();
201 total_written = f.writeBlock( cstr.data(), cstr.length() );
202 if ( total_written != int( cstr.length() ) ) {
203 f.close();
204 QFile::remove( strNewFile );
205 return false;
206 }
207 f.close();
208
209 // move the file over, I'm just going to use the system call
210 // because, I don't feel like using QDir.
211 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
212 qWarning( "problem renaming file %s to %s, errno: %d",
213 strNewFile.latin1(), m_journalName.latin1(), errno );
214 // remove the tmp file...
215 QFile::remove( strNewFile );
216 }
217
218 /* The journalfile should be removed now... */
219 removeJournal();
220
221 m_changed = false;
222 return true;
223}
224
225bool OContactAccessBackend_XML::load ()
226{
227 m_contactList.clear();
228 m_uidToContact.clear();
229
230 /* Load XML-File and journal if it exists */
231 if ( !load ( m_fileName, false ) )
232 return false;
233 /* The returncode of the journalfile is ignored due to the
234 * fact that it does not exist when this class is instantiated !
235 * But there may such a file exist, if the application crashed.
236 * Therefore we try to load it to get the changes before the #
237 * crash happened...
238 */
239 load (m_journalName, true);
240
241 return true;
242}
243
244void OContactAccessBackend_XML::clear ()
245{
246 m_contactList.clear();
247 m_uidToContact.clear();
248
249 m_changed = false;
250}
251
252bool OContactAccessBackend_XML::wasChangedExternally()
253{
254 QFileInfo fi( m_fileName );
255
256 QDateTime lastmod = fi.lastModified ();
257
258 return (lastmod != m_readtime);
259}
260
261QArray<int> OContactAccessBackend_XML::allRecords() const
262{
263 QArray<int> uid_list( m_contactList.count() );
264
265 uint counter = 0;
266 QListIterator<OContact> it( m_contactList );
267 for( ; it.current(); ++it ){
268 uid_list[counter++] = (*it)->uid();
269 }
270
271 return ( uid_list );
272}
273
274OContact OContactAccessBackend_XML::find ( int uid ) const
275{
276 OContact foundContact; //Create empty contact
277
278 OContact* found = m_uidToContact.find( QString().setNum( uid ) );
279
280 if ( found ){
281 foundContact = *found;
282 }
283
284 return ( foundContact );
285}
286
287QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, int settings,
288 const QDateTime& d )
289{
290
291 QArray<int> m_currentQuery( m_contactList.count() );
292 QListIterator<OContact> it( m_contactList );
293 uint arraycounter = 0;
294
295 for( ; it.current(); ++it ){
296 /* Search all fields and compare them with query object. Store them into list
297 * if all fields matches.
298 */
299 QDate* queryDate = 0l;
300 QDate* checkDate = 0l;
301 bool allcorrect = true;
302 for ( int i = 0; i < Qtopia::Groups; i++ ) {
303 // Birthday and anniversary are special nonstring fields and should
304 // be handled specially
305 switch ( i ){
306 case Qtopia::Birthday:
307 queryDate = new QDate( query.birthday() );
308 checkDate = new QDate( (*it)->birthday() );
309 case Qtopia::Anniversary:
310 if ( queryDate == 0l ){
311 queryDate = new QDate( query.anniversary() );
312 checkDate = new QDate( (*it)->anniversary() );
313 }
314
315 if ( queryDate->isValid() ){
316 if( checkDate->isValid() ){
317 if ( settings & OContactAccess::DateYear ){
318 if ( queryDate->year() != checkDate->year() )
319 allcorrect = false;
320 }
321 if ( settings & OContactAccess::DateMonth ){
322 if ( queryDate->month() != checkDate->month() )
323 allcorrect = false;
324 }
325 if ( settings & OContactAccess::DateDay ){
326 if ( queryDate->day() != checkDate->day() )
327 allcorrect = false;
328 }
329 if ( settings & OContactAccess::DateDiff ) {
330 QDate current;
331 // If we get an additional date, we
332 // will take this date instead of
333 // the current one..
334 if ( !d.date().isValid() )
335 current = QDate::currentDate();
336 else
337 current = d.date();
338
339 // We have to equalize the year, otherwise
340 // the search will fail..
341 checkDate->setYMD( current.year(),
342 checkDate->month(),
343 checkDate->day() );
344 if ( *checkDate < current )
345 checkDate->setYMD( current.year()+1,
346 checkDate->month(),
347 checkDate->day() );
348
349 // Check whether the birthday/anniversary date is between
350 // the current/given date and the maximum date
351 // ( maximum time range ) !
352 qWarning("Checking if %s is between %s and %s ! ",
353 checkDate->toString().latin1(),
354 current.toString().latin1(),
355 queryDate->toString().latin1() );
356 if ( current.daysTo( *queryDate ) >= 0 ){
357 if ( !( ( *checkDate >= current ) &&
358 ( *checkDate <= *queryDate ) ) ){
359 allcorrect = false;
360 qWarning (" Nope!..");
361 }
362 }
363 }
364 } else{
365 // checkDate is invalid. Therefore this entry is always rejected
366 allcorrect = false;
367 }
368 }
369
370 delete queryDate;
371 queryDate = 0l;
372 delete checkDate;
373 checkDate = 0l;
374 break;
375 default:
376 /* Just compare fields which are not empty in the query object */
377 if ( !query.field(i).isEmpty() ){
378 switch ( settings & ~( OContactAccess::IgnoreCase
379 | OContactAccess::DateDiff
380 | OContactAccess::DateYear
381 | OContactAccess::DateMonth
382 | OContactAccess::DateDay
383 | OContactAccess::MatchOne
384 ) ){
385
386 case OContactAccess::RegExp:{
387 QRegExp expr ( query.field(i),
388 !(settings & OContactAccess::IgnoreCase),
389 false );
390 if ( expr.find ( (*it)->field(i), 0 ) == -1 )
391 allcorrect = false;
392 }
393 break;
394 case OContactAccess::WildCards:{
395 QRegExp expr ( query.field(i),
396 !(settings & OContactAccess::IgnoreCase),
397 true );
398 if ( expr.find ( (*it)->field(i), 0 ) == -1 )
399 allcorrect = false;
400 }
401 break;
402 case OContactAccess::ExactMatch:{
403 if (settings & OContactAccess::IgnoreCase){
404 if ( query.field(i).upper() !=
405 (*it)->field(i).upper() )
406 allcorrect = false;
407 }else{
408 if ( query.field(i) != (*it)->field(i) )
409 allcorrect = false;
410 }
411 }
412 break;
413 }
414 }
415 }
416 }
417 if ( allcorrect ){
418 m_currentQuery[arraycounter++] = (*it)->uid();
419 }
420 }
421
422 // Shrink to fit..
423 m_currentQuery.resize(arraycounter);
424
425 return m_currentQuery;
426}
427
428QArray<int> OContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const
429{
430 QArray<int> m_currentQuery( m_contactList.count() );
431 QListIterator<OContact> it( m_contactList );
432 uint arraycounter = 0;
433
434 for( ; it.current(); ++it ){
435 if ( (*it)->match( r ) ){
436 m_currentQuery[arraycounter++] = (*it)->uid();
437 }
438
439 }
440 // Shrink to fit..
441 m_currentQuery.resize(arraycounter);
442
443 return m_currentQuery;
444}
445
446const uint OContactAccessBackend_XML::querySettings()
447{
448 return ( OContactAccess::WildCards
449 | OContactAccess::IgnoreCase
450 | OContactAccess::RegExp
451 | OContactAccess::ExactMatch
452 | OContactAccess::DateDiff
453 | OContactAccess::DateYear
454 | OContactAccess::DateMonth
455 | OContactAccess::DateDay
456 );
457}
458
459bool OContactAccessBackend_XML::hasQuerySettings (uint querySettings) const
460{
461 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
462 * may be added with any of the other settings. IgnoreCase should never used alone.
463 * Wildcards, RegExp, ExactMatch should never used at the same time...
464 */
465
466 // Step 1: Check whether the given settings are supported by this backend
467 if ( ( querySettings & (
468 OContactAccess::IgnoreCase
469 | OContactAccess::WildCards
470 | OContactAccess::DateDiff
471 | OContactAccess::DateYear
472 | OContactAccess::DateMonth
473 | OContactAccess::DateDay
474 | OContactAccess::RegExp
475 | OContactAccess::ExactMatch
476 ) ) != querySettings )
477 return false;
478
479 // Step 2: Check whether the given combinations are ok..
480
481 // IngoreCase alone is invalid
482 if ( querySettings == OContactAccess::IgnoreCase )
483 return false;
484
485 // WildCards, RegExp and ExactMatch should never used at the same time
486 switch ( querySettings & ~( OContactAccess::IgnoreCase
487 | OContactAccess::DateDiff
488 | OContactAccess::DateYear
489 | OContactAccess::DateMonth
490 | OContactAccess::DateDay
491 )
492 ){
493 case OContactAccess::RegExp:
494 return ( true );
495 case OContactAccess::WildCards:
496 return ( true );
497 case OContactAccess::ExactMatch:
498 return ( true );
499 case 0: // one of the upper removed bits were set..
500 return ( true );
501 default:
502 return ( false );
503 }
504}
505
506// Currently only asc implemented..
507QArray<int> OContactAccessBackend_XML::sorted( bool asc, int , int , int )
508{
509 QMap<QString, int> nameToUid;
510 QStringList names;
511 QArray<int> m_currentQuery( m_contactList.count() );
512
513 // First fill map and StringList with all Names
514 // Afterwards sort namelist and use map to fill array to return..
515 QListIterator<OContact> it( m_contactList );
516 for( ; it.current(); ++it ){
517 names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) );
518 nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() );
519 }
520 names.sort();
521
522 int i = 0;
523 if ( asc ){
524 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
525 m_currentQuery[i++] = nameToUid[ (*it) ];
526 }else{
527 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
528 m_currentQuery[i++] = nameToUid[ (*it) ];
529 }
530
531 return m_currentQuery;
532
533}
534
535bool OContactAccessBackend_XML::add ( const OContact &newcontact )
536{
537 //qWarning("odefaultbackend: ACTION::ADD");
538 updateJournal (newcontact, ACTION_ADD);
539 addContact_p( newcontact );
540
541 m_changed = true;
542
543 return true;
544}
545
546bool OContactAccessBackend_XML::replace ( const OContact &contact )
547{
548 m_changed = true;
549
550 OContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) );
551
552 if ( found ) {
553 OContact* newCont = new OContact( contact );
554
555 updateJournal ( *newCont, ACTION_REPLACE);
556 m_contactList.removeRef ( found );
557 m_contactList.append ( newCont );
558 m_uidToContact.remove( QString().setNum( contact.uid() ) );
559 m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont );
560
561 qWarning("Nur zur Sicherheit: %d == %d ?",contact.uid(), newCont->uid());
562
563 return true;
564 } else
565 return false;
566}
567
568bool OContactAccessBackend_XML::remove ( int uid )
569{
570 m_changed = true;
571
572 OContact* found = m_uidToContact.find ( QString().setNum( uid ) );
573
574 if ( found ) {
575 updateJournal ( *found, ACTION_REMOVE);
576 m_contactList.removeRef ( found );
577 m_uidToContact.remove( QString().setNum( uid ) );
578
579 return true;
580 } else
581 return false;
582}
583
584bool OContactAccessBackend_XML::reload(){
585 /* Reload is the same as load in this implementation */
586 return ( load() );
587}
588
589void OContactAccessBackend_XML::addContact_p( const OContact &newcontact )
590{
591 OContact* contRef = new OContact( newcontact );
592
593 m_contactList.append ( contRef );
594 m_uidToContact.insert( QString().setNum( newcontact.uid() ), contRef );
595}
596
597/* This function loads the xml-database and the journalfile */
598bool OContactAccessBackend_XML::load( const QString filename, bool isJournal )
599{
600
601 /* We use the time of the last read to check if the file was
602 * changed externally.
603 */
604 if ( !isJournal ){
605 QFileInfo fi( filename );
606 m_readtime = fi.lastModified ();
607 }
608
609 const int JOURNALACTION = Qtopia::Notes + 1;
610 const int JOURNALROW = JOURNALACTION + 1;
611
612 bool foundAction = false;
613 journal_action action = ACTION_ADD;
614 int journalKey = 0;
615 QMap<int, QString> contactMap;
616 QMap<QString, QString> customMap;
617 QMap<QString, QString>::Iterator customIt;
618 QAsciiDict<int> dict( 47 );
619
620 dict.setAutoDelete( TRUE );
621 dict.insert( "Uid", new int(Qtopia::AddressUid) );
622 dict.insert( "Title", new int(Qtopia::Title) );
623 dict.insert( "FirstName", new int(Qtopia::FirstName) );
624 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
625 dict.insert( "LastName", new int(Qtopia::LastName) );
626 dict.insert( "Suffix", new int(Qtopia::Suffix) );
627 dict.insert( "FileAs", new int(Qtopia::FileAs) );
628 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
629 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
630 dict.insert( "Emails", new int(Qtopia::Emails) );
631 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
632 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
633 dict.insert( "HomeState", new int(Qtopia::HomeState) );
634 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
635 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
636 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
637 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
638 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
639 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
640 dict.insert( "Company", new int(Qtopia::Company) );
641 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
642 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
643 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
644 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
645 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
646 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
647 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
648 dict.insert( "Department", new int(Qtopia::Department) );
649 dict.insert( "Office", new int(Qtopia::Office) );
650 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
651 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
652 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
653 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
654 dict.insert( "Profession", new int(Qtopia::Profession) );
655 dict.insert( "Assistant", new int(Qtopia::Assistant) );
656 dict.insert( "Manager", new int(Qtopia::Manager) );
657 dict.insert( "Spouse", new int(Qtopia::Spouse) );
658 dict.insert( "Children", new int(Qtopia::Children) );
659 dict.insert( "Gender", new int(Qtopia::Gender) );
660 dict.insert( "Birthday", new int(Qtopia::Birthday) );
661 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
662 dict.insert( "Nickname", new int(Qtopia::Nickname) );
663 dict.insert( "Notes", new int(Qtopia::Notes) );
664 dict.insert( "action", new int(JOURNALACTION) );
665 dict.insert( "actionrow", new int(JOURNALROW) );
666
667 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
668
669 XMLElement *root = XMLElement::load( filename );
670 if(root != 0l ){ // start parsing
671 /* Parse all XML-Elements and put the data into the
672 * Contact-Class
673 */
674 XMLElement *element = root->firstChild();
675 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() );
676 element = element->firstChild();
677
678 /* Search Tag "Contacts" which is the parent of all Contacts */
679 while( element && !isJournal ){
680 if( element->tagName() != QString::fromLatin1("Contacts") ){
681 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s",
682 // element->tagName().latin1());
683 element = element->nextChild();
684 } else {
685 element = element->firstChild();
686 break;
687 }
688 }
689 /* Parse all Contacts and ignore unknown tags */
690 while( element ){
691 if( element->tagName() != QString::fromLatin1("Contact") ){
692 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s",
693 // element->tagName().latin1());
694 element = element->nextChild();
695 continue;
696 }
697 /* Found alement with tagname "contact", now parse and store all
698 * attributes contained
699 */
700 //qWarning("OContactDefBack::load element tagName() : %s",
701 // element->tagName().latin1() );
702 QString dummy;
703 foundAction = false;
704
705 XMLElement::AttributeMap aMap = element->attributes();
706 XMLElement::AttributeMap::Iterator it;
707 contactMap.clear();
708 customMap.clear();
709 for( it = aMap.begin(); it != aMap.end(); ++it ){
710 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1());
711
712 int *find = dict[ it.key() ];
713 /* Unknown attributes will be stored as "Custom" elements */
714 if ( !find ) {
715 // qWarning("Attribute %s not known.", it.key().latin1());
716 //contact.setCustomField(it.key(), it.data());
717 customMap.insert( it.key(), it.data() );
718 continue;
719 }
720
721 /* Check if special conversion is needed and add attribute
722 * into Contact class
723 */
724 switch( *find ) {
725 /*
726 case Qtopia::AddressUid:
727 contact.setUid( it.data().toInt() );
728 break;
729 case Qtopia::AddressCategory:
730 contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
731 break;
732 */
733 case JOURNALACTION:
734 action = journal_action(it.data().toInt());
735 foundAction = true;
736 qWarning ("ODefBack(journal)::ACTION found: %d", action);
737 break;
738 case JOURNALROW:
739 journalKey = it.data().toInt();
740 break;
741 default: // no conversion needed add them to the map
742 contactMap.insert( *find, it.data() );
743 break;
744 }
745 }
746 /* now generate the Contact contact */
747 OContact contact( contactMap );
748
749 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
750 contact.setCustomField( customIt.key(), customIt.data() );
751 }
752
753 if (foundAction){
754 foundAction = false;
755 switch ( action ) {
756 case ACTION_ADD:
757 addContact_p (contact);
758 break;
759 case ACTION_REMOVE:
760 if ( !remove (contact.uid()) )
761 qWarning ("ODefBack(journal)::Unable to remove uid: %d",
762 contact.uid() );
763 break;
764 case ACTION_REPLACE:
765 if ( !replace ( contact ) )
766 qWarning ("ODefBack(journal)::Unable to replace uid: %d",
767 contact.uid() );
768 break;
769 default:
770 qWarning ("Unknown action: ignored !");
771 break;
772 }
773 }else{
774 /* Add contact to list */
775 addContact_p (contact);
776 }
777
778 /* Move to next element */
779 element = element->nextChild();
780 }
781 }else {
782 qWarning("ODefBack::could not load");
783 }
784 delete root;
785 qWarning("returning from loading" );
786 return true;
787}
788
789
790void OContactAccessBackend_XML::updateJournal( const OContact& cnt,
791 journal_action action )
792{
793 QFile f( m_journalName );
794 bool created = !f.exists();
795 if ( !f.open(IO_WriteOnly|IO_Append) )
796 return;
797
798 QString buf;
799 QCString str;
800
801 // if the file was created, we have to set the Tag "<CONTACTS>" to
802 // get a XML-File which is readable by our parser.
803 // This is just a cheat, but better than rewrite the parser.
804 if ( created ){
805 buf = "<Contacts>";
806 QCString cstr = buf.utf8();
807 f.writeBlock( cstr.data(), cstr.length() );
808 }
809
810 buf = "<Contact ";
811 cnt.save( buf );
812 buf += " action=\"" + QString::number( (int)action ) + "\" ";
813 buf += "/>\n";
814 QCString cstr = buf.utf8();
815 f.writeBlock( cstr.data(), cstr.length() );
816}
817
818void OContactAccessBackend_XML::removeJournal()
819{
820 QFile f ( m_journalName );
821 if ( f.exists() )
822 f.remove();
823}
824
diff --git a/noncore/unsupported/libopie/pim/ocontactaccessbackend_xml.h b/noncore/unsupported/libopie/pim/ocontactaccessbackend_xml.h
new file mode 100644
index 0000000..6857844
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontactaccessbackend_xml.h
@@ -0,0 +1,163 @@
1/*
2 * XML Backend for the OPIE-Contact Database.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * ToDo: XML-Backend: Automatic reload if something was changed...
13 * File Locking to protect against concurrent access
14 *
15 *
16 * =====================================================================
17 * Version: $Id$
18 * =====================================================================
19 * History:
20 * $Log$
21 * Revision 1.1 2004/11/16 21:46:07 mickeyl
22 * libopie1 goes into unsupported
23 *
24 * Revision 1.15 2003/09/22 14:31:16 eilers
25 * Added first experimental incarnation of sql-backend for addressbook.
26 * Some modifications to be able to compile the todo sql-backend.
27 * A lot of changes fill follow...
28 *
29 * Revision 1.14 2003/04/13 18:07:10 zecke
30 * More API doc
31 * QString -> const QString&
32 * QString = 0l -> QString::null
33 *
34 * Revision 1.13 2003/03/21 10:33:09 eilers
35 * Merged speed optimized xml backend for contacts to main.
36 * Added QDateTime to querybyexample. For instance, it is now possible to get
37 * all Birthdays/Anniversaries between two dates. This should be used
38 * to show all birthdays in the datebook..
39 * This change is sourcecode backward compatible but you have to upgrade
40 * the binaries for today-addressbook.
41 *
42 * Revision 1.12.2.2 2003/02/11 12:17:28 eilers
43 * Speed optimization. Removed the sequential search loops.
44 *
45 * Revision 1.12.2.1 2003/02/09 15:05:01 eilers
46 * Nothing happened.. Just some cleanup before I will start..
47 *
48 * Revision 1.12 2003/01/03 16:58:03 eilers
49 * Reenable debug output
50 *
51 * Revision 1.11 2003/01/03 12:31:28 eilers
52 * Bugfix for calculating data diffs..
53 *
54 * Revision 1.10 2003/01/02 14:27:12 eilers
55 * Improved query by example: Search by date is possible.. First step
56 * for a today plugin for birthdays..
57 *
58 * Revision 1.9 2002/12/08 12:48:57 eilers
59 * Moved journal-enum from ocontact into i the xml-backend..
60 *
61 * Revision 1.8 2002/11/14 17:04:24 eilers
62 * Sorting will now work if fullname is identical on some entries
63 *
64 * Revision 1.7 2002/11/13 15:02:46 eilers
65 * Small Bug in sorted fixed
66 *
67 * Revision 1.6 2002/11/13 14:14:51 eilers
68 * Added sorted for Contacts..
69 *
70 * Revision 1.5 2002/11/01 15:10:42 eilers
71 * Added regExp-search in database for all fields in a contact.
72 *
73 * Revision 1.4 2002/10/16 10:52:40 eilers
74 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
75 *
76 * Revision 1.3 2002/10/14 16:21:54 eilers
77 * Some minor interface updates
78 *
79 * Revision 1.2 2002/10/07 17:34:24 eilers
80 * added OBackendFactory for advanced backend access
81 *
82 * Revision 1.1 2002/09/27 17:11:44 eilers
83 * Added API for accessing the Contact-Database ! It is compiling, but
84 * please do not expect that anything is working !
85 * I will debug that stuff in the next time ..
86 * Please read README_COMPILE for compiling !
87 *
88 *
89 */
90
91#ifndef _OContactAccessBackend_XML_
92#define _OContactAccessBackend_XML_
93
94#include "ocontactaccessbackend.h"
95#include "ocontactaccess.h"
96
97#include <qlist.h>
98#include <qdict.h>
99
100/* the default xml implementation */
101/**
102 * This class is the XML implementation of a Contact backend
103 * it does implement everything available for OContact.
104 * @see OPimAccessBackend for more information of available methods
105 */
106class OContactAccessBackend_XML : public OContactAccessBackend {
107 public:
108 OContactAccessBackend_XML ( const QString& appname, const QString& filename = QString::null );
109
110 bool save();
111
112 bool load ();
113
114 void clear ();
115
116 bool wasChangedExternally();
117
118 QArray<int> allRecords() const;
119
120 OContact find ( int uid ) const;
121
122 QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() );
123
124 QArray<int> matchRegexp( const QRegExp &r ) const;
125
126 const uint querySettings();
127
128 bool hasQuerySettings (uint querySettings) const;
129
130 // Currently only asc implemented..
131 QArray<int> sorted( bool asc, int , int , int );
132 bool add ( const OContact &newcontact );
133
134 bool replace ( const OContact &contact );
135
136 bool remove ( int uid );
137 bool reload();
138
139 private:
140
141 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE };
142
143 void addContact_p( const OContact &newcontact );
144
145 /* This function loads the xml-database and the journalfile */
146 bool load( const QString filename, bool isJournal );
147
148
149 void updateJournal( const OContact& cnt, journal_action action );
150 void removeJournal();
151
152 protected:
153 bool m_changed;
154 QString m_journalName;
155 QString m_fileName;
156 QString m_appName;
157 QList<OContact> m_contactList;
158 QDateTime m_readtime;
159
160 QDict<OContact> m_uidToContact;
161};
162
163#endif
diff --git a/noncore/unsupported/libopie/pim/ocontactfields.cpp b/noncore/unsupported/libopie/pim/ocontactfields.cpp
new file mode 100644
index 0000000..0f08a5a
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontactfields.cpp
@@ -0,0 +1,477 @@
1
2#include "ocontactfields.h"
3
4#include <qstringlist.h>
5#include <qobject.h>
6
7// We should use our own enum in the future ..
8#include <qpe/recordfields.h>
9#include <qpe/config.h>
10#include <opie/ocontact.h>
11
12/*!
13 \internal
14 Returns a list of personal field names for a contact.
15*/
16QStringList OContactFields::personalfields( bool sorted, bool translated )
17{
18 QStringList list;
19 QMap<int, QString> mapIdToStr;
20 if ( translated )
21 mapIdToStr = idToTrFields();
22 else
23 mapIdToStr = idToUntrFields();
24
25 list.append( mapIdToStr[ Qtopia::AddressUid ] );
26 list.append( mapIdToStr[ Qtopia::AddressCategory ] );
27
28 list.append( mapIdToStr[ Qtopia::Title ] );
29 list.append( mapIdToStr[ Qtopia::FirstName ] );
30 list.append( mapIdToStr[ Qtopia::MiddleName ] );
31 list.append( mapIdToStr[ Qtopia::LastName ] );
32 list.append( mapIdToStr[ Qtopia::Suffix ] );
33 list.append( mapIdToStr[ Qtopia::FileAs ] );
34
35 list.append( mapIdToStr[ Qtopia::JobTitle ] );
36 list.append( mapIdToStr[ Qtopia::Department ] );
37 list.append( mapIdToStr[ Qtopia::Company ] );
38
39 list.append( mapIdToStr[ Qtopia::Notes ] );
40 list.append( mapIdToStr[ Qtopia::Groups ] );
41
42 if (sorted) list.sort();
43 return list;
44}
45
46/*!
47 \internal
48 Returns a list of details field names for a contact.
49*/
50QStringList OContactFields::detailsfields( bool sorted, bool translated )
51{
52 QStringList list;
53 QMap<int, QString> mapIdToStr;
54 if ( translated )
55 mapIdToStr = idToTrFields();
56 else
57 mapIdToStr = idToUntrFields();
58
59 list.append( mapIdToStr[ Qtopia::Office ] );
60 list.append( mapIdToStr[ Qtopia::Profession ] );
61 list.append( mapIdToStr[ Qtopia::Assistant ] );
62 list.append( mapIdToStr[ Qtopia::Manager ] );
63
64 list.append( mapIdToStr[ Qtopia::Spouse ] );
65 list.append( mapIdToStr[ Qtopia::Gender ] );
66 list.append( mapIdToStr[ Qtopia::Birthday ] );
67 list.append( mapIdToStr[ Qtopia::Anniversary ] );
68 list.append( mapIdToStr[ Qtopia::Nickname ] );
69 list.append( mapIdToStr[ Qtopia::Children ] );
70
71 if (sorted) list.sort();
72 return list;
73}
74
75/*!
76 \internal
77 Returns a list of phone field names for a contact.
78*/
79QStringList OContactFields::phonefields( bool sorted, bool translated )
80{
81 QStringList list;
82 QMap<int, QString> mapIdToStr;
83 if ( translated )
84 mapIdToStr = idToTrFields();
85 else
86 mapIdToStr = idToUntrFields();
87
88 list.append( mapIdToStr[Qtopia::BusinessPhone] );
89 list.append( mapIdToStr[Qtopia::BusinessFax] );
90 list.append( mapIdToStr[Qtopia::BusinessMobile] );
91 list.append( mapIdToStr[Qtopia::BusinessPager] );
92 list.append( mapIdToStr[Qtopia::BusinessWebPage] );
93
94 list.append( mapIdToStr[Qtopia::DefaultEmail] );
95 list.append( mapIdToStr[Qtopia::Emails] );
96
97 list.append( mapIdToStr[Qtopia::HomePhone] );
98 list.append( mapIdToStr[Qtopia::HomeFax] );
99 list.append( mapIdToStr[Qtopia::HomeMobile] );
100 // list.append( mapIdToStr[Qtopia::HomePager] );
101 list.append( mapIdToStr[Qtopia::HomeWebPage] );
102
103 if (sorted) list.sort();
104
105 return list;
106}
107
108/*!
109 \internal
110 Returns a list of field names for a contact.
111*/
112QStringList OContactFields::fields( bool sorted, bool translated )
113{
114 QStringList list;
115 QMap<int, QString> mapIdToStr;
116 if ( translated )
117 mapIdToStr = idToTrFields();
118 else
119 mapIdToStr = idToUntrFields();
120
121 list += personalfields( sorted, translated );
122
123 list += phonefields( sorted, translated );
124
125 list.append( mapIdToStr[Qtopia::BusinessStreet] );
126 list.append( mapIdToStr[Qtopia::BusinessCity] );
127 list.append( mapIdToStr[Qtopia::BusinessState] );
128 list.append( mapIdToStr[Qtopia::BusinessZip] );
129 list.append( mapIdToStr[Qtopia::BusinessCountry] );
130
131 list.append( mapIdToStr[Qtopia::HomeStreet] );
132 list.append( mapIdToStr[Qtopia::HomeCity] );
133 list.append( mapIdToStr[Qtopia::HomeState] );
134 list.append( mapIdToStr[Qtopia::HomeZip] );
135 list.append( mapIdToStr[Qtopia::HomeCountry] );
136
137 list += detailsfields( sorted, translated );
138
139 if (sorted) list.sort();
140
141 return list;
142}
143
144
145/*!
146 \internal
147 Returns an untranslated list of personal field names for a contact.
148*/
149QStringList OContactFields::untrpersonalfields( bool sorted )
150{
151 return personalfields( sorted, false );
152}
153
154
155/*!
156 \internal
157 Returns a translated list of personal field names for a contact.
158*/
159QStringList OContactFields::trpersonalfields( bool sorted )
160{
161 return personalfields( sorted, true );
162}
163
164
165/*!
166 \internal
167 Returns an untranslated list of details field names for a contact.
168*/
169QStringList OContactFields::untrdetailsfields( bool sorted )
170{
171 return detailsfields( sorted, false );
172}
173
174
175/*!
176 \internal
177 Returns a translated list of details field names for a contact.
178*/
179QStringList OContactFields::trdetailsfields( bool sorted )
180{
181 return detailsfields( sorted, true );
182}
183
184
185/*!
186 \internal
187 Returns a translated list of phone field names for a contact.
188*/
189QStringList OContactFields::trphonefields( bool sorted )
190{
191 return phonefields( sorted, true );
192}
193
194/*!
195 \internal
196 Returns an untranslated list of phone field names for a contact.
197*/
198QStringList OContactFields::untrphonefields( bool sorted )
199{
200 return phonefields( sorted, false );
201}
202
203
204/*!
205 \internal
206 Returns a translated list of field names for a contact.
207*/
208QStringList OContactFields::trfields( bool sorted )
209{
210 return fields( sorted, true );
211}
212
213/*!
214 \internal
215 Returns an untranslated list of field names for a contact.
216*/
217QStringList OContactFields::untrfields( bool sorted )
218{
219 return fields( sorted, false );
220}
221
222QMap<int, QString> OContactFields::idToTrFields()
223{
224 QMap<int, QString> ret_map;
225
226 ret_map.insert( Qtopia::AddressUid, QObject::tr( "User Id" ) );
227 ret_map.insert( Qtopia::AddressCategory, QObject::tr( "Categories" ) );
228
229 ret_map.insert( Qtopia::Title, QObject::tr( "Name Title") );
230 ret_map.insert( Qtopia::FirstName, QObject::tr( "First Name" ) );
231 ret_map.insert( Qtopia::MiddleName, QObject::tr( "Middle Name" ) );
232 ret_map.insert( Qtopia::LastName, QObject::tr( "Last Name" ) );
233 ret_map.insert( Qtopia::Suffix, QObject::tr( "Suffix" ));
234 ret_map.insert( Qtopia::FileAs, QObject::tr( "File As" ) );
235
236 ret_map.insert( Qtopia::JobTitle, QObject::tr( "Job Title" ) );
237 ret_map.insert( Qtopia::Department, QObject::tr( "Department" ) );
238 ret_map.insert( Qtopia::Company, QObject::tr( "Company" ) );
239 ret_map.insert( Qtopia::BusinessPhone, QObject::tr( "Business Phone" ) );
240 ret_map.insert( Qtopia::BusinessFax, QObject::tr( "Business Fax" ) );
241 ret_map.insert( Qtopia::BusinessMobile, QObject::tr( "Business Mobile" ));
242
243 // email
244 ret_map.insert( Qtopia::DefaultEmail, QObject::tr( "Default Email" ) );
245 ret_map.insert( Qtopia::Emails, QObject::tr( "Emails" ) );
246
247 ret_map.insert( Qtopia::HomePhone, QObject::tr( "Home Phone" ) );
248 ret_map.insert( Qtopia::HomeFax, QObject::tr( "Home Fax" ) );
249 ret_map.insert( Qtopia::HomeMobile, QObject::tr( "Home Mobile" ) );
250
251 // business
252 ret_map.insert( Qtopia::BusinessStreet, QObject::tr( "Business Street" ) );
253 ret_map.insert( Qtopia::BusinessCity, QObject::tr( "Business City" ) );
254 ret_map.insert( Qtopia::BusinessState, QObject::tr( "Business State" ) );
255 ret_map.insert( Qtopia::BusinessZip, QObject::tr( "Business Zip" ) );
256 ret_map.insert( Qtopia::BusinessCountry, QObject::tr( "Business Country" ) );
257 ret_map.insert( Qtopia::BusinessPager, QObject::tr( "Business Pager" ) );
258 ret_map.insert( Qtopia::BusinessWebPage, QObject::tr( "Business WebPage" ) );
259
260 ret_map.insert( Qtopia::Office, QObject::tr( "Office" ) );
261 ret_map.insert( Qtopia::Profession, QObject::tr( "Profession" ) );
262 ret_map.insert( Qtopia::Assistant, QObject::tr( "Assistant" ) );
263 ret_map.insert( Qtopia::Manager, QObject::tr( "Manager" ) );
264
265 // home
266 ret_map.insert( Qtopia::HomeStreet, QObject::tr( "Home Street" ) );
267 ret_map.insert( Qtopia::HomeCity, QObject::tr( "Home City" ) );
268 ret_map.insert( Qtopia::HomeState, QObject::tr( "Home State" ) );
269 ret_map.insert( Qtopia::HomeZip, QObject::tr( "Home Zip" ) );
270 ret_map.insert( Qtopia::HomeCountry, QObject::tr( "Home Country" ) );
271 ret_map.insert( Qtopia::HomeWebPage, QObject::tr( "Home Web Page" ) );
272
273 //personal
274 ret_map.insert( Qtopia::Spouse, QObject::tr( "Spouse" ) );
275 ret_map.insert( Qtopia::Gender, QObject::tr( "Gender" ) );
276 ret_map.insert( Qtopia::Birthday, QObject::tr( "Birthday" ) );
277 ret_map.insert( Qtopia::Anniversary, QObject::tr( "Anniversary" ) );
278 ret_map.insert( Qtopia::Nickname, QObject::tr( "Nickname" ) );
279 ret_map.insert( Qtopia::Children, QObject::tr( "Children" ) );
280
281 // other
282 ret_map.insert( Qtopia::Notes, QObject::tr( "Notes" ) );
283
284
285 return ret_map;
286}
287
288QMap<int, QString> OContactFields::idToUntrFields()
289{
290 QMap<int, QString> ret_map;
291
292 ret_map.insert( Qtopia::AddressUid, "User Id" );
293 ret_map.insert( Qtopia::AddressCategory, "Categories" );
294
295 ret_map.insert( Qtopia::Title, "Name Title" );
296 ret_map.insert( Qtopia::FirstName, "First Name" );
297 ret_map.insert( Qtopia::MiddleName, "Middle Name" );
298 ret_map.insert( Qtopia::LastName, "Last Name" );
299 ret_map.insert( Qtopia::Suffix, "Suffix" );
300 ret_map.insert( Qtopia::FileAs, "File As" );
301
302 ret_map.insert( Qtopia::JobTitle, "Job Title" );
303 ret_map.insert( Qtopia::Department, "Department" );
304 ret_map.insert( Qtopia::Company, "Company" );
305 ret_map.insert( Qtopia::BusinessPhone, "Business Phone" );
306 ret_map.insert( Qtopia::BusinessFax, "Business Fax" );
307 ret_map.insert( Qtopia::BusinessMobile, "Business Mobile" );
308
309 // email
310 ret_map.insert( Qtopia::DefaultEmail, "Default Email" );
311 ret_map.insert( Qtopia::Emails, "Emails" );
312
313 ret_map.insert( Qtopia::HomePhone, "Home Phone" );
314 ret_map.insert( Qtopia::HomeFax, "Home Fax" );
315 ret_map.insert( Qtopia::HomeMobile, "Home Mobile" );
316
317 // business
318 ret_map.insert( Qtopia::BusinessStreet, "Business Street" );
319 ret_map.insert( Qtopia::BusinessCity, "Business City" );
320 ret_map.insert( Qtopia::BusinessState, "Business State" );
321 ret_map.insert( Qtopia::BusinessZip, "Business Zip" );
322 ret_map.insert( Qtopia::BusinessCountry, "Business Country" );
323 ret_map.insert( Qtopia::BusinessPager, "Business Pager" );
324 ret_map.insert( Qtopia::BusinessWebPage, "Business WebPage" );
325
326 ret_map.insert( Qtopia::Office, "Office" );
327 ret_map.insert( Qtopia::Profession, "Profession" );
328 ret_map.insert( Qtopia::Assistant, "Assistant" );
329 ret_map.insert( Qtopia::Manager, "Manager" );
330
331 // home
332 ret_map.insert( Qtopia::HomeStreet, "Home Street" );
333 ret_map.insert( Qtopia::HomeCity, "Home City" );
334 ret_map.insert( Qtopia::HomeState, "Home State" );
335 ret_map.insert( Qtopia::HomeZip, "Home Zip" );
336 ret_map.insert( Qtopia::HomeCountry, "Home Country" );
337 ret_map.insert( Qtopia::HomeWebPage, "Home Web Page" );
338
339 //personal
340 ret_map.insert( Qtopia::Spouse, "Spouse" );
341 ret_map.insert( Qtopia::Gender, "Gender" );
342 ret_map.insert( Qtopia::Birthday, "Birthday" );
343 ret_map.insert( Qtopia::Anniversary, "Anniversary" );
344 ret_map.insert( Qtopia::Nickname, "Nickname" );
345 ret_map.insert( Qtopia::Children, "Children" );
346
347 // other
348 ret_map.insert( Qtopia::Notes, "Notes" );
349 ret_map.insert( Qtopia::Groups, "Groups" );
350
351
352 return ret_map;
353}
354
355QMap<QString, int> OContactFields::trFieldsToId()
356{
357 QMap<int, QString> idtostr = idToTrFields();
358 QMap<QString, int> ret_map;
359
360
361 QMap<int, QString>::Iterator it;
362 for( it = idtostr.begin(); it != idtostr.end(); ++it )
363 ret_map.insert( *it, it.key() );
364
365
366 return ret_map;
367}
368
369/* ======================================================================= */
370
371QMap<QString, int> OContactFields::untrFieldsToId()
372{
373 QMap<int, QString> idtostr = idToUntrFields();
374 QMap<QString, int> ret_map;
375
376
377 QMap<int, QString>::Iterator it;
378 for( it = idtostr.begin(); it != idtostr.end(); ++it )
379 ret_map.insert( *it, it.key() );
380
381
382 return ret_map;
383}
384
385
386OContactFields::OContactFields():
387 fieldOrder( DEFAULT_FIELD_ORDER ),
388 changedFieldOrder( false )
389{
390 // Get the global field order from the config file and
391 // use it as a start pattern
392 Config cfg ( "AddressBook" );
393 cfg.setGroup( "ContactFieldOrder" );
394 globalFieldOrder = cfg.readEntry( "General", DEFAULT_FIELD_ORDER );
395}
396
397OContactFields::~OContactFields(){
398
399 // We will store the fieldorder into the config file
400 // to reuse it for the future..
401 if ( changedFieldOrder ){
402 Config cfg ( "AddressBook" );
403 cfg.setGroup( "ContactFieldOrder" );
404 cfg.writeEntry( "General", globalFieldOrder );
405 }
406}
407
408
409
410void OContactFields::saveToRecord( OContact &cnt ){
411
412 qDebug("ocontactfields saveToRecord: >%s<",fieldOrder.latin1());
413
414 // Store fieldorder into this contact.
415 cnt.setCustomField( CONTACT_FIELD_ORDER_NAME, fieldOrder );
416
417 globalFieldOrder = fieldOrder;
418 changedFieldOrder = true;
419
420}
421
422void OContactFields::loadFromRecord( const OContact &cnt ){
423 qDebug("ocontactfields loadFromRecord");
424 qDebug("loading >%s<",cnt.fullName().latin1());
425
426 // Get fieldorder for this contact. If none is defined,
427 // we will use the global one from the config file..
428
429 fieldOrder = cnt.customField( CONTACT_FIELD_ORDER_NAME );
430
431 qDebug("fieldOrder from contact>%s<",fieldOrder.latin1());
432
433 if (fieldOrder.isEmpty()){
434 fieldOrder = globalFieldOrder;
435 }
436
437
438 qDebug("effective fieldOrder in loadFromRecord >%s<",fieldOrder.latin1());
439}
440
441void OContactFields::setFieldOrder( int num, int index ){
442 qDebug("qcontactfields setfieldorder pos %i -> %i",num,index);
443
444 fieldOrder[num] = QString::number( index, 16 )[0];
445
446 // We will store this new fieldorder globally to
447 // remember it for contacts which have none
448 globalFieldOrder = fieldOrder;
449 changedFieldOrder = true;
450
451 qDebug("fieldOrder >%s<",fieldOrder.latin1());
452}
453
454int OContactFields::getFieldOrder( int num, int defIndex ){
455 qDebug("ocontactfields getFieldOrder");
456 qDebug("fieldOrder >%s<",fieldOrder.latin1());
457
458 // Get index of combo as char..
459 QChar poschar = fieldOrder[num];
460
461 bool ok;
462 int ret = 0;
463 // Convert char to number..
464 if ( !( poschar == QChar::null ) )
465 ret = QString( poschar ).toInt(&ok, 16);
466 else
467 ok = false;
468
469 // Return default value if index for
470 // num was not set or if anything else happened..
471 if ( !ok ) ret = defIndex;
472
473 qDebug("returning >%i<",ret);
474
475 return ret;
476
477}
diff --git a/noncore/unsupported/libopie/pim/ocontactfields.h b/noncore/unsupported/libopie/pim/ocontactfields.h
new file mode 100644
index 0000000..f105de7
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/ocontactfields.h
@@ -0,0 +1,67 @@
1#ifndef OPIE_CONTACTS_FIELDS
2#define OPIE_CONTACTS_FIELDS
3
4class QStringList;
5
6#include <qmap.h>
7#include <qstring.h>
8#include <opie/ocontact.h>
9
10#define CONTACT_FIELD_ORDER_NAME "opie-contactfield-order"
11#define DEFAULT_FIELD_ORDER "__________"
12
13class OContactFields{
14
15 public:
16 OContactFields();
17 ~OContactFields();
18 /** Set the index for combo boxes.
19 * Sets the <b>index</b> of combo <b>num</b>.
20 * @param num selects the number of the combo
21 * @param index sets the index in the combo
22 */
23 void setFieldOrder( int num, int index );
24
25 /** Get the index for combo boxes.
26 * Returns the index of combo <b>num</b> or defindex
27 * if none was defined..
28 * @param num Selects the number of the combo
29 * @param defIndex will be returned if none was defined (either
30 * globally in the config file, nor by the contact which was used
31 * by loadFromRecord() )
32 */
33 int getFieldOrder( int num, int defIndex);
34
35 /** Store fieldorder to contact. */
36 void saveToRecord( OContact& );
37 /** Get Fieldorder from contact. */
38 void loadFromRecord( const OContact& );
39
40 private:
41 QString fieldOrder;
42 QString globalFieldOrder;
43 bool changedFieldOrder;
44
45 public:
46 static QStringList personalfields( bool sorted = true, bool translated = false );
47 static QStringList phonefields( bool sorted = true, bool translated = false );
48 static QStringList detailsfields( bool sorted = true, bool translated = false );
49 static QStringList fields( bool sorted = true, bool translated = false );
50
51 static QStringList trpersonalfields( bool sorted = true );
52 static QStringList untrpersonalfields( bool sorted = true );
53 static QStringList trphonefields( bool sorted = true );
54 static QStringList untrphonefields( bool sorted = true );
55 static QStringList trdetailsfields( bool sorted = true );
56 static QStringList untrdetailsfields( bool sorted = true );
57 static QStringList trfields( bool sorted = true );
58 static QStringList untrfields( bool sorted = true );
59
60 static QMap<int, QString> idToTrFields();
61 static QMap<QString, int> trFieldsToId();
62 static QMap<int, QString> idToUntrFields();
63 static QMap<QString, int> untrFieldsToId();
64
65};
66
67#endif
diff --git a/noncore/unsupported/libopie/pim/oconversion.cpp b/noncore/unsupported/libopie/pim/oconversion.cpp
new file mode 100644
index 0000000..0d15414
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/oconversion.cpp
@@ -0,0 +1,113 @@
1/**********************************************************************
2** Copyright (C) 2003 by Stefan Eilers (eilers.stefan@epost.de)
3**
4** This file may be distributed and/or modified under the terms of the
5** GNU Lesser General Public License version 2 as published by the Free Software
6** Foundation and appearing in the file LICENSE.GPL included in the
7** packaging of this file.
8**
9** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11**
12**********************************************************************/
13
14#include "oconversion.h"
15#include <qpe/timeconversion.h>
16
17
18QString OConversion::dateToString( const QDate &d )
19{
20 if ( d.isNull() || !d.isValid() )
21 return QString::null;
22
23 // ISO format in year, month, day (YYYYMMDD); e.g. 20021231
24 QString year = QString::number( d.year() );
25 QString month = QString::number( d.month() );
26 month = month.rightJustify( 2, '0' );
27 QString day = QString::number( d.day() );
28 day = day.rightJustify( 2, '0' );
29
30 QString str = year + month + day;
31 //qDebug( "\tPimContact dateToStr = %s", str.latin1() );
32
33 return str;
34}
35
36QDate OConversion::dateFromString( const QString& s )
37{
38 QDate date;
39
40 if ( s.isEmpty() )
41 return date;
42
43 // Be backward compatible to old Opie format:
44 // Try to load old format. If it fails, try new ISO-Format!
45 date = TimeConversion::fromString ( s );
46 if ( date.isValid() )
47 return date;
48
49 // Read ISO-Format (YYYYMMDD)
50 int year = s.mid(0, 4).toInt();
51 int month = s.mid(4,2).toInt();
52 int day = s.mid(6,2).toInt();
53
54 // do some quick sanity checking -eilers
55 // but we isValid() again? -zecke
56 if ( year < 1900 || year > 3000 ) {
57 qWarning( "PimContact year is not in range");
58 return date;
59 }
60 if ( month < 0 || month > 12 ) {
61 qWarning( "PimContact month is not in range");
62 return date;
63 }
64 if ( day < 0 || day > 31 ) {
65 qWarning( "PimContact day is not in range");
66 return date;
67 }
68
69 date.setYMD( year, month, day );
70 if ( !date.isValid() ) {
71 qWarning( "PimContact date is not valid");
72 return date;
73 }
74
75 return date;
76}
77QString OConversion::dateTimeToString( const QDateTime& dt ) {
78 if (!dt.isValid() || dt.isNull() ) return QString::null;
79
80 QString year = QString::number( dt.date().year() );
81 QString month = QString::number( dt.date().month() );
82 QString day = QString::number( dt.date().day() );
83
84 QString hour = QString::number( dt.time().hour() );
85 QString min = QString::number( dt.time().minute() );
86 QString sec = QString::number( dt.time().second() );
87
88 month = month.rightJustify( 2, '0' );
89 day = day. rightJustify( 2, '0' );
90 hour = hour. rightJustify( 2, '0' );
91 min = min. rightJustify( 2, '0' );
92 sec = sec. rightJustify( 2, '0' );
93
94 QString str = day + month + year + hour + min + sec;
95
96 return str;
97}
98QDateTime OConversion::dateTimeFromString( const QString& str) {
99
100 if ( str.isEmpty() ) return QDateTime();
101 int day = str.mid(0, 2).toInt();
102 int month = str.mid(2, 2).toInt();
103 int year = str.mid(4, 4).toInt();
104 int hour = str.mid(8, 2).toInt();
105 int min = str.mid(10, 2).toInt();
106 int sec = str.mid(12, 2).toInt();
107
108 QDate date( year, month, day );
109 QTime time( hour, min, sec );
110 QDateTime dt( date, time );
111 return dt;
112}
113
diff --git a/noncore/unsupported/libopie/pim/oconversion.h b/noncore/unsupported/libopie/pim/oconversion.h
new file mode 100644
index 0000000..4c0a497
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/oconversion.h
@@ -0,0 +1,48 @@
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** Copyright (C) 2002-2003 by Stefan Eilers (eilers.stefan@epost.de)
4**
5** This file may be distributed and/or modified under the terms of the
6** GNU General Public License version 2 as published by the Free Software
7** Foundation and appearing in the file LICENSE.GPL included in the
8** packaging of this file.
9**
10** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12**
13** See http://www.trolltech.com/gpl/ for GPL licensing information.
14**
15** Contact info@trolltech.com if any conditions of this licensing are
16** not clear to you.
17**********************************************************************/
18
19#ifndef __oconversion_h__
20#define __oconversion_h__
21
22/* #include <time.h> */
23/* #include <sys/types.h> */
24#include <qdatetime.h>
25
26/* FIXME namespace? -zecke */
27class OConversion
28{
29public:
30 static QString dateToString( const QDate &d );
31 static QDate dateFromString( const QString &datestr );
32
33 /**
34 * simple function to store DateTime as string and read from string
35 * no timezone changing is done
36 * DDMMYYYYHHMMSS is the simple format
37 */
38 static QString dateTimeToString( const QDateTime& );
39 static QDateTime dateTimeFromString( const QString& );
40
41private:
42 class Private;
43 Private* d;
44
45};
46
47#endif // __oconversion_h__
48
diff --git a/noncore/unsupported/libopie/pim/odatebookaccess.cpp b/noncore/unsupported/libopie/pim/odatebookaccess.cpp
new file mode 100644
index 0000000..d95fed6
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/odatebookaccess.cpp
@@ -0,0 +1,81 @@
1#include "obackendfactory.h"
2#include "odatebookaccess.h"
3
4/**
5 * Simple constructor
6 * It takes a ODateBookAccessBackend as parent. If it is 0 the default implementation
7 * will be used!
8 * @param back The backend to be used or 0 for the default backend
9 * @param ac What kind of access is intended
10 */
11ODateBookAccess::ODateBookAccess( ODateBookAccessBackend* back, enum Access ac )
12 : OPimAccessTemplate<OEvent>( back )
13{
14 if (!back )
15 back = OBackendFactory<ODateBookAccessBackend>::Default("datebook", QString::null );
16
17 m_backEnd = back;
18 setBackEnd( m_backEnd );
19}
20ODateBookAccess::~ODateBookAccess() {
21}
22
23/**
24 * @return all events available
25 */
26ODateBookAccess::List ODateBookAccess::rawEvents()const {
27 QArray<int> ints = m_backEnd->rawEvents();
28
29 List lis( ints, this );
30 return lis;
31}
32
33/**
34 * @return all repeating events
35 */
36ODateBookAccess::List ODateBookAccess::rawRepeats()const {
37 QArray<int> ints = m_backEnd->rawRepeats();
38
39 List lis( ints, this );
40 return lis;
41}
42
43/**
44 * @return all non repeating events
45 */
46ODateBookAccess::List ODateBookAccess::nonRepeats()const {
47 QArray<int> ints = m_backEnd->nonRepeats();
48
49 List lis( ints, this );
50 return lis;
51}
52
53/**
54 * @return dates in the time span between from and to
55 * @param from Include all events from...
56 * @param to Include all events to...
57 */
58OEffectiveEvent::ValueList ODateBookAccess::effectiveEvents( const QDate& from, const QDate& to ) const {
59 return m_backEnd->effectiveEvents( from, to );
60}
61/**
62 * @return all events at a given datetime
63 */
64OEffectiveEvent::ValueList ODateBookAccess::effectiveEvents( const QDateTime& start ) const {
65 return m_backEnd->effectiveEvents( start );
66}
67
68/**
69 * @return non repeating dates in the time span between from and to
70 * @param from Include all events from...
71 * @param to Include all events to...
72 */
73OEffectiveEvent::ValueList ODateBookAccess::effectiveNonRepeatingEvents( const QDate& from, const QDate& to ) const {
74 return m_backEnd->effectiveNonRepeatingEvents( from, to );
75}
76/**
77 * @return all non repeating events at a given datetime
78 */
79OEffectiveEvent::ValueList ODateBookAccess::effectiveNonRepeatingEvents( const QDateTime& start ) const {
80 return m_backEnd->effectiveNonRepeatingEvents( start );
81}
diff --git a/noncore/unsupported/libopie/pim/odatebookaccess.h b/noncore/unsupported/libopie/pim/odatebookaccess.h
new file mode 100644
index 0000000..62196da
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/odatebookaccess.h
@@ -0,0 +1,44 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_H
2#define OPIE_DATE_BOOK_ACCESS_H
3
4#include "odatebookaccessbackend.h"
5#include "opimaccesstemplate.h"
6
7#include "oevent.h"
8
9/**
10 * This is the object orientated datebook database. It'll use OBackendFactory
11 * to query for a backend.
12 * All access to the datebook should be done via this class.
13 * Make sure to load and save the datebook this is not part of
14 * destructing and creating the object
15 *
16 * @author Holger Freyther, Stefan Eilers
17 */
18class ODateBookAccess : public OPimAccessTemplate<OEvent> {
19public:
20 ODateBookAccess( ODateBookAccessBackend* = 0l, enum Access acc = Random );
21 ~ODateBookAccess();
22
23 /* return all events */
24 List rawEvents()const;
25
26 /* return repeating events */
27 List rawRepeats()const;
28
29 /* return non repeating events */
30 List nonRepeats()const;
31
32 /* return non repeating events (from,to) */
33 OEffectiveEvent::ValueList effectiveEvents( const QDate& from, const QDate& to ) const;
34 OEffectiveEvent::ValueList effectiveEvents( const QDateTime& start ) const;
35 OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDate& from, const QDate& to ) const;
36 OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDateTime& start ) const;
37
38private:
39 ODateBookAccessBackend* m_backEnd;
40 class Private;
41 Private* d;
42};
43
44#endif
diff --git a/noncore/unsupported/libopie/pim/odatebookaccessbackend.cpp b/noncore/unsupported/libopie/pim/odatebookaccessbackend.cpp
new file mode 100644
index 0000000..f0c5d65
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/odatebookaccessbackend.cpp
@@ -0,0 +1,182 @@
1#include <qtl.h>
2
3#include "orecur.h"
4
5#include "odatebookaccessbackend.h"
6
7namespace {
8/* a small helper to get all NonRepeating events for a range of time */
9 void events( OEffectiveEvent::ValueList& tmpList, const OEvent::ValueList& events,
10 const QDate& from, const QDate& to ) {
11 QDateTime dtStart, dtEnd;
12
13 for ( OEvent::ValueList::ConstIterator it = events.begin(); it != events.end(); ++it ) {
14 dtStart = (*it).startDateTime();
15 dtEnd = (*it).endDateTime();
16
17 /*
18 * If in range
19 */
20 if (dtStart.date() >= from && dtEnd.date() <= to ) {
21 OEffectiveEvent eff;
22 eff.setEvent( (*it) );
23 eff.setDate( dtStart.date() );
24 eff.setStartTime( dtStart.time() );
25
26 /* if not on the same day */
27 if ( dtStart.date() != dtEnd.date() )
28 eff.setEndTime( QTime(23, 59, 0 ) );
29 else
30 eff.setEndTime( dtEnd.time() );
31
32 tmpList.append( eff );
33 }
34
35 /* we must also check for end date information... */
36 if ( dtEnd.date() != dtStart.date() && dtEnd.date() >= from ) {
37 QDateTime dt = dtStart.addDays( 1 );
38 dt.setTime( QTime(0, 0, 0 ) );
39 QDateTime dtStop;
40 if ( dtEnd > to )
41 dtStop = to;
42 else
43 dtStop = dtEnd;
44
45 while ( dt <= dtStop ) {
46 OEffectiveEvent eff;
47 eff.setEvent( (*it) );
48 eff.setDate( dt.date() );
49
50 if ( dt >= from ) {
51 eff.setStartTime( QTime(0, 0, 0 ) );
52 if ( dt.date() == dtEnd.date() )
53 eff.setEndTime( dtEnd.time() );
54 else
55 eff.setEndTime( QTime(23, 59, 0 ) );
56 tmpList.append( eff );
57 }
58 dt = dt.addDays( 1 );
59 }
60 }
61 }
62 }
63
64 void repeat( OEffectiveEvent::ValueList& tmpList, const OEvent::ValueList& list,
65 const QDate& from, const QDate& to ) {
66 QDate repeat;
67 for ( OEvent::ValueList::ConstIterator it = list.begin(); it != list.end(); ++it ) {
68 int dur = (*it).startDateTime().date().daysTo( (*it).endDateTime().date() );
69 QDate itDate = from.addDays(-dur );
70 ORecur rec = (*it).recurrence();
71 if ( !rec.hasEndDate() || rec.endDate() > to ) {
72 rec.setEndDate( to );
73 rec.setHasEndDate( true );
74 }
75 while (rec.nextOcurrence(itDate, repeat ) ) {
76 if (repeat > to ) break;
77 OEffectiveEvent eff;
78 eff.setDate( repeat );
79 if ( (*it).isAllDay() ) {
80 eff.setStartTime( QTime(0, 0, 0 ) );
81 eff.setEndTime( QTime(23, 59, 59 ) );
82 }else {
83 /* we only occur by days, not hours/minutes/seconds. Hence
84 * the actual end and start times will be the same for
85 * every repeated event. For multi day events this is
86 * fixed up later if on wronge day span
87 */
88 eff.setStartTime( (*it).startDateTime().time() );
89 eff.setEndTime( (*it).endDateTime().time() );
90 }
91 if ( dur != 0 ) {
92 // multi-day repeating events
93 QDate sub_it = QMAX( repeat, from );
94 QDate startDate = repeat;
95 QDate endDate = startDate.addDays( dur );
96
97 while ( sub_it <= endDate && sub_it <= to ) {
98 OEffectiveEvent tmpEff = eff;
99 tmpEff.setEvent( (*it) );
100 if ( sub_it != startDate )
101 tmpEff.setStartTime( QTime(0, 0, 0 ) );
102 if ( sub_it != endDate )
103 tmpEff.setEndTime( QTime( 23, 59, 59 ) );
104
105 tmpEff.setDate( sub_it );
106 tmpEff.setEffectiveDates( startDate, endDate );
107 tmpList.append( tmpEff );
108
109 sub_it = sub_it.addDays( 1 );
110 }
111 itDate = endDate;
112 }else {
113 eff.setEvent( (*it) );
114 tmpList.append( eff );
115 itDate = repeat.addDays( 1 );
116 }
117 }
118 }
119 }
120}
121
122ODateBookAccessBackend::ODateBookAccessBackend()
123 : OPimAccessBackend<OEvent>()
124{
125
126}
127ODateBookAccessBackend::~ODateBookAccessBackend() {
128
129}
130OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveEvents( const QDate& from,
131 const QDate& to ) {
132 OEffectiveEvent::ValueList tmpList;
133 OEvent::ValueList list = directNonRepeats();
134
135 events( tmpList, list, from, to );
136 repeat( tmpList, directRawRepeats(),from,to );
137
138 list = directRawRepeats(); // Useless, isn't it ? (eilers)
139
140 qHeapSort( tmpList );
141 return tmpList;
142}
143OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveEvents( const QDateTime& dt ) {
144 OEffectiveEvent::ValueList day = effectiveEvents( dt.date(), dt.date() );
145 OEffectiveEvent::ValueList::Iterator it;
146
147 OEffectiveEvent::ValueList tmpList;
148 QDateTime dtTmp;
149 for ( it = day.begin(); it != day.end(); ++it ) {
150 dtTmp = QDateTime( (*it).date(), (*it).startTime() );
151 if ( QABS(dt.secsTo(dtTmp) ) < 60 )
152 tmpList.append( (*it) );
153 }
154
155 return tmpList;
156}
157
158OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveNonRepeatingEvents( const QDate& from,
159 const QDate& to ) {
160 OEffectiveEvent::ValueList tmpList;
161 OEvent::ValueList list = directNonRepeats();
162
163 events( tmpList, list, from, to );
164
165 qHeapSort( tmpList );
166 return tmpList;
167}
168
169OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveNonRepeatingEvents( const QDateTime& dt ) {
170 OEffectiveEvent::ValueList day = effectiveNonRepeatingEvents( dt.date(), dt.date() );
171 OEffectiveEvent::ValueList::Iterator it;
172
173 OEffectiveEvent::ValueList tmpList;
174 QDateTime dtTmp;
175 for ( it = day.begin(); it != day.end(); ++it ) {
176 dtTmp = QDateTime( (*it).date(), (*it).startTime() );
177 if ( QABS(dt.secsTo(dtTmp) ) < 60 )
178 tmpList.append( (*it) );
179 }
180
181 return tmpList;
182}
diff --git a/noncore/unsupported/libopie/pim/odatebookaccessbackend.h b/noncore/unsupported/libopie/pim/odatebookaccessbackend.h
new file mode 100644
index 0000000..3472ab3
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/odatebookaccessbackend.h
@@ -0,0 +1,90 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_H
2#define OPIE_DATE_BOOK_ACCESS_BACKEND_H
3
4#include <qarray.h>
5
6#include "opimaccessbackend.h"
7#include "oevent.h"
8
9/**
10 * This class is the interface to the storage of Events.
11 * @see OPimAccessBackend
12 *
13 */
14class ODateBookAccessBackend : public OPimAccessBackend<OEvent> {
15public:
16 typedef int UID;
17
18 /**
19 * c'tor without parameter
20 */
21 ODateBookAccessBackend();
22 ~ODateBookAccessBackend();
23
24 /**
25 * This method should return a list of UIDs containing
26 * all events. No filter should be applied
27 * @return list of events
28 */
29 virtual QArray<UID> rawEvents()const = 0;
30
31 /**
32 * This method should return a list of UIDs containing
33 * all repeating events. No filter should be applied
34 * @return list of repeating events
35 */
36 virtual QArray<UID> rawRepeats()const = 0;
37
38 /**
39 * This mthod should return a list of UIDs containing all non
40 * repeating events. No filter should be applied
41 * @return list of nonrepeating events
42 */
43 virtual QArray<UID> nonRepeats() const = 0;
44
45 /**
46 * If you do not want to implement the effectiveEvents methods below
47 * you need to supply it with directNonRepeats.
48 * This method can return empty lists if effectiveEvents is implememted
49 */
50 virtual OEvent::ValueList directNonRepeats() = 0;
51
52 /**
53 * Same as above but return raw repeats!
54 */
55 virtual OEvent::ValueList directRawRepeats() = 0;
56
57 /* is implemented by default but you can reimplement it*/
58 /**
59 * Effective Events are special event occuring during a time frame. This method does calcualte
60 * EffectiveEvents bases on the directNonRepeats and directRawRepeats. You may implement this method
61 * yourself
62 */
63 virtual OEffectiveEvent::ValueList effectiveEvents( const QDate& from, const QDate& to );
64
65 /**
66 * this is an overloaded member function
67 * @see effectiveEvents( const QDate& from, const QDate& to )
68 */
69 virtual OEffectiveEvent::ValueList effectiveEvents( const QDateTime& start );
70
71 /**
72 * Effective Events are special event occuring during a time frame. This method does calcualte
73 * EffectiveEvents bases on the directNonRepeats and directRawRepeats. You may implement this method
74 * yourself
75 */
76 virtual OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDate& from, const QDate& to );
77
78 /**
79 * this is an overloaded member function
80 * @see effectiveNonRepeatingEvents( const QDate& from, const QDate& to )
81 */
82 virtual OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDateTime& start );
83
84private:
85 class Private;
86 Private *d;
87
88};
89
90#endif
diff --git a/noncore/unsupported/libopie/pim/odatebookaccessbackend_sql.cpp b/noncore/unsupported/libopie/pim/odatebookaccessbackend_sql.cpp
new file mode 100644
index 0000000..5f87afe
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/odatebookaccessbackend_sql.cpp
@@ -0,0 +1,374 @@
1/*
2 * SQL Backend for the OPIE-Calender Database.
3 *
4 * Copyright (c) 2003 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * =====================================================================
13 * Version: $Id$
14 * =====================================================================
15 * History:
16 * $Log$
17 * Revision 1.1 2004/11/16 21:46:08 mickeyl
18 * libopie1 goes into unsupported
19 *
20 * Revision 1.4 2004/03/14 13:50:35 alwin
21 * namespace correction
22 *
23 * Revision 1.3 2003/12/22 11:41:39 eilers
24 * Fixing stupid bug, found by sourcode review..
25 *
26 * Revision 1.2 2003/12/22 10:19:26 eilers
27 * Finishing implementation of sql-backend for datebook. But I have to
28 * port the PIM datebook application to use it, before I could debug the
29 * whole stuff.
30 * Thus, PIM-Database backend is finished, but highly experimental. And some
31 * parts are still generic. For instance, the "queryByExample()" methods are
32 * not (or not fully) implemented. Todo: custom-entries not stored.
33 * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
34 * expression search in the database, which is not supported by sqlite !
35 * Therefore we need either an extended sqlite or a workaround which would
36 * be very slow and memory consuming..
37 *
38 * Revision 1.1 2003/12/08 15:18:12 eilers
39 * Committing unfinished sql implementation before merging to libopie2 starts..
40 *
41 *
42 */
43
44#include <stdio.h>
45#include <stdlib.h>
46
47#include <qarray.h>
48#include <qstringlist.h>
49
50#include <qpe/global.h>
51
52#include <opie2/osqldriver.h>
53#include <opie2/osqlmanager.h>
54#include <opie2/osqlquery.h>
55
56#include "orecur.h"
57#include "odatebookaccessbackend_sql.h"
58
59using namespace Opie::DB;
60
61
62ODateBookAccessBackend_SQL::ODateBookAccessBackend_SQL( const QString& ,
63 const QString& fileName )
64 : ODateBookAccessBackend(), m_driver( NULL )
65{
66 m_fileName = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.db" ) : fileName;
67
68 // Get the standart sql-driver from the OSQLManager..
69 OSQLManager man;
70 m_driver = man.standard();
71 m_driver->setUrl( m_fileName );
72
73 initFields();
74
75 load();
76}
77
78ODateBookAccessBackend_SQL::~ODateBookAccessBackend_SQL() {
79 if( m_driver )
80 delete m_driver;
81}
82
83void ODateBookAccessBackend_SQL::initFields()
84{
85
86 // This map contains the translation of the fieldtype id's to
87 // the names of the table columns
88 m_fieldMap.insert( OEvent::FUid, "uid" );
89 m_fieldMap.insert( OEvent::FCategories, "Categories" );
90 m_fieldMap.insert( OEvent::FDescription, "Description" );
91 m_fieldMap.insert( OEvent::FLocation, "Location" );
92 m_fieldMap.insert( OEvent::FType, "Type" );
93 m_fieldMap.insert( OEvent::FAlarm, "Alarm" );
94 m_fieldMap.insert( OEvent::FSound, "Sound" );
95 m_fieldMap.insert( OEvent::FRType, "RType" );
96 m_fieldMap.insert( OEvent::FRWeekdays, "RWeekdays" );
97 m_fieldMap.insert( OEvent::FRPosition, "RPosition" );
98 m_fieldMap.insert( OEvent::FRFreq, "RFreq" );
99 m_fieldMap.insert( OEvent::FRHasEndDate, "RHasEndDate" );
100 m_fieldMap.insert( OEvent::FREndDate, "REndDate" );
101 m_fieldMap.insert( OEvent::FRCreated, "RCreated" );
102 m_fieldMap.insert( OEvent::FRExceptions, "RExceptions" );
103 m_fieldMap.insert( OEvent::FStart, "Start" );
104 m_fieldMap.insert( OEvent::FEnd, "End" );
105 m_fieldMap.insert( OEvent::FNote, "Note" );
106 m_fieldMap.insert( OEvent::FTimeZone, "TimeZone" );
107 m_fieldMap.insert( OEvent::FRecParent, "RecParent" );
108 m_fieldMap.insert( OEvent::FRecChildren, "Recchildren" );
109
110 // Create a map that maps the column name to the id
111 QMapConstIterator<int, QString> it;
112 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
113 m_reverseFieldMap.insert( it.data(), it.key() );
114 }
115
116}
117
118bool ODateBookAccessBackend_SQL::load()
119{
120 if (!m_driver->open() )
121 return false;
122
123 // Don't expect that the database exists.
124 // It is save here to create the table, even if it
125 // do exist. ( Is that correct for all databases ?? )
126 QStringqu = "create table datebook( uid INTEGER PRIMARY KEY ";
127
128 QMap<int, QString>::Iterator it;
129 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
130 qu += QString( ",%1 VARCHAR(10)" ).arg( it.data() );
131 }
132 qu += " );";
133
134 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
135
136 qWarning( "command: %s", qu.latin1() );
137
138 OSQLRawQuery raw( qu );
139 OSQLResult res = m_driver->query( &raw );
140 if ( res.state() != OSQLResult::Success )
141 return false;
142
143 update();
144
145 return true;
146}
147
148void ODateBookAccessBackend_SQL::update()
149{
150
151 QString qu = "select uid from datebook";
152 OSQLRawQuery raw( qu );
153 OSQLResult res = m_driver->query( &raw );
154 if ( res.state() != OSQLResult::Success ){
155 // m_uids.clear();
156 return;
157 }
158
159 m_uids = extractUids( res );
160
161}
162
163bool ODateBookAccessBackend_SQL::reload()
164{
165 return load();
166}
167
168bool ODateBookAccessBackend_SQL::save()
169{
170 return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
171}
172
173QArray<int> ODateBookAccessBackend_SQL::allRecords()const
174{
175 return m_uids;
176}
177
178QArray<int> ODateBookAccessBackend_SQL::queryByExample(const OEvent&, int, const QDateTime& ) {
179 return QArray<int>();
180}
181
182void ODateBookAccessBackend_SQL::clear()
183{
184 QString qu = "drop table datebook;";
185 qu += "drop table custom_data;";
186
187 OSQLRawQuery raw( qu );
188 OSQLResult res = m_driver->query( &raw );
189
190 reload();
191}
192
193
194OEvent ODateBookAccessBackend_SQL::find( int uid ) const{
195 QString qu = "select *";
196 qu += "from datebook where uid = " + QString::number(uid);
197
198 OSQLRawQuery raw( qu );
199 OSQLResult res = m_driver->query( &raw );
200
201 OSQLResultItem resItem = res.first();
202
203 // Create Map for date event and insert UID
204 QMap<int,QString> dateEventMap;
205 dateEventMap.insert( OEvent::FUid, QString::number( uid ) );
206
207 // Now insert the data out of the columns into the map.
208 QMapConstIterator<int, QString> it;
209 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
210 dateEventMap.insert( m_reverseFieldMap[*it], resItem.data( *it ) );
211 }
212
213 // Last step: Put map into date event and return it
214 OEvent retDate( dateEventMap );
215
216 return retDate;
217}
218
219// FIXME: Speed up update of uid's..
220bool ODateBookAccessBackend_SQL::add( const OEvent& ev )
221{
222 QMap<int,QString> eventMap = ev.toMap();
223
224 QString qu = "insert into datebook VALUES( " + QString::number( ev.uid() );
225 QMap<int, QString>::Iterator it;
226 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
227 if ( !eventMap[it.key()].isEmpty() )
228 qu += QString( ",\"%1\"" ).arg( eventMap[it.key()] );
229 else
230 qu += QString( ",\"\"" );
231 }
232 qu += " );";
233
234 // Add custom entries
235 int id = 0;
236 QMap<QString, QString> customMap = ev.toExtraMap();
237 for( QMap<QString, QString>::Iterator it = customMap.begin();
238 it != customMap.end(); ++it ){
239 qu += "insert into custom_data VALUES("
240 + QString::number( ev.uid() )
241 + ","
242 + QString::number( id++ )
243 + ",'"
244 + it.key() //.latin1()
245 + "',"
246 + "0" // Priority for future enhancements
247 + ",'"
248 + it.data() //.latin1()
249 + "');";
250 }
251 qWarning("add %s", qu.latin1() );
252
253 OSQLRawQuery raw( qu );
254 OSQLResult res = m_driver->query( &raw );
255 if ( res.state() != OSQLResult::Success ){
256 return false;
257 }
258
259 // Update list of uid's
260 update();
261
262 return true;
263}
264
265// FIXME: Speed up update of uid's..
266bool ODateBookAccessBackend_SQL::remove( int uid )
267{
268 QString qu = "DELETE from datebook where uid = "
269 + QString::number( uid ) + ";";
270 qu += "DELETE from custom_data where uid = "
271 + QString::number( uid ) + ";";
272
273 OSQLRawQuery raw( qu );
274 OSQLResult res = m_driver->query( &raw );
275 if ( res.state() != OSQLResult::Success ){
276 return false;
277 }
278
279 // Update list of uid's
280 update();
281
282 return true;
283}
284
285bool ODateBookAccessBackend_SQL::replace( const OEvent& ev )
286{
287 remove( ev.uid() );
288 return add( ev );
289}
290
291QArray<int> ODateBookAccessBackend_SQL::rawEvents()const
292{
293 return allRecords();
294}
295
296QArray<int> ODateBookAccessBackend_SQL::rawRepeats()const
297{
298 QString qu = "select uid from datebook where RType!=\"\" AND RType!=\"NoRepeat\"";
299 OSQLRawQuery raw( qu );
300 OSQLResult res = m_driver->query( &raw );
301 if ( res.state() != OSQLResult::Success ){
302 QArray<int> nix;
303 return nix;
304 }
305
306 return extractUids( res );
307}
308
309QArray<int> ODateBookAccessBackend_SQL::nonRepeats()const
310{
311 QString qu = "select uid from datebook where RType=\"\" or RType=\"NoRepeat\"";
312 OSQLRawQuery raw( qu );
313 OSQLResult res = m_driver->query( &raw );
314 if ( res.state() != OSQLResult::Success ){
315 QArray<int> nix;
316 return nix;
317 }
318
319 return extractUids( res );
320}
321
322OEvent::ValueList ODateBookAccessBackend_SQL::directNonRepeats()
323{
324 QArray<int> nonRepUids = nonRepeats();
325 OEvent::ValueList list;
326
327 for (uint i = 0; i < nonRepUids.count(); ++i ){
328 list.append( find( nonRepUids[i] ) );
329 }
330
331 return list;
332
333}
334OEvent::ValueList ODateBookAccessBackend_SQL::directRawRepeats()
335{
336 QArray<int> rawRepUids = rawRepeats();
337 OEvent::ValueList list;
338
339 for (uint i = 0; i < rawRepUids.count(); ++i ){
340 list.append( find( rawRepUids[i] ) );
341 }
342
343 return list;
344}
345
346
347QArray<int> ODateBookAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
348{
349 QArray<int> null;
350 return null;
351}
352
353/* ===== Private Functions ========================================== */
354
355QArray<int> ODateBookAccessBackend_SQL::extractUids( OSQLResult& res ) const
356{
357 qWarning("extractUids");
358 QTime t;
359 t.start();
360 OSQLResultItem::ValueList list = res.results();
361 OSQLResultItem::ValueList::Iterator it;
362 QArray<int> ints(list.count() );
363 qWarning(" count = %d", list.count() );
364
365 int i = 0;
366 for (it = list.begin(); it != list.end(); ++it ) {
367 ints[i] = (*it).data("uid").toInt();
368 i++;
369 }
370 qWarning("extractUids ready: count2 = %d needs %d ms", i, t.elapsed() );
371
372 return ints;
373
374}
diff --git a/noncore/unsupported/libopie/pim/odatebookaccessbackend_sql.h b/noncore/unsupported/libopie/pim/odatebookaccessbackend_sql.h
new file mode 100644
index 0000000..ba514bc
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/odatebookaccessbackend_sql.h
@@ -0,0 +1,65 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
2#define OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
3
4#include <qmap.h>
5#include <opie2/osqlresult.h>
6
7#include "odatebookaccessbackend.h"
8
9namespace Opie { namespace DB {
10class OSQLDriver;
11
12}}
13
14/**
15 * This is the default SQL implementation for DateBoook SQL storage
16 * It fully implements the interface
17 * @see ODateBookAccessBackend
18 * @see OPimAccessBackend
19 */
20class ODateBookAccessBackend_SQL : public ODateBookAccessBackend {
21public:
22 ODateBookAccessBackend_SQL( const QString& appName,
23 const QString& fileName = QString::null);
24 ~ODateBookAccessBackend_SQL();
25
26 bool load();
27 bool reload();
28 bool save();
29
30 QArray<int> allRecords()const;
31 QArray<int> matchRegexp(const QRegExp &r) const;
32 QArray<int> queryByExample( const OEvent&, int, const QDateTime& d = QDateTime() );
33 OEvent find( int uid )const;
34 void clear();
35 bool add( const OEvent& ev );
36 bool remove( int uid );
37 bool replace( const OEvent& ev );
38
39 QArray<UID> rawEvents()const;
40 QArray<UID> rawRepeats()const;
41 QArray<UID> nonRepeats()const;
42
43 OEvent::ValueList directNonRepeats();
44 OEvent::ValueList directRawRepeats();
45
46private:
47 bool loadFile();
48 QString m_fileName;
49 QArray<int> m_uids;
50
51 QMap<int, QString> m_fieldMap;
52 QMap<QString, int> m_reverseFieldMap;
53
54 Opie::DB::OSQLDriver* m_driver;
55
56 class Private;
57 Private *d;
58
59 void initFields();
60 void update();
61 QArray<int> extractUids( Opie::DB::OSQLResult& res ) const;
62
63};
64
65#endif
diff --git a/noncore/unsupported/libopie/pim/odatebookaccessbackend_xml.cpp b/noncore/unsupported/libopie/pim/odatebookaccessbackend_xml.cpp
new file mode 100644
index 0000000..929d004
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/odatebookaccessbackend_xml.cpp
@@ -0,0 +1,612 @@
1#include <errno.h>
2#include <fcntl.h>
3
4#include <stdio.h>
5#include <stdlib.h>
6
7#include <sys/types.h>
8#include <sys/mman.h>
9#include <sys/stat.h>
10
11#include <unistd.h>
12
13#include <qasciidict.h>
14#include <qfile.h>
15
16#include <qtopia/global.h>
17#include <qtopia/stringutil.h>
18#include <qtopia/timeconversion.h>
19
20#include "opimnotifymanager.h"
21#include "orecur.h"
22#include "otimezone.h"
23#include "odatebookaccessbackend_xml.h"
24
25namespace {
26 // FROM TT again
27char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
28{
29 char needleChar;
30 char haystackChar;
31 if (!needle || !haystack || !hLen || !nLen)
32 return 0;
33
34 const char* hsearch = haystack;
35
36 if ((needleChar = *needle++) != 0) {
37 nLen--; //(to make up for needle++)
38 do {
39 do {
40 if ((haystackChar = *hsearch++) == 0)
41 return (0);
42 if (hsearch >= haystack + hLen)
43 return (0);
44 } while (haystackChar != needleChar);
45 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
46 hsearch--;
47 }
48 return ((char *)hsearch);
49}
50}
51
52namespace {
53 time_t start, end, created, rp_end;
54 ORecur* rec;
55 ORecur* recur() {
56 if (!rec)
57 rec = new ORecur;
58
59 return rec;
60 }
61 int alarmTime;
62 int snd;
63 enum Attribute{
64 FDescription = 0,
65 FLocation,
66 FCategories,
67 FUid,
68 FType,
69 FAlarm,
70 FSound,
71 FRType,
72 FRWeekdays,
73 FRPosition,
74 FRFreq,
75 FRHasEndDate,
76 FREndDate,
77 FRStart,
78 FREnd,
79 FNote,
80 FCreated, // Should't this be called FRCreated ?
81 FTimeZone,
82 FRecParent,
83 FRecChildren,
84 FExceptions
85 };
86
87 // FIXME: Use OEvent::toMap() here !! (eilers)
88 inline void save( const OEvent& ev, QString& buf ) {
89 qWarning("Saving %d %s", ev.uid(), ev.description().latin1() );
90 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\"";
91 if (!ev.location().isEmpty() )
92 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\"";
93
94 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\"";
95 buf += " uid=\"" + QString::number( ev.uid() ) + "\"";
96
97 if (ev.isAllDay() )
98 buf += " type=\"AllDay\""; // is that all ?? (eilers)
99
100 if (ev.hasNotifiers() ) {
101 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first
102 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60;
103 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\"";
104 if ( alarm.sound() == OPimAlarm::Loud )
105 buf += "loud";
106 else
107 buf += "silent";
108 buf += "\"";
109 }
110 if ( ev.hasRecurrence() ) {
111 buf += ev.recurrence().toString();
112 }
113
114 /*
115 * fscking timezones :) well, we'll first convert
116 * the QDateTime to a QDateTime in UTC time
117 * and then we'll create a nice time_t
118 */
119 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
120 buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\"";
121 buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\"";
122 if (!ev.note().isEmpty() ) {
123 buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\"";
124 }
125
126 buf += " timezone=\"";
127 if ( ev.timeZone().isEmpty() )
128 buf += "None";
129 else
130 buf += ev.timeZone();
131 buf += "\"";
132
133 if (ev.parent() != 0 ) {
134 buf += " recparent=\""+QString::number(ev.parent() )+"\"";
135 }
136
137 if (ev.children().count() != 0 ) {
138 QArray<int> children = ev.children();
139 buf += " recchildren=\"";
140 for ( uint i = 0; i < children.count(); i++ ) {
141 if ( i != 0 ) buf += " ";
142 buf += QString::number( children[i] );
143 }
144 buf+= "\"";
145 }
146
147 // skip custom writing
148 }
149
150 inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) {
151 QMap<int, OEvent>::ConstIterator it;
152 QString buf;
153 QCString str;
154 int total_written;
155 for ( it = list.begin(); it != list.end(); ++it ) {
156 buf = "<event";
157 save( it.data(), buf );
158 buf += " />\n";
159 str = buf.utf8();
160
161 total_written = file.writeBlock(str.data(), str.length() );
162 if ( total_written != int(str.length() ) )
163 return false;
164 }
165 return true;
166 }
167}
168
169ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& ,
170 const QString& fileName )
171 : ODateBookAccessBackend() {
172 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName;
173 m_changed = false;
174}
175ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() {
176}
177bool ODateBookAccessBackend_XML::load() {
178 return loadFile();
179}
180bool ODateBookAccessBackend_XML::reload() {
181 clear();
182 return load();
183}
184bool ODateBookAccessBackend_XML::save() {
185 if (!m_changed) return true;
186
187 int total_written;
188 QString strFileNew = m_name + ".new";
189
190 QFile f( strFileNew );
191 if (!f.open( IO_WriteOnly | IO_Raw ) ) return false;
192
193 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
194 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n";
195 buf += "<events>\n";
196 QCString str = buf.utf8();
197 total_written = f.writeBlock( str.data(), str.length() );
198 if ( total_written != int(str.length() ) ) {
199 f.close();
200 QFile::remove( strFileNew );
201 return false;
202 }
203
204 if (!forAll( m_raw, f ) ) {
205 f.close();
206 QFile::remove( strFileNew );
207 return false;
208 }
209 if (!forAll( m_rep, f ) ) {
210 f.close();
211 QFile::remove( strFileNew );
212 return false;
213 }
214
215 buf = "</events>\n</DATEBOOK>\n";
216 str = buf.utf8();
217 total_written = f.writeBlock( str.data(), str.length() );
218 if ( total_written != int(str.length() ) ) {
219 f.close();
220 QFile::remove( strFileNew );
221 return false;
222 }
223 f.close();
224
225 if ( ::rename( strFileNew, m_name ) < 0 ) {
226 QFile::remove( strFileNew );
227 return false;
228 }
229
230 m_changed = false;
231 return true;
232}
233QArray<int> ODateBookAccessBackend_XML::allRecords()const {
234 QArray<int> ints( m_raw.count()+ m_rep.count() );
235 uint i = 0;
236 QMap<int, OEvent>::ConstIterator it;
237
238 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
239 ints[i] = it.key();
240 i++;
241 }
242 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
243 ints[i] = it.key();
244 i++;
245 }
246
247 return ints;
248}
249QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) {
250 return QArray<int>();
251}
252void ODateBookAccessBackend_XML::clear() {
253 m_changed = true;
254 m_raw.clear();
255 m_rep.clear();
256}
257OEvent ODateBookAccessBackend_XML::find( int uid ) const{
258 if ( m_raw.contains( uid ) )
259 return m_raw[uid];
260 else
261 return m_rep[uid];
262}
263bool ODateBookAccessBackend_XML::add( const OEvent& ev ) {
264 m_changed = true;
265 if (ev.hasRecurrence() )
266 m_rep.insert( ev.uid(), ev );
267 else
268 m_raw.insert( ev.uid(), ev );
269
270 return true;
271}
272bool ODateBookAccessBackend_XML::remove( int uid ) {
273 m_changed = true;
274 m_rep.remove( uid );
275 m_rep.remove( uid );
276
277 return true;
278}
279bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) {
280 replace( ev.uid() ); // ??? Shouldn't this be "remove( ev.uid() ) ??? (eilers)
281 return add( ev );
282}
283QArray<int> ODateBookAccessBackend_XML::rawEvents()const {
284 return allRecords();
285}
286QArray<int> ODateBookAccessBackend_XML::rawRepeats()const {
287 QArray<int> ints( m_rep.count() );
288 uint i = 0;
289 QMap<int, OEvent>::ConstIterator it;
290
291 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
292 ints[i] = it.key();
293 i++;
294 }
295
296 return ints;
297}
298QArray<int> ODateBookAccessBackend_XML::nonRepeats()const {
299 QArray<int> ints( m_raw.count() );
300 uint i = 0;
301 QMap<int, OEvent>::ConstIterator it;
302
303 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
304 ints[i] = it.key();
305 i++;
306 }
307
308 return ints;
309}
310OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() {
311 OEvent::ValueList list;
312 QMap<int, OEvent>::ConstIterator it;
313 for (it = m_raw.begin(); it != m_raw.end(); ++it )
314 list.append( it.data() );
315
316 return list;
317}
318OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() {
319 OEvent::ValueList list;
320 QMap<int, OEvent>::ConstIterator it;
321 for (it = m_rep.begin(); it != m_rep.end(); ++it )
322 list.append( it.data() );
323
324 return list;
325}
326
327// FIXME: Use OEvent::fromMap() (eilers)
328bool ODateBookAccessBackend_XML::loadFile() {
329 m_changed = false;
330
331 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY );
332 if ( fd < 0 ) return false;
333
334 struct stat attribute;
335 if ( ::fstat(fd, &attribute ) == -1 ) {
336 ::close( fd );
337 return false;
338 }
339 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 );
340 if ( map_addr == ( (caddr_t)-1) ) {
341 ::close( fd );
342 return false;
343 }
344
345 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL );
346 ::close( fd );
347
348 QAsciiDict<int> dict(FExceptions+1);
349 dict.setAutoDelete( true );
350 dict.insert( "description", new int(FDescription) );
351 dict.insert( "location", new int(FLocation) );
352 dict.insert( "categories", new int(FCategories) );
353 dict.insert( "uid", new int(FUid) );
354 dict.insert( "type", new int(FType) );
355 dict.insert( "alarm", new int(FAlarm) );
356 dict.insert( "sound", new int(FSound) );
357 dict.insert( "rtype", new int(FRType) );
358 dict.insert( "rweekdays", new int(FRWeekdays) );
359 dict.insert( "rposition", new int(FRPosition) );
360 dict.insert( "rfreq", new int(FRFreq) );
361 dict.insert( "rhasenddate", new int(FRHasEndDate) );
362 dict.insert( "enddt", new int(FREndDate) );
363 dict.insert( "start", new int(FRStart) );
364 dict.insert( "end", new int(FREnd) );
365 dict.insert( "note", new int(FNote) );
366 dict.insert( "created", new int(FCreated) ); // Shouldn't this be FRCreated ??
367 dict.insert( "recparent", new int(FRecParent) );
368 dict.insert( "recchildren", new int(FRecChildren) );
369 dict.insert( "exceptions", new int(FExceptions) );
370 dict.insert( "timezone", new int(FTimeZone) );
371
372 char* dt = (char*)map_addr;
373 int len = attribute.st_size;
374 int i = 0;
375 char* point;
376 const char* collectionString = "<event ";
377 int strLen = ::strlen(collectionString);
378 int *find;
379 while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) {
380 i = point -dt;
381 i+= strLen;
382
383 alarmTime = -1;
384 snd = 0; // silent
385
386 OEvent ev;
387 rec = 0;
388
389 while ( TRUE ) {
390 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
391 ++i;
392 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
393 break;
394
395
396 // we have another attribute, read it.
397 int j = i;
398 while ( j < len && dt[j] != '=' )
399 ++j;
400 QCString attr( dt+i, j-i+1);
401
402 i = ++j; // skip =
403
404 // find the start of quotes
405 while ( i < len && dt[i] != '"' )
406 ++i;
407 j = ++i;
408
409 bool haveUtf = FALSE;
410 bool haveEnt = FALSE;
411 while ( j < len && dt[j] != '"' ) {
412 if ( ((unsigned char)dt[j]) > 0x7f )
413 haveUtf = TRUE;
414 if ( dt[j] == '&' )
415 haveEnt = TRUE;
416 ++j;
417 }
418 if ( i == j ) {
419 // empty value
420 i = j + 1;
421 continue;
422 }
423
424 QCString value( dt+i, j-i+1 );
425 i = j + 1;
426
427 QString str = (haveUtf ? QString::fromUtf8( value )
428 : QString::fromLatin1( value ) );
429 if ( haveEnt )
430 str = Qtopia::plainString( str );
431
432 /*
433 * add key + value
434 */
435 find = dict[attr.data()];
436 if (!find)
437 ev.setCustomField( attr, str );
438 else {
439 setField( ev, *find, str );
440 }
441 }
442 /* time to finalize */
443 finalizeRecord( ev );
444 delete rec;
445 }
446 ::munmap(map_addr, attribute.st_size );
447 m_changed = false; // changed during add
448
449 return true;
450}
451
452// FIXME: Use OEvent::fromMap() which makes this obsolete.. (eilers)
453void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) {
454 /* AllDay is alway in UTC */
455 if ( ev.isAllDay() ) {
456 OTimeZone utc = OTimeZone::utc();
457 ev.setStartDateTime( utc.fromUTCDateTime( start ) );
458 ev.setEndDateTime ( utc.fromUTCDateTime( end ) );
459 ev.setTimeZone( "UTC"); // make sure it is really utc
460 }else {
461 /* to current date time */
462 // qWarning(" Start is %d", start );
463 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
464 QDateTime date = zone.toDateTime( start );
465 qWarning(" Start is %s", date.toString().latin1() );
466 ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
467
468 date = zone.toDateTime( end );
469 ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
470 }
471 if ( rec && rec->doesRecur() ) {
472 OTimeZone utc = OTimeZone::utc();
473 ORecur recu( *rec ); // call copy c'tor;
474 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() );
475 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) );
476 recu.setStart( ev.startDateTime().date() );
477 ev.setRecurrence( recu );
478 }
479
480 if (alarmTime != -1 ) {
481 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 );
482 OPimAlarm al( snd , dt );
483 ev.notifiers().add( al );
484 }
485 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) {
486 qWarning("already contains assign uid");
487 ev.setUid( 1 );
488 }
489 qWarning("addind %d %s", ev.uid(), ev.description().latin1() );
490 if ( ev.hasRecurrence() )
491 m_rep.insert( ev.uid(), ev );
492 else
493 m_raw.insert( ev.uid(), ev );
494
495}
496void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) {
497// qWarning(" setting %s", value.latin1() );
498 switch( id ) {
499 case FDescription:
500 e.setDescription( value );
501 break;
502 case FLocation:
503 e.setLocation( value );
504 break;
505 case FCategories:
506 e.setCategories( e.idsFromString( value ) );
507 break;
508 case FUid:
509 e.setUid( value.toInt() );
510 break;
511 case FType:
512 if ( value == "AllDay" ) {
513 e.setAllDay( true );
514 e.setTimeZone( "UTC" );
515 }
516 break;
517 case FAlarm:
518 alarmTime = value.toInt();
519 break;
520 case FSound:
521 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent;
522 break;
523 // recurrence stuff
524 case FRType:
525 if ( value == "Daily" )
526 recur()->setType( ORecur::Daily );
527 else if ( value == "Weekly" )
528 recur()->setType( ORecur::Weekly);
529 else if ( value == "MonthlyDay" )
530 recur()->setType( ORecur::MonthlyDay );
531 else if ( value == "MonthlyDate" )
532 recur()->setType( ORecur::MonthlyDate );
533 else if ( value == "Yearly" )
534 recur()->setType( ORecur::Yearly );
535 else
536 recur()->setType( ORecur::NoRepeat );
537 break;
538 case FRWeekdays:
539 recur()->setDays( value.toInt() );
540 break;
541 case FRPosition:
542 recur()->setPosition( value.toInt() );
543 break;
544 case FRFreq:
545 recur()->setFrequency( value.toInt() );
546 break;
547 case FRHasEndDate:
548 recur()->setHasEndDate( value.toInt() );
549 break;
550 case FREndDate: {
551 rp_end = (time_t) value.toLong();
552 break;
553 }
554 case FRStart: {
555 start = (time_t) value.toLong();
556 break;
557 }
558 case FREnd: {
559 end = ( (time_t) value.toLong() );
560 break;
561 }
562 case FNote:
563 e.setNote( value );
564 break;
565 case FCreated:
566 created = value.toInt();
567 break;
568 case FRecParent:
569 e.setParent( value.toInt() );
570 break;
571 case FRecChildren:{
572 QStringList list = QStringList::split(' ', value );
573 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
574 e.addChild( (*it).toInt() );
575 }
576 }
577 break;
578 case FExceptions:{
579 QStringList list = QStringList::split(' ', value );
580 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
581 QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() );
582 qWarning("adding exception %s", date.toString().latin1() );
583 recur()->exceptions().append( date );
584 }
585 }
586 break;
587 case FTimeZone:
588 if ( value != "None" )
589 e.setTimeZone( value );
590 break;
591 default:
592 break;
593 }
594}
595QArray<int> ODateBookAccessBackend_XML::matchRegexp( const QRegExp &r ) const
596{
597 QArray<int> m_currentQuery( m_raw.count()+ m_rep.count() );
598 uint arraycounter = 0;
599 QMap<int, OEvent>::ConstIterator it;
600
601 for ( it = m_raw.begin(); it != m_raw.end(); ++it )
602 if ( it.data().match( r ) )
603 m_currentQuery[arraycounter++] = it.data().uid();
604 for ( it = m_rep.begin(); it != m_rep.end(); ++it )
605 if ( it.data().match( r ) )
606 m_currentQuery[arraycounter++] = it.data().uid();
607
608 // Shrink to fit..
609 m_currentQuery.resize(arraycounter);
610
611 return m_currentQuery;
612}
diff --git a/noncore/unsupported/libopie/pim/odatebookaccessbackend_xml.h b/noncore/unsupported/libopie/pim/odatebookaccessbackend_xml.h
new file mode 100644
index 0000000..a5cc0fc
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/odatebookaccessbackend_xml.h
@@ -0,0 +1,55 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H
2#define OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H
3
4#include <qmap.h>
5
6#include "odatebookaccessbackend.h"
7
8/**
9 * This is the default XML implementation for DateBoook XML storage
10 * It fully implements the interface
11 * @see ODateBookAccessBackend
12 * @see OPimAccessBackend
13 */
14class ODateBookAccessBackend_XML : public ODateBookAccessBackend {
15public:
16 ODateBookAccessBackend_XML( const QString& appName,
17 const QString& fileName = QString::null);
18 ~ODateBookAccessBackend_XML();
19
20 bool load();
21 bool reload();
22 bool save();
23
24 QArray<int> allRecords()const;
25 QArray<int> matchRegexp(const QRegExp &r) const;
26 QArray<int> queryByExample( const OEvent&, int, const QDateTime& d = QDateTime() );
27 OEvent find( int uid )const;
28 void clear();
29 bool add( const OEvent& ev );
30 bool remove( int uid );
31 bool replace( const OEvent& ev );
32
33 QArray<UID> rawEvents()const;
34 QArray<UID> rawRepeats()const;
35 QArray<UID> nonRepeats()const;
36
37 OEvent::ValueList directNonRepeats();
38 OEvent::ValueList directRawRepeats();
39
40private:
41 bool m_changed :1 ;
42 bool loadFile();
43 inline void finalizeRecord( OEvent& ev );
44 inline void setField( OEvent&, int field, const QString& val );
45 QString m_name;
46 QMap<int, OEvent> m_raw;
47 QMap<int, OEvent> m_rep;
48
49 struct Data;
50 Data* data;
51 class Private;
52 Private *d;
53};
54
55#endif
diff --git a/noncore/unsupported/libopie/pim/oevent.cpp b/noncore/unsupported/libopie/pim/oevent.cpp
new file mode 100644
index 0000000..9b31957
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/oevent.cpp
@@ -0,0 +1,717 @@
1#include <qshared.h>
2#include <qarray.h>
3
4#include <qpe/palmtopuidgen.h>
5#include <qpe/categories.h>
6#include <qpe/stringutil.h>
7
8#include "orecur.h"
9#include "opimresolver.h"
10#include "opimnotifymanager.h"
11
12#include "oevent.h"
13
14int OCalendarHelper::week( const QDate& date) {
15 // Calculates the week this date is in within that
16 // month. Equals the "row" is is in in the month view
17 int week = 1;
18 QDate tmp( date.year(), date.month(), 1 );
19 if ( date.dayOfWeek() < tmp.dayOfWeek() )
20 ++week;
21
22 week += ( date.day() - 1 ) / 7;
23
24 return week;
25}
26int OCalendarHelper::ocurrence( const QDate& date) {
27 // calculates the number of occurrances of this day of the
28 // week till the given date (e.g 3rd Wednesday of the month)
29 return ( date.day() - 1 ) / 7 + 1;
30}
31int OCalendarHelper::dayOfWeek( char day ) {
32 int dayOfWeek = 1;
33 char i = ORecur::MON;
34 while ( !( i & day ) && i <= ORecur::SUN ) {
35 i <<= 1;
36 ++dayOfWeek;
37 }
38 return dayOfWeek;
39}
40int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) {
41 return ( second.year() - first.year() ) * 12 +
42 second.month() - first.month();
43}
44
45struct OEvent::Data : public QShared {
46 Data() : QShared() {
47 child = 0;
48 recur = 0;
49 manager = 0;
50 isAllDay = false;
51 parent = 0;
52 }
53 ~Data() {
54 delete manager;
55 delete recur;
56 }
57 QString description;
58 QString location;
59 OPimNotifyManager* manager;
60 ORecur* recur;
61 QString note;
62 QDateTime created;
63 QDateTime start;
64 QDateTime end;
65 bool isAllDay : 1;
66 QString timezone;
67 QArray<int>* child;
68 int parent;
69};
70
71OEvent::OEvent( int uid )
72 : OPimRecord( uid ) {
73 data = new Data;
74}
75OEvent::OEvent( const OEvent& ev)
76 : OPimRecord( ev ), data( ev.data )
77{
78 data->ref();
79}
80
81OEvent::OEvent( const QMap<int, QString> map )
82 : OPimRecord( 0 )
83{
84 data = new Data;
85
86 fromMap( map );
87}
88
89OEvent::~OEvent() {
90 if ( data->deref() ) {
91 delete data;
92 data = 0;
93 }
94}
95OEvent& OEvent::operator=( const OEvent& ev) {
96 if ( this == &ev ) return *this;
97
98 OPimRecord::operator=( ev );
99 ev.data->ref();
100 deref();
101 data = ev.data;
102
103
104 return *this;
105}
106QString OEvent::description()const {
107 return data->description;
108}
109void OEvent::setDescription( const QString& description ) {
110 changeOrModify();
111 data->description = description;
112}
113void OEvent::setLocation( const QString& loc ) {
114 changeOrModify();
115 data->location = loc;
116}
117QString OEvent::location()const {
118 return data->location;
119}
120OPimNotifyManager &OEvent::notifiers()const {
121 // I hope we can skip the changeOrModify here
122 // the notifier should take care of it
123 // and OPimNotify is shared too
124 if (!data->manager )
125 data->manager = new OPimNotifyManager;
126
127 return *data->manager;
128}
129bool OEvent::hasNotifiers()const {
130 if (!data->manager )
131 return false;
132 if (data->manager->reminders().isEmpty() &&
133 data->manager->alarms().isEmpty() )
134 return false;
135
136 return true;
137}
138ORecur OEvent::recurrence()const {
139 if (!data->recur)
140 data->recur = new ORecur;
141
142 return *data->recur;
143}
144void OEvent::setRecurrence( const ORecur& rec) {
145 changeOrModify();
146 if (data->recur )
147 (*data->recur) = rec;
148 else
149 data->recur = new ORecur( rec );
150}
151bool OEvent::hasRecurrence()const {
152 if (!data->recur ) return false;
153 return data->recur->doesRecur();
154}
155QString OEvent::note()const {
156 return data->note;
157}
158void OEvent::setNote( const QString& note ) {
159 changeOrModify();
160 data->note = note;
161}
162QDateTime OEvent::createdDateTime()const {
163 return data->created;
164}
165void OEvent::setCreatedDateTime( const QDateTime& time ) {
166 changeOrModify();
167 data->created = time;
168}
169QDateTime OEvent::startDateTime()const {
170 if ( data->isAllDay )
171 return QDateTime( data->start.date(), QTime(0, 0, 0 ) );
172 return data->start;
173}
174QDateTime OEvent::startDateTimeInZone()const {
175 /* if no timezone, or all day event or if the current and this timeZone match... */
176 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime();
177
178 OTimeZone zone(data->timezone );
179 return zone.toDateTime( data->start, OTimeZone::current() );
180}
181void OEvent::setStartDateTime( const QDateTime& dt ) {
182 changeOrModify();
183 data->start = dt;
184}
185QDateTime OEvent::endDateTime()const {
186 /*
187 * if all Day event the end time needs
188 * to be on the same day as the start
189 */
190 if ( data->isAllDay )
191 return QDateTime( data->start.date(), QTime(23, 59, 59 ) );
192 return data->end;
193}
194QDateTime OEvent::endDateTimeInZone()const {
195 /* if no timezone, or all day event or if the current and this timeZone match... */
196 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime();
197
198 OTimeZone zone(data->timezone );
199 return zone.toDateTime( data->end, OTimeZone::current() );
200}
201void OEvent::setEndDateTime( const QDateTime& dt ) {
202 changeOrModify();
203 data->end = dt;
204}
205bool OEvent::isMultipleDay()const {
206 return data->end.date().day() - data->start.date().day();
207}
208bool OEvent::isAllDay()const {
209 return data->isAllDay;
210}
211void OEvent::setAllDay( bool allDay ) {
212 changeOrModify();
213 data->isAllDay = allDay;
214 if (allDay ) data->timezone = "UTC";
215}
216void OEvent::setTimeZone( const QString& tz ) {
217 changeOrModify();
218 data->timezone = tz;
219}
220QString OEvent::timeZone()const {
221 if (data->isAllDay ) return QString::fromLatin1("UTC");
222 return data->timezone;
223}
224bool OEvent::match( const QRegExp& re )const {
225 if ( re.match( data->description ) != -1 ){
226 setLastHitField( Qtopia::DatebookDescription );
227 return true;
228 }
229 if ( re.match( data->note ) != -1 ){
230 setLastHitField( Qtopia::Note );
231 return true;
232 }
233 if ( re.match( data->location ) != -1 ){
234 setLastHitField( Qtopia::Location );
235 return true;
236 }
237 if ( re.match( data->start.toString() ) != -1 ){
238 setLastHitField( Qtopia::StartDateTime );
239 return true;
240 }
241 if ( re.match( data->end.toString() ) != -1 ){
242 setLastHitField( Qtopia::EndDateTime );
243 return true;
244 }
245 return false;
246}
247QString OEvent::toRichText()const {
248 QString text, value;
249
250 // description
251 text += "<b><h3><img src=\"datebook/DateBook\">";
252 if ( !description().isEmpty() ) {
253 text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "" );
254 }
255 text += "</h3></b><br><hr><br>";
256
257 // location
258 if ( !(value = location()).isEmpty() ) {
259 text += "<b>" + QObject::tr( "Location:" ) + "</b> ";
260 text += Qtopia::escapeString(value) + "<br>";
261 }
262
263 // all day event
264 if ( isAllDay() ) {
265 text += "<b><i>" + QObject::tr( "This is an all day event" ) + "</i></b><br>";
266 }
267 // multiple day event
268 else if ( isMultipleDay () ) {
269 text += "<b><i>" + QObject::tr( "This is a multiple day event" ) + "</i></b><br>";
270 }
271 // start & end times
272 else {
273 // start time
274 if ( startDateTime().isValid() ) {
275 text += "<b>" + QObject::tr( "Start:") + "</b> ";
276 text += Qtopia::escapeString(startDateTime().toString() ).
277 replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
278 }
279
280 // end time
281 if ( endDateTime().isValid() ) {
282 text += "<b>" + QObject::tr( "End:") + "</b> ";
283 text += Qtopia::escapeString(endDateTime().toString() ).
284 replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
285 }
286 }
287
288 // categories
289 if ( categoryNames("Calendar").count() ){
290 text += "<b>" + QObject::tr( "Category:") + "</b> ";
291 text += categoryNames("Calendar").join(", ");
292 text += "<br>";
293 }
294
295 //notes
296 if ( !note().isEmpty() ) {
297 text += "<b>" + QObject::tr( "Note:") + "</b><br>";
298 text += note();
299// text += Qtopia::escapeString(note() ).
300// replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
301 }
302 return text;
303}
304QString OEvent::toShortText()const {
305 QString text;
306 text += QString::number( startDateTime().date().day() );
307 text += ".";
308 text += QString::number( startDateTime().date().month() );
309 text += ".";
310 text += QString::number( startDateTime().date().year() );
311 text += " ";
312 text += QString::number( startDateTime().time().hour() );
313 text += ":";
314 text += QString::number( startDateTime().time().minute() );
315 text += " - ";
316 text += description();
317 return text;
318}
319QString OEvent::type()const {
320 return QString::fromLatin1("OEvent");
321}
322QString OEvent::recordField( int /*id */ )const {
323 return QString::null;
324}
325int OEvent::rtti() {
326 return OPimResolver::DateBook;
327}
328bool OEvent::loadFromStream( QDataStream& ) {
329 return true;
330}
331bool OEvent::saveToStream( QDataStream& )const {
332 return true;
333}
334void OEvent::changeOrModify() {
335 if ( data->count != 1 ) {
336 data->deref();
337 Data* d2 = new Data;
338 d2->description = data->description;
339 d2->location = data->location;
340
341 if (data->manager )
342 d2->manager = new OPimNotifyManager( *data->manager );
343
344 if ( data->recur )
345 d2->recur = new ORecur( *data->recur );
346
347 d2->note = data->note;
348 d2->created = data->created;
349 d2->start = data->start;
350 d2->end = data->end;
351 d2->isAllDay = data->isAllDay;
352 d2->timezone = data->timezone;
353 d2->parent = data->parent;
354
355 if ( data->child ) {
356 d2->child = new QArray<int>( *data->child );
357 d2->child->detach();
358 }
359
360 data = d2;
361 }
362}
363void OEvent::deref() {
364 if ( data->deref() ) {
365 delete data;
366 data = 0;
367 }
368}
369// Exporting Event data to map. Using the same
370// encoding as ODateBookAccessBackend_xml does..
371// Thus, we could remove the stuff there and use this
372// for it and for all other places..
373// Encoding should happen at one place, only ! (eilers)
374QMap<int, QString> OEvent::toMap()const {
375 QMap<int, QString> retMap;
376
377 retMap.insert( OEvent::FUid, QString::number( uid() ) );
378 retMap.insert( OEvent::FCategories, Qtopia::escapeString( Qtopia::Record::idsToString( categories() ) ));
379 retMap.insert( OEvent::FDescription, Qtopia::escapeString( description() ) );
380 retMap.insert( OEvent::FLocation, Qtopia::escapeString( location() ) );
381 retMap.insert( OEvent::FType, isAllDay() ? "AllDay" : "" );
382 OPimAlarm alarm = notifiers().alarms()[0];
383 retMap.insert( OEvent::FAlarm, QString::number( alarm.dateTime().secsTo( startDateTime() ) / 60 ) );
384 retMap.insert( OEvent::FSound, (alarm.sound() == OPimAlarm::Loud) ? "loud" : "silent" );
385
386 OTimeZone zone( timeZone().isEmpty() ? OTimeZone::current() : timeZone() );
387 retMap.insert( OEvent::FStart, QString::number( zone.fromUTCDateTime( zone.toDateTime( startDateTime(), OTimeZone::utc() ) ) ) );
388 retMap.insert( OEvent::FEnd, QString::number( zone.fromUTCDateTime( zone.toDateTime( endDateTime(), OTimeZone::utc() ) ) ) );
389 retMap.insert( OEvent::FNote, Qtopia::escapeString( note() ) );
390 retMap.insert( OEvent::FTimeZone, timeZone().isEmpty() ? QString( "None" ) : timeZone() );
391 if( parent() )
392 retMap.insert( OEvent::FRecParent, QString::number( parent() ) );
393 if( children().count() ){
394 QArray<int> childr = children();
395 QString buf;
396 for ( uint i = 0; i < childr.count(); i++ ) {
397 if ( i != 0 ) buf += " ";
398 buf += QString::number( childr[i] );
399 }
400 retMap.insert( OEvent::FRecChildren, buf );
401 }
402
403 // Add recurrence stuff
404 if( hasRecurrence() ){
405 ORecur recur = recurrence();
406 QMap<int, QString> recFields = recur.toMap();
407 retMap.insert( OEvent::FRType, recFields[ORecur::RType] );
408 retMap.insert( OEvent::FRWeekdays, recFields[ORecur::RWeekdays] );
409 retMap.insert( OEvent::FRPosition, recFields[ORecur::RPosition] );
410 retMap.insert( OEvent::FRFreq, recFields[ORecur::RFreq] );
411 retMap.insert( OEvent::FRHasEndDate, recFields[ORecur::RHasEndDate] );
412 retMap.insert( OEvent::FREndDate, recFields[ORecur::EndDate] );
413 retMap.insert( OEvent::FRCreated, recFields[ORecur::Created] );
414 retMap.insert( OEvent::FRExceptions, recFields[ORecur::Exceptions] );
415 } else {
416 ORecur recur = recurrence();
417 QMap<int, QString> recFields = recur.toMap();
418 retMap.insert( OEvent::FRType, recFields[ORecur::RType] );
419 }
420
421 return retMap;
422}
423
424void OEvent::fromMap( const QMap<int, QString>& map )
425{
426
427 // We just want to set the UID if it is really stored.
428 if ( !map[OEvent::FUid].isEmpty() )
429 setUid( map[OEvent::FUid].toInt() );
430
431 setCategories( idsFromString( map[OEvent::FCategories] ) );
432 setDescription( map[OEvent::FDescription] );
433 setLocation( map[OEvent::FLocation] );
434
435 if ( map[OEvent::FType] == "AllDay" )
436 setAllDay( true );
437 else
438 setAllDay( false );
439
440 int alarmTime = -1;
441 if( !map[OEvent::FAlarm].isEmpty() )
442 alarmTime = map[OEvent::FAlarm].toInt();
443
444 int sound = ( ( map[OEvent::FSound] == "loud" ) ? OPimAlarm::Loud : OPimAlarm::Silent );
445 if ( ( alarmTime != -1 ) ){
446 QDateTime dt = startDateTime().addSecs( -1*alarmTime*60 );
447 OPimAlarm al( sound , dt );
448 notifiers().add( al );
449 }
450 if ( !map[OEvent::FTimeZone].isEmpty() && ( map[OEvent::FTimeZone] != "None" ) ){
451 setTimeZone( map[OEvent::FTimeZone] );
452 }
453
454 time_t start = (time_t) map[OEvent::FStart].toLong();
455 time_t end = (time_t) map[OEvent::FEnd].toLong();
456
457 /* AllDay is always in UTC */
458 if ( isAllDay() ) {
459 OTimeZone utc = OTimeZone::utc();
460 setStartDateTime( utc.fromUTCDateTime( start ) );
461 setEndDateTime ( utc.fromUTCDateTime( end ) );
462 setTimeZone( "UTC"); // make sure it is really utc
463 }else {
464 /* to current date time */
465 // qWarning(" Start is %d", start );
466 OTimeZone zone( timeZone().isEmpty() ? OTimeZone::current() : timeZone() );
467 QDateTime date = zone.toDateTime( start );
468 qWarning(" Start is %s", date.toString().latin1() );
469 setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
470
471 date = zone.toDateTime( end );
472 setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
473 }
474
475 if ( !map[OEvent::FRecParent].isEmpty() )
476 setParent( map[OEvent::FRecParent].toInt() );
477
478 if ( !map[OEvent::FRecChildren].isEmpty() ){
479 QStringList list = QStringList::split(' ', map[OEvent::FRecChildren] );
480 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
481 addChild( (*it).toInt() );
482 }
483 }
484
485 // Fill recurrence stuff and put it directly into the ORecur-Object using fromMap..
486 if( !map[OEvent::FRType].isEmpty() ){
487 QMap<int, QString> recFields;
488 recFields.insert( ORecur::RType, map[OEvent::FRType] );
489 recFields.insert( ORecur::RWeekdays, map[OEvent::FRWeekdays] );
490 recFields.insert( ORecur::RPosition, map[OEvent::FRPosition] );
491 recFields.insert( ORecur::RFreq, map[OEvent::FRFreq] );
492 recFields.insert( ORecur::RHasEndDate, map[OEvent::FRHasEndDate] );
493 recFields.insert( ORecur::EndDate, map[OEvent::FREndDate] );
494 recFields.insert( ORecur::Created, map[OEvent::FRCreated] );
495 recFields.insert( ORecur::Exceptions, map[OEvent::FRExceptions] );
496 ORecur recur( recFields );
497 setRecurrence( recur );
498 }
499
500}
501
502
503int OEvent::parent()const {
504 return data->parent;
505}
506void OEvent::setParent( int uid ) {
507 changeOrModify();
508 data->parent = uid;
509}
510QArray<int> OEvent::children() const{
511 if (!data->child) return QArray<int>();
512 else
513 return data->child->copy();
514}
515void OEvent::setChildren( const QArray<int>& arr ) {
516 changeOrModify();
517 if (data->child) delete data->child;
518
519 data->child = new QArray<int>( arr );
520 data->child->detach();
521}
522void OEvent::addChild( int uid ) {
523 changeOrModify();
524 if (!data->child ) {
525 data->child = new QArray<int>(1);
526 (*data->child)[0] = uid;
527 }else{
528 int count = data->child->count();
529 data->child->resize( count + 1 );
530 (*data->child)[count] = uid;
531 }
532}
533void OEvent::removeChild( int uid ) {
534 if (!data->child || !data->child->contains( uid ) ) return;
535 changeOrModify();
536 QArray<int> newAr( data->child->count() - 1 );
537 int j = 0;
538 uint count = data->child->count();
539 for ( uint i = 0; i < count; i++ ) {
540 if ( (*data->child)[i] != uid ) {
541 newAr[j] = (*data->child)[i];
542 j++;
543 }
544 }
545 (*data->child) = newAr;
546}
547struct OEffectiveEvent::Data : public QShared {
548 Data() : QShared() {
549 }
550 OEvent event;
551 QDate date;
552 QTime start, end;
553 QDate startDate, endDate;
554 bool dates : 1;
555};
556
557OEffectiveEvent::OEffectiveEvent() {
558 data = new Data;
559 data->date = QDate::currentDate();
560 data->start = data->end = QTime::currentTime();
561 data->dates = false;
562}
563OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate,
564 Position pos ) {
565 data = new Data;
566 data->event = ev;
567 data->date = startDate;
568 if ( pos & Start )
569 data->start = ev.startDateTime().time();
570 else
571 data->start = QTime( 0, 0, 0 );
572
573 if ( pos & End )
574 data->end = ev.endDateTime().time();
575 else
576 data->end = QTime( 23, 59, 59 );
577
578 data->dates = false;
579}
580OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) {
581 data = ev.data;
582 data->ref();
583}
584OEffectiveEvent::~OEffectiveEvent() {
585 if ( data->deref() ) {
586 delete data;
587 data = 0;
588 }
589}
590OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) {
591 if ( *this == ev ) return *this;
592
593 ev.data->ref();
594 deref();
595 data = ev.data;
596
597 return *this;
598}
599
600void OEffectiveEvent::setStartTime( const QTime& ti) {
601 changeOrModify();
602 data->start = ti;
603}
604void OEffectiveEvent::setEndTime( const QTime& en) {
605 changeOrModify();
606 data->end = en;
607}
608void OEffectiveEvent::setEvent( const OEvent& ev) {
609 changeOrModify();
610 data->event = ev;
611}
612void OEffectiveEvent::setDate( const QDate& da) {
613 changeOrModify();
614 data->date = da;
615}
616void OEffectiveEvent::setEffectiveDates( const QDate& from,
617 const QDate& to ) {
618 if (!from.isValid() ) {
619 data->dates = false;
620 return;
621 }
622
623 data->startDate = from;
624 data->endDate = to;
625}
626QString OEffectiveEvent::description()const {
627 return data->event.description();
628}
629QString OEffectiveEvent::location()const {
630 return data->event.location();
631}
632QString OEffectiveEvent::note()const {
633 return data->event.note();
634}
635OEvent OEffectiveEvent::event()const {
636 return data->event;
637}
638QTime OEffectiveEvent::startTime()const {
639 return data->start;
640}
641QTime OEffectiveEvent::endTime()const {
642 return data->end;
643}
644QDate OEffectiveEvent::date()const {
645 return data->date;
646}
647int OEffectiveEvent::length()const {
648 return (data->end.hour() * 60 - data->start.hour() * 60)
649 + QABS(data->start.minute() - data->end.minute() );
650}
651int OEffectiveEvent::size()const {
652 return ( data->end.hour() - data->start.hour() ) * 3600
653 + (data->end.minute() - data->start.minute() * 60
654 + data->end.second() - data->start.second() );
655}
656QDate OEffectiveEvent::startDate()const {
657 if ( data->dates )
658 return data->startDate;
659 else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer
660 return data->date;
661 else
662 return data->event.startDateTime().date();
663}
664QDate OEffectiveEvent::endDate()const {
665 if ( data->dates )
666 return data->endDate;
667 else if ( data->event.hasRecurrence() )
668 return data->date;
669 else
670 return data->event.endDateTime().date();
671}
672void OEffectiveEvent::deref() {
673 if ( data->deref() ) {
674 delete data;
675 data = 0;
676 }
677}
678void OEffectiveEvent::changeOrModify() {
679 if ( data->count != 1 ) {
680 data->deref();
681 Data* d2 = new Data;
682 d2->event = data->event;
683 d2->date = data->date;
684 d2->start = data->start;
685 d2->end = data->end;
686 d2->startDate = data->startDate;
687 d2->endDate = data->endDate;
688 d2->dates = data->dates;
689 data = d2;
690 }
691}
692bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{
693 if ( data->date < e.date() )
694 return TRUE;
695 if ( data->date == e.date() )
696 return ( startTime() < e.startTime() );
697 else
698 return FALSE;
699}
700bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{
701 return (data->date <= e.date() );
702}
703bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const {
704 return ( date() == e.date()
705 && startTime() == e.startTime()
706 && endTime()== e.endTime()
707 && event() == e.event() );
708}
709bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const {
710 return !(*this == e );
711}
712bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const {
713 return !(*this <= e );
714}
715bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const {
716 return !(*this < e);
717}
diff --git a/noncore/unsupported/libopie/pim/oevent.h b/noncore/unsupported/libopie/pim/oevent.h
new file mode 100644
index 0000000..9eb948f
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/oevent.h
@@ -0,0 +1,236 @@
1// CONTAINS GPLed code of TT
2
3#ifndef OPIE_PIM_EVENT_H
4#define OPIE_PIM_EVENT_H
5
6#include <qstring.h>
7#include <qdatetime.h>
8#include <qvaluelist.h>
9
10#include <qpe/recordfields.h>
11#include <qpe/palmtopuidgen.h>
12
13#include "otimezone.h"
14#include "opimrecord.h"
15
16struct OCalendarHelper {
17 /** calculate the week number of the date */
18 static int week( const QDate& );
19 /** calculate the occurence of week days since the start of the month */
20 static int ocurrence( const QDate& );
21
22 // returns the dayOfWeek for the *first* day it finds (ignores
23 // any further days!). Returns 1 (Monday) if there isn't any day found
24 static int dayOfWeek( char day );
25
26 /** returns the diff of month */
27 static int monthDiff( const QDate& first, const QDate& second );
28
29};
30
31class OPimNotifyManager;
32class ORecur;
33
34/**
35 * This is the container for all Events. It encapsules all
36 * available information for a single Event
37 * @short container for events.
38 */
39class OEvent : public OPimRecord {
40public:
41 typedef QValueList<OEvent> ValueList;
42 /**
43 * RecordFields contain possible attributes
44 * used in the Results of toMap()..
45 */
46 enum RecordFields {
47 FUid = Qtopia::UID_ID,
48 FCategories = Qtopia::CATEGORY_ID,
49 FDescription = 0,
50 FLocation,
51 FType,
52 FAlarm,
53 FSound,
54 FRType,
55 FRWeekdays,
56 FRPosition,
57 FRFreq,
58 FRHasEndDate,
59 FREndDate,
60 FRCreated,
61 FRExceptions,
62 FStart,
63 FEnd,
64 FNote,
65 FTimeZone,
66 FRecParent,
67 FRecChildren,
68 };
69
70 /**
71 * Start with an Empty OEvent. UID == 0 means that it is empty
72 */
73 OEvent(int uid = 0);
74
75 /**
76 * copy c'tor
77 */
78 OEvent( const OEvent& );
79
80 /**
81 * Create OEvent, initialized by map
82 * @see enum RecordFields
83 */
84 OEvent( const QMap<int, QString> map );
85 ~OEvent();
86 OEvent &operator=( const OEvent& );
87
88 QString description()const;
89 void setDescription( const QString& description );
90
91 QString location()const;
92 void setLocation( const QString& loc );
93
94 bool hasNotifiers()const;
95 OPimNotifyManager &notifiers()const;
96
97 ORecur recurrence()const;
98 void setRecurrence( const ORecur& );
99 bool hasRecurrence()const;
100
101 QString note()const;
102 void setNote( const QString& note );
103
104
105 QDateTime createdDateTime()const;
106 void setCreatedDateTime( const QDateTime& dt);
107
108 /** set the date to dt. dt is the QDateTime in localtime */
109 void setStartDateTime( const QDateTime& );
110 /** returns the datetime in the local timeZone */
111 QDateTime startDateTime()const;
112
113 /** returns the start datetime in the current zone */
114 QDateTime startDateTimeInZone()const;
115
116 /** in current timezone */
117 void setEndDateTime( const QDateTime& );
118 /** in current timezone */
119 QDateTime endDateTime()const;
120 QDateTime endDateTimeInZone()const;
121
122 bool isMultipleDay()const;
123 bool isAllDay()const;
124 void setAllDay( bool isAllDay );
125
126 /* pin this event to a timezone! FIXME */
127 void setTimeZone( const QString& timeZone );
128 QString timeZone()const;
129
130
131 virtual bool match( const QRegExp& )const;
132
133 /** For exception to recurrence here is a list of children... */
134 QArray<int> children()const;
135 void setChildren( const QArray<int>& );
136 void addChild( int uid );
137 void removeChild( int uid );
138
139 /** return the parent OEvent */
140 int parent()const;
141 void setParent( int uid );
142
143
144 /* needed reimp */
145 QString toRichText()const;
146 QString toShortText()const;
147 QString type()const;
148
149 QMap<int, QString> toMap()const;
150 void fromMap( const QMap<int, QString>& map );
151 QString recordField(int )const;
152
153 static int rtti();
154
155 bool loadFromStream( QDataStream& );
156 bool saveToStream( QDataStream& )const;
157
158/* bool operator==( const OEvent& );
159 bool operator!=( const OEvent& );
160 bool operator<( const OEvent& );
161 bool operator<=( const OEvent& );
162 bool operator>( const OEvent& );
163 bool operator>=(const OEvent& );
164*/
165private:
166 inline void changeOrModify();
167 void deref();
168 struct Data;
169 Data* data;
170 class Private;
171 Private* priv;
172
173};
174
175/**
176 * AN Event can span through multiple days. We split up a multiday eve
177 */
178class OEffectiveEvent {
179public:
180 typedef QValueList<OEffectiveEvent> ValueList;
181 enum Position { MidWay, Start, End, StartEnd };
182 // If we calculate the effective event of a multi-day event
183 // we have to figure out whether we are at the first day,
184 // at the end, or anywhere else ("middle"). This is important
185 // for the start/end times (00:00/23:59)
186 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi-
187 // day event
188 // Start: start time -> 23:59
189 // End: 00:00 -> end time
190 // Start | End == StartEnd: for single-day events (default)
191 // here we draw start time -> end time
192 OEffectiveEvent();
193 OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd );
194 OEffectiveEvent( const OEffectiveEvent& );
195 OEffectiveEvent &operator=(const OEffectiveEvent& );
196 ~OEffectiveEvent();
197
198 void setStartTime( const QTime& );
199 void setEndTime( const QTime& );
200 void setEvent( const OEvent& );
201 void setDate( const QDate& );
202
203 void setEffectiveDates( const QDate& from, const QDate& to );
204
205 QString description()const;
206 QString location()const;
207 QString note()const;
208 OEvent event()const;
209 QTime startTime()const;
210 QTime endTime()const;
211 QDate date()const;
212
213 /* return the length in hours */
214 int length()const;
215 int size()const;
216
217 QDate startDate()const;
218 QDate endDate()const;
219
220 bool operator<( const OEffectiveEvent &e ) const;
221 bool operator<=( const OEffectiveEvent &e ) const;
222 bool operator==( const OEffectiveEvent &e ) const;
223 bool operator!=( const OEffectiveEvent &e ) const;
224 bool operator>( const OEffectiveEvent &e ) const;
225 bool operator>= ( const OEffectiveEvent &e ) const;
226
227private:
228 void deref();
229 inline void changeOrModify();
230 class Private;
231 Private* priv;
232 struct Data;
233 Data* data;
234
235};
236#endif
diff --git a/noncore/unsupported/libopie/pim/opimaccessbackend.h b/noncore/unsupported/libopie/pim/opimaccessbackend.h
new file mode 100644
index 0000000..fd264fc
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimaccessbackend.h
@@ -0,0 +1,160 @@
1#ifndef OPIE_PIM_ACCESS_BACKEND
2#define OPIE_PIM_ACCESS_BACKEND
3
4#include <qarray.h>
5#include <qdatetime.h>
6
7#include <opie/otemplatebase.h>
8#include <opie/opimrecord.h>
9
10
11class OPimAccessBackendPrivate;
12/**
13 * OPimAccessBackend is the base class
14 * for all private backends
15 * it operates on OPimRecord as the base class
16 * and it's responsible for fast manipulating
17 * the resource the implementation takes care
18 * of
19 */
20template <class T = OPimRecord>
21class OPimAccessBackend {
22public:
23 typedef OTemplateBase<T> Frontend;
24
25 /** The access hint from the frontend */
26 OPimAccessBackend(int access = 0);
27 virtual ~OPimAccessBackend();
28
29 /**
30 * load the resource
31 */
32 virtual bool load() = 0;
33
34 /**
35 * reload the resource
36 */
37 virtual bool reload() = 0;
38
39 /**
40 * save the resource and
41 * all it's changes
42 */
43 virtual bool save() = 0;
44
45 /**
46 * return an array of
47 * all available uids
48 */
49 virtual QArray<int> allRecords()const = 0;
50
51 /**
52 * return a List of records
53 * that match the regex
54 */
55 virtual QArray<int> matchRegexp(const QRegExp &r) const = 0;
56
57 /**
58 * queryByExample for T with the given Settings
59 *
60 */
61 virtual QArray<int> queryByExample( const T& t, int settings, const QDateTime& d = QDateTime() ) = 0;
62
63 /**
64 * find the OPimRecord with uid @param uid
65 * returns T and T.isEmpty() if nothing was found
66 */
67 virtual T find(int uid )const = 0;
68
69 virtual T find(int uid, const QArray<int>& items,
70 uint current, typename Frontend::CacheDirection )const ;
71 /**
72 * clear the back end
73 */
74 virtual void clear() = 0;
75
76 /**
77 * add T
78 */
79 virtual bool add( const T& t ) = 0;
80
81 /**
82 * remove
83 */
84 virtual bool remove( int uid ) = 0;
85
86 /**
87 * replace a record with T.uid()
88 */
89 virtual bool replace( const T& t ) = 0;
90
91 /*
92 * setTheFrontEnd!!!
93 */
94 void setFrontend( Frontend* front );
95
96 /**
97 * set the read ahead count
98 */
99 void setReadAhead( uint count );
100protected:
101 int access()const;
102 void cache( const T& t )const;
103
104 /**
105 * use a prime number here!
106 */
107 void setSaneCacheSize( int );
108
109 uint readAhead()const;
110
111private:
112 OPimAccessBackendPrivate *d;
113 Frontend* m_front;
114 uint m_read;
115 int m_acc;
116
117};
118
119template <class T>
120OPimAccessBackend<T>::OPimAccessBackend(int acc)
121 : m_acc( acc )
122{
123 m_front = 0l;
124}
125template <class T>
126OPimAccessBackend<T>::~OPimAccessBackend() {
127
128}
129template <class T>
130void OPimAccessBackend<T>::setFrontend( Frontend* fr ) {
131 m_front = fr;
132}
133template <class T>
134void OPimAccessBackend<T>::cache( const T& t )const {
135 if (m_front )
136 m_front->cache( t );
137}
138template <class T>
139void OPimAccessBackend<T>::setSaneCacheSize( int size) {
140 if (m_front )
141 m_front->setSaneCacheSize( size );
142}
143template <class T>
144T OPimAccessBackend<T>::find( int uid, const QArray<int>&,
145 uint, typename Frontend::CacheDirection )const {
146 return find( uid );
147}
148template <class T>
149void OPimAccessBackend<T>::setReadAhead( uint count ) {
150 m_read = count;
151}
152template <class T>
153uint OPimAccessBackend<T>::readAhead()const {
154 return m_read;
155}
156template <class T>
157int OPimAccessBackend<T>::access()const {
158 return m_acc;
159}
160#endif
diff --git a/noncore/unsupported/libopie/pim/opimaccesstemplate.h b/noncore/unsupported/libopie/pim/opimaccesstemplate.h
new file mode 100644
index 0000000..ecbeb68
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimaccesstemplate.h
@@ -0,0 +1,302 @@
1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H
2#define OPIE_PIM_ACCESS_TEMPLATE_H
3
4#include <qarray.h>
5
6#include <opie/opimrecord.h>
7#include <opie/opimaccessbackend.h>
8#include <opie/orecordlist.h>
9
10#include "opimcache.h"
11#include "otemplatebase.h"
12
13class OPimAccessTemplatePrivate;
14/**
15 * Thats the frontend to our OPIE PIM
16 * Library. Either you want to use it's
17 * interface or you want to implement
18 * your own Access lib
19 * Just create a OPimRecord and inherit from
20 * the plugins
21 */
22
23template <class T = OPimRecord >
24class OPimAccessTemplate : public OTemplateBase<T> {
25public:
26 enum Access {
27 Random = 0,
28 SortedAccess
29 };
30 typedef ORecordList<T> List;
31 typedef OPimAccessBackend<T> BackEnd;
32 typedef OPimCache<T> Cache;
33
34 /**
35 * c'tor BackEnd
36 * enum Access a small hint on how to handle the backend
37 */
38 OPimAccessTemplate( BackEnd* end);
39
40 virtual ~OPimAccessTemplate();
41
42 /**
43 * load from the backend
44 */
45 bool load();
46
47 /** Reload database.
48 * You should execute this function if the external database
49 * was changed.
50 * This function will load the external database and afterwards
51 * rejoin the local changes. Therefore the local database will be set consistent.
52 */
53 virtual bool reload();
54
55 /** Save contacts database.
56 * Save is more a "commit". After calling this function, all changes are public available.
57 * @return true if successful
58 */
59 bool save();
60
61 /**
62 * if the resource was changed externally
63 * You should use the signal handling instead of polling possible changes !
64 * zecke: Do you implement a signal for otodoaccess ?
65 */
66 bool wasChangedExternally()const;
67
68 /**
69 * return a List of records
70 * you can iterate over them
71 */
72 virtual List allRecords()const;
73
74 /**
75 * return a List of records
76 * that match the regex
77 */
78 virtual List matchRegexp( const QRegExp &r ) const;
79
80 /**
81 * queryByExample.
82 * @see otodoaccess, ocontactaccess
83 */
84 virtual List queryByExample( const T& t, int querySettings, const QDateTime& d = QDateTime() );
85
86 /**
87 * find the OPimRecord uid
88 */
89 virtual T find( int uid )const;
90
91 /**
92 * read ahead cache find method ;)
93 */
94 virtual T find( int uid, const QArray<int>&,
95 uint current, typename OTemplateBase<T>::CacheDirection dir = OTemplateBase<T>::Forward )const;
96
97 /* invalidate cache here */
98 /**
99 * clears the backend and invalidates the backend
100 */
101 void clear() ;
102
103 /**
104 * add T to the backend
105 * @param t The item to add.
106 * @return <i>true</i> if added successfully.
107 */
108 virtual bool add( const T& t ) ;
109 bool add( const OPimRecord& );
110
111 /* only the uid matters */
112 /**
113 * remove T from the backend
114 * @param t The item to remove
115 * @return <i>true</i> if successful.
116 */
117 virtual bool remove( const T& t );
118
119 /**
120 * remove the OPimRecord with uid
121 * @param uid The ID of the item to remove
122 * @return <i>true</i> if successful.
123 */
124 bool remove( int uid );
125 bool remove( const OPimRecord& );
126
127 /**
128 * replace T from backend
129 * @param t The item to replace
130 * @return <i>true</i> if successful.
131 */
132 virtual bool replace( const T& t) ;
133
134 void setReadAhead( uint count );
135 /**
136 * @internal
137 */
138 void cache( const T& )const;
139 void setSaneCacheSize( int );
140
141 QArray<int> records()const;
142protected:
143 /**
144 * invalidate the cache
145 */
146 void invalidateCache();
147
148 void setBackEnd( BackEnd* end );
149 /**
150 * returns the backend
151 */
152 BackEnd* backEnd();
153 BackEnd* m_backEnd;
154 Cache m_cache;
155
156private:
157 OPimAccessTemplatePrivate *d;
158
159};
160
161template <class T>
162OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end )
163 : OTemplateBase<T>(), m_backEnd( end )
164{
165 if (end )
166 end->setFrontend( this );
167}
168template <class T>
169OPimAccessTemplate<T>::~OPimAccessTemplate() {
170 qWarning("~OPimAccessTemplate<T>");
171 delete m_backEnd;
172}
173template <class T>
174bool OPimAccessTemplate<T>::load() {
175 invalidateCache();
176 return m_backEnd->load();
177}
178template <class T>
179bool OPimAccessTemplate<T>::reload() {
180 invalidateCache(); // zecke: I think this should be added (se)
181 return m_backEnd->reload();
182}
183template <class T>
184bool OPimAccessTemplate<T>::save() {
185 return m_backEnd->save();
186}
187template <class T>
188typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
189 QArray<int> ints = m_backEnd->allRecords();
190 List lis(ints, this );
191 return lis;
192}
193template <class T>
194typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::matchRegexp( const QRegExp &r )const {
195 QArray<int> ints = m_backEnd->matchRegexp( r );
196 List lis(ints, this );
197 return lis;
198}
199template <class T>
200QArray<int> OPimAccessTemplate<T>::records()const {
201 return m_backEnd->allRecords();
202}
203template <class T>
204typename OPimAccessTemplate<T>::List
205OPimAccessTemplate<T>::queryByExample( const T& t, int settings, const QDateTime& d ) {
206 QArray<int> ints = m_backEnd->queryByExample( t, settings, d );
207
208 List lis(ints, this );
209 return lis;
210}
211template <class T>
212T OPimAccessTemplate<T>::find( int uid ) const{
213 T t = m_backEnd->find( uid );
214 cache( t );
215 return t;
216}
217template <class T>
218T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar,
219 uint current, typename OTemplateBase<T>::CacheDirection dir )const {
220 /*
221 * better do T.isEmpty()
222 * after a find this way we would
223 * avoid two finds in QCache...
224 */
225 // qWarning("find it now %d", uid );
226 if (m_cache.contains( uid ) ) {
227 return m_cache.find( uid );
228 }
229
230 T t = m_backEnd->find( uid, ar, current, dir );
231 cache( t );
232 return t;
233}
234template <class T>
235void OPimAccessTemplate<T>::clear() {
236 invalidateCache();
237 m_backEnd->clear();
238}
239template <class T>
240bool OPimAccessTemplate<T>::add( const T& t ) {
241 cache( t );
242 return m_backEnd->add( t );
243}
244template <class T>
245bool OPimAccessTemplate<T>::add( const OPimRecord& rec) {
246 /* same type */
247 if ( rec.rtti() == T::rtti() ) {
248 const T &t = static_cast<const T&>(rec);
249 return add(t);
250 }
251 return false;
252}
253template <class T>
254bool OPimAccessTemplate<T>::remove( const T& t ) {
255 return remove( t.uid() );
256}
257template <class T>
258bool OPimAccessTemplate<T>::remove( int uid ) {
259 m_cache.remove( uid );
260 return m_backEnd->remove( uid );
261}
262template <class T>
263bool OPimAccessTemplate<T>::remove( const OPimRecord& rec) {
264 return remove( rec.uid() );
265}
266template <class T>
267bool OPimAccessTemplate<T>::replace( const T& t ) {
268 m_cache.replace( t );
269 return m_backEnd->replace( t );
270}
271template <class T>
272void OPimAccessTemplate<T>::invalidateCache() {
273 m_cache.invalidate();
274}
275template <class T>
276typename OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() {
277 return m_backEnd;
278}
279template <class T>
280bool OPimAccessTemplate<T>::wasChangedExternally()const {
281 return false;
282}
283template <class T>
284void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) {
285 m_backEnd = end;
286 if (m_backEnd )
287 m_backEnd->setFrontend( this );
288}
289template <class T>
290void OPimAccessTemplate<T>::cache( const T& t ) const{
291 /* hacky we need to work around the const*/
292 ((OPimAccessTemplate<T>*)this)->m_cache.add( t );
293}
294template <class T>
295void OPimAccessTemplate<T>::setSaneCacheSize( int size ) {
296 m_cache.setSize( size );
297}
298template <class T>
299void OPimAccessTemplate<T>::setReadAhead( uint count ) {
300 m_backEnd->setReadAhead( count );
301}
302#endif
diff --git a/noncore/unsupported/libopie/pim/opimcache.h b/noncore/unsupported/libopie/pim/opimcache.h
new file mode 100644
index 0000000..7f7cff5
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimcache.h
@@ -0,0 +1,131 @@
1#ifndef OPIE_PIM_CACHE_H
2#define OPIE_PIM_CACHE_H
3
4#include <qintcache.h>
5
6#include "opimrecord.h"
7
8class OPimCacheItemPrivate;
9
10template <class T = OPimRecord>
11class OPimCacheItem {
12public:
13 OPimCacheItem( const T& t = T() );
14 OPimCacheItem( const OPimCacheItem& );
15 ~OPimCacheItem();
16
17 OPimCacheItem &operator=( const OPimCacheItem& );
18
19 T record()const;
20 void setRecord( const T& );
21private:
22 T m_t;
23 OPimCacheItemPrivate *d;
24};
25
26
27class OPimCachePrivate;
28/**
29 * OPimCache for caching the items
30 * We support adding, removing
31 * and finding
32 */
33template <class T = OPimRecord>
34class OPimCache {
35public:
36 typedef OPimCacheItem<T> Item;
37 OPimCache();
38 OPimCache( const OPimCache& );
39 ~OPimCache();
40
41 OPimCache &operator=( const OPimCache& );
42
43 bool contains(int uid)const;
44 void invalidate();
45 void setSize( int size );
46
47 T find(int uid )const;
48 void add( const T& );
49 void remove( int uid );
50 void replace( const T& );
51
52private:
53 QIntCache<Item> m_cache;
54 OPimCachePrivate* d;
55};
56
57// Implementation
58template <class T>
59OPimCacheItem<T>::OPimCacheItem( const T& t )
60 : m_t(t) {
61}
62template <class T>
63OPimCacheItem<T>::~OPimCacheItem() {
64
65}
66template <class T>
67T OPimCacheItem<T>::record()const {
68 return m_t;
69}
70template <class T>
71void OPimCacheItem<T>::setRecord( const T& t ) {
72 m_t = t;
73}
74// Cache
75template <class T>
76OPimCache<T>::OPimCache()
77 : m_cache(100, 53 )
78{
79 m_cache.setAutoDelete( TRUE );
80}
81template <class T>
82OPimCache<T>::~OPimCache() {
83
84}
85template <class T>
86bool OPimCache<T>::contains(int uid )const {
87 Item* it = m_cache.find( uid, FALSE );
88 if (!it)
89 return false;
90 return true;
91}
92template <class T>
93void OPimCache<T>::invalidate() {
94 m_cache.clear();
95}
96template <class T>
97void OPimCache<T>::setSize( int size ) {
98 m_cache.setMaxCost( size );
99}
100template <class T>
101T OPimCache<T>::find(int uid )const {
102 Item *it = m_cache.find( uid );
103 if (it)
104 return it->record();
105 return T();
106}
107template <class T>
108void OPimCache<T>::add( const T& t ) {
109 Item* it = 0l;
110 it = m_cache.find(t.uid(), FALSE );
111
112 if (it )
113 it->setRecord( t );
114
115 it = new Item( t );
116 if (!m_cache.insert( t.uid(), it ) )
117 delete it;
118}
119template <class T>
120void OPimCache<T>::remove( int uid ) {
121 m_cache.remove( uid );
122}
123template <class T>
124void OPimCache<T>::replace( const T& t) {
125 Item *it = m_cache.find( t.uid() );
126 if ( it ) {
127 it->setRecord( t );
128 }
129}
130
131#endif
diff --git a/noncore/unsupported/libopie/pim/opimmaintainer.cpp b/noncore/unsupported/libopie/pim/opimmaintainer.cpp
new file mode 100644
index 0000000..92cb25a
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimmaintainer.cpp
@@ -0,0 +1,37 @@
1#include "opimmaintainer.h"
2
3OPimMaintainer::OPimMaintainer( int mode, int uid )
4 : m_mode(mode), m_uid(uid )
5{}
6OPimMaintainer::~OPimMaintainer() {
7}
8OPimMaintainer::OPimMaintainer( const OPimMaintainer& main ) {
9 *this = main;
10}
11OPimMaintainer &OPimMaintainer::operator=( const OPimMaintainer& main ) {
12 m_mode = main.m_mode;
13 m_uid = main.m_uid;
14
15 return *this;
16}
17bool OPimMaintainer::operator==( const OPimMaintainer& main ) {
18 if (m_mode != main.m_mode ) return false;
19 if (m_uid != main.m_uid ) return false;
20
21 return true;
22}
23bool OPimMaintainer::operator!=( const OPimMaintainer& main ) {
24 return !(*this == main );
25}
26int OPimMaintainer::mode()const {
27 return m_mode;
28}
29int OPimMaintainer::uid()const {
30 return m_uid;
31}
32void OPimMaintainer::setMode( int mo) {
33 m_mode = mo;
34}
35void OPimMaintainer::setUid( int uid ) {
36 m_uid = uid;
37}
diff --git a/noncore/unsupported/libopie/pim/opimmaintainer.h b/noncore/unsupported/libopie/pim/opimmaintainer.h
new file mode 100644
index 0000000..793d066
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimmaintainer.h
@@ -0,0 +1,40 @@
1#ifndef OPIE_PIM_MAINTAINER_H
2#define OPIE_PIM_MAINTAINER_H
3
4#include <qstring.h>
5
6/**
7 * Who maintains what?
8 */
9class OPimMaintainer {
10public:
11 enum Mode { Undefined = -1,
12 Nothing = 0,
13 Responsible,
14 DoneBy,
15 Coordinating,
16 };
17 OPimMaintainer( int mode = Undefined, int uid = 0);
18 OPimMaintainer( const OPimMaintainer& );
19 ~OPimMaintainer();
20
21 OPimMaintainer &operator=( const OPimMaintainer& );
22 bool operator==( const OPimMaintainer& );
23 bool operator!=( const OPimMaintainer& );
24
25
26 int mode()const;
27 int uid()const;
28
29 void setMode( int mode );
30 void setUid( int uid );
31
32private:
33 int m_mode;
34 int m_uid;
35 class Private;
36 Private *d;
37
38};
39
40#endif
diff --git a/noncore/unsupported/libopie/pim/opimmainwindow.cpp b/noncore/unsupported/libopie/pim/opimmainwindow.cpp
new file mode 100644
index 0000000..99a0333
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimmainwindow.cpp
@@ -0,0 +1,150 @@
1#include <qapplication.h>
2#include <qdatetime.h>
3#include <qcopchannel_qws.h>
4
5#include <qpe/sound.h>
6#include <qpe/qcopenvelope_qws.h>
7#include <qpe/qpeapplication.h>
8
9#include "opimresolver.h"
10#include "opimmainwindow.h"
11
12OPimMainWindow::OPimMainWindow( const QString& service, QWidget* parent,
13 const char* name, WFlags flag )
14 : QMainWindow( parent, name, flag ), m_rtti(-1), m_service( service ), m_fallBack(0l) {
15
16 /*
17 * let's generate our QCopChannel
18 */
19 m_str = QString("QPE/"+m_service).local8Bit();
20 m_channel= new QCopChannel(m_str, this );
21 connect(m_channel, SIGNAL(received(const QCString&,const QByteArray&) ),
22 this, SLOT( appMessage(const QCString&,const QByteArray&) ) );
23 connect(qApp, SIGNAL(appMessage(const QCString&,const QByteArray&) ),
24 this, SLOT( appMessage(const QCString&,const QByteArray&) ) );
25
26 /* connect flush and reload */
27 connect(qApp, SIGNAL(flush() ),
28 this, SLOT(flush() ) );
29 connect(qApp, SIGNAL(reload() ),
30 this, SLOT(reload() ) );
31}
32OPimMainWindow::~OPimMainWindow() {
33 delete m_channel;
34}
35QCopChannel* OPimMainWindow::channel() {
36 return m_channel;
37}
38void OPimMainWindow::doSetDocument( const QString& ) {
39
40}
41void OPimMainWindow::appMessage( const QCString& cmd, const QByteArray& array ) {
42 bool needShow = false;
43 /*
44 * create demands to create
45 * a new record...
46 */
47 QDataStream stream(array, IO_ReadOnly);
48 if ( cmd == "create()" ) {
49 raise();
50 int uid = create();
51 QCopEnvelope e(m_str, "created(int)" );
52 e << uid;
53 needShow = true;
54 }else if ( cmd == "remove(int)" ) {
55 int uid;
56 stream >> uid;
57 bool rem = remove( uid );
58 QCopEnvelope e(m_str, "removed(bool)" );
59 e << rem;
60 needShow = true;
61 }else if ( cmd == "beam(int)" ) {
62 int uid;
63 stream >> uid;
64 beam( uid);
65 }else if ( cmd == "show(int)" ) {
66 raise();
67 int uid;
68 stream >> uid;
69 show( uid );
70 needShow = true;
71 }else if ( cmd == "edit(int)" ) {
72 raise();
73 int uid;
74 stream >> uid;
75 edit( uid );
76 }else if ( cmd == "add(int,QByteArray)" ) {
77 int rtti;
78 QByteArray array;
79 stream >> rtti;
80 stream >> array;
81 m_fallBack = record(rtti, array );
82 if (!m_fallBack) return;
83 add( *m_fallBack );
84 delete m_fallBack;
85 }else if ( cmd == "alarm(QDateTime,int)" ) {
86 raise();
87 QDateTime dt; int uid;
88 stream >> dt;
89 stream >> uid;
90 qWarning(" Date: %s Uid: %d", dt.toString().latin1(), uid );
91 QDateTime current = QDateTime::currentDateTime();
92 if ( current.time().hour() != dt.time().hour() && current.time().minute() != dt.time().minute() )
93 return;
94 doAlarm( dt, uid );
95 needShow = true;
96 }
97
98 if (needShow )
99 QPEApplication::setKeepRunning();
100}
101/* implement the url scripting here */
102void OPimMainWindow::setDocument( const QString& str) {
103 doSetDocument( str );
104}
105/*
106 * we now try to get the array demarshalled
107 * check if the rtti matches this one
108 */
109OPimRecord* OPimMainWindow::record( int rtti, const QByteArray& array ) {
110 if ( service() != rtti )
111 return 0l;
112
113 OPimRecord* record = OPimResolver::self()->record( rtti );
114 QDataStream str(array, IO_ReadOnly );
115 if ( !record || !record->loadFromStream(str) ) {
116 delete record;
117 record = 0l;
118 }
119
120 return record;
121}
122/*
123 * get the rtti for the service
124 */
125int OPimMainWindow::service() {
126 if ( m_rtti == -1 )
127 m_rtti = OPimResolver::self()->serviceId( m_service );
128
129 return m_rtti;
130}
131void OPimMainWindow::doAlarm( const QDateTime&, int ) {
132
133}
134void OPimMainWindow::startAlarm(int count ) {
135 m_alarmCount = count;
136 m_playedCount = 0;
137 Sound::soundAlarm();
138 m_timerId = startTimer( 5000 );
139}
140void OPimMainWindow::killAlarm() {
141 killTimer( m_timerId );
142}
143void OPimMainWindow::timerEvent( QTimerEvent* e) {
144 if ( m_playedCount <m_alarmCount ) {
145 m_playedCount++;
146 Sound::soundAlarm();
147 }else {
148 killTimer( e->timerId() );
149 }
150}
diff --git a/noncore/unsupported/libopie/pim/opimmainwindow.h b/noncore/unsupported/libopie/pim/opimmainwindow.h
new file mode 100644
index 0000000..855d364
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimmainwindow.h
@@ -0,0 +1,99 @@
1#ifndef OPIE_PIM_MAINWINDOW_H
2#define OPIE_PIM_MAINWINDOW_H
3
4#include <qmainwindow.h>
5
6#include <opie/opimrecord.h>
7
8/**
9 * This is a common Opie PIM MainWindow
10 * it takes care of the QCOP internals
11 * and implements some functions
12 * for the URL scripting schema
13 */
14/*
15 * due Qt and Templates with signal and slots
16 * do not work that good :(
17 * (Ok how to moc a template ;) )
18 * We will have the mainwindow which calls a struct which
19 * is normally reimplemented as a template ;)
20 */
21
22class QCopChannel;
23class QDateTime;
24class OPimMainWindow : public QMainWindow {
25 Q_OBJECT
26public:
27 enum TransPort { BlueTooth=0,
28 IrDa };
29
30 OPimMainWindow( const QString& service, QWidget *parent = 0, const char* name = 0,
31 WFlags f = WType_TopLevel);
32 virtual ~OPimMainWindow();
33
34
35protected slots:
36 /*
37 * called when a setDocument
38 * couldn't be handled by this window
39 */
40 virtual void doSetDocument( const QString& );
41 /* for syncing */
42 virtual void flush() = 0;
43 virtual void reload() = 0;
44
45 /** create a new Records and return the uid */
46 virtual int create() = 0;
47 /** remove a record with UID == uid */
48 virtual bool remove( int uid ) = 0;
49 /** beam the record with UID = uid */
50 virtual void beam( int uid ) = 0;
51
52 /** show the record with UID == uid */
53 virtual void show( int uid ) = 0;
54 /** edit the record */
55 virtual void edit( int uid ) = 0;
56
57 /** make a copy of it! */
58 virtual void add( const OPimRecord& ) = 0;
59
60 virtual void doAlarm( const QDateTime&, int uid );
61
62 QCopChannel* channel();
63
64protected:
65 /**
66 * start to play soundAlarm()
67 * @param count How many times the alarm is played
68 */
69 void startAlarm(int count = 10);
70 void killAlarm();
71 void timerEvent( QTimerEvent* );
72
73private slots:
74 void appMessage( const QCString&, const QByteArray& );
75 void setDocument( const QString& );
76
77
78private:
79 class Private;
80 Private* d;
81
82 int m_rtti;
83 QCopChannel* m_channel;
84 QString m_service;
85 QCString m_str;
86 OPimRecord* m_fallBack;
87 int m_alarmCount;
88 int m_playedCount;
89 int m_timerId;
90 /* I would love to do this as a template
91 * but can't think of a right way
92 * because I need signal and slots -zecke
93 */
94 virtual OPimRecord* record( int rtti, const QByteArray& ) ;
95 int service();
96};
97
98
99#endif
diff --git a/noncore/unsupported/libopie/pim/opimnotify.cpp b/noncore/unsupported/libopie/pim/opimnotify.cpp
new file mode 100644
index 0000000..af5514b
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimnotify.cpp
@@ -0,0 +1,227 @@
1#include <qshared.h>
2
3#include "opimnotify.h"
4
5struct OPimNotify::Data : public QShared {
6 Data() : QShared(),dur(-1),parent(0) {
7
8 }
9 QDateTime start;
10 int dur;
11 QString application;
12 int parent;
13};
14
15OPimNotify::OPimNotify( const QDateTime& start, int duration, int parent ) {
16 data = new Data;
17 data->start = start;
18 data->dur = duration;
19 data->parent = parent;
20}
21OPimNotify::OPimNotify( const OPimNotify& noti)
22 : data( noti.data )
23{
24 data->ref();
25}
26OPimNotify::~OPimNotify() {
27 if ( data->deref() ) {
28 delete data;
29 data = 0l;
30 }
31}
32
33OPimNotify &OPimNotify::operator=( const OPimNotify& noti) {
34 noti.data->ref();
35 deref();
36 data = noti.data;
37
38 return *this;
39}
40bool OPimNotify::operator==( const OPimNotify& noti ) {
41 if ( data == noti.data ) return true;
42 if ( data->dur != noti.data->dur ) return false;
43 if ( data->parent != noti.data->parent ) return false;
44 if ( data->application != noti.data->application ) return false;
45 if ( data->start != noti.data->start ) return false;
46
47 return true;
48}
49QDateTime OPimNotify::dateTime()const {
50 return data->start;
51}
52QString OPimNotify::service()const {
53 return data->application;
54}
55int OPimNotify::parent()const {
56 return data->parent;
57}
58int OPimNotify::duration()const {
59 return data->dur;
60}
61QDateTime OPimNotify::endTime()const {
62 return QDateTime( data->start.date(), data->start.time().addSecs( data->dur) );
63}
64void OPimNotify::setDateTime( const QDateTime& time ) {
65 copyIntern();
66 data->start = time;
67}
68void OPimNotify::setDuration( int dur ) {
69 copyIntern();
70 data->dur = dur;
71}
72void OPimNotify::setParent( int uid ) {
73 copyIntern();
74 data->parent = uid;
75}
76void OPimNotify::setService( const QString& str ) {
77 copyIntern();
78 data->application = str;
79}
80void OPimNotify::copyIntern() {
81 if ( data->count != 1 ) {
82 data->deref();
83 Data* dat = new Data;
84 dat->start = data->start;
85 dat->dur = data->dur;
86 dat->application = data->application;
87 dat->parent = data->parent;
88 data = dat;
89 }
90}
91void OPimNotify::deref() {
92 if ( data->deref() ) {
93 delete data;
94 data = 0;
95 }
96}
97
98/***********************************************************/
99struct OPimAlarm::Data : public QShared {
100 Data() : QShared() {
101 sound = 1;
102 }
103 int sound;
104 QString file;
105};
106OPimAlarm::OPimAlarm( int sound, const QDateTime& start, int duration, int parent )
107 : OPimNotify( start, duration, parent )
108{
109 data = new Data;
110 data->sound = sound;
111}
112OPimAlarm::OPimAlarm( const OPimAlarm& al)
113 : OPimNotify(al), data( al.data )
114{
115 data->ref();
116}
117OPimAlarm::~OPimAlarm() {
118 if ( data->deref() ) {
119 delete data;
120 data = 0l;
121 }
122}
123OPimAlarm &OPimAlarm::operator=( const OPimAlarm& al)
124{
125 OPimNotify::operator=( al );
126 deref();
127 al.data->ref();
128
129 data = al.data;
130
131
132 return *this;
133}
134bool OPimAlarm::operator==( const OPimAlarm& al) {
135 if ( data->sound != al.data->sound ) return false;
136 else if ( data->sound == Custom && data->file != al.data->file )
137 return false;
138
139 return OPimNotify::operator==( al );
140}
141QString OPimAlarm::type()const {
142 return QString::fromLatin1("OPimAlarm");
143}
144int OPimAlarm::sound()const {
145 return data->sound;
146}
147QString OPimAlarm::file()const {
148 return data->file;
149}
150void OPimAlarm::setSound( int snd) {
151 copyIntern();
152 data->sound = snd;
153}
154void OPimAlarm::setFile( const QString& sound ) {
155 copyIntern();
156 data->file = sound;
157}
158void OPimAlarm::deref() {
159 if ( data->deref() ) {
160 delete data;
161 data = 0l;
162 }
163}
164void OPimAlarm::copyIntern() {
165 if ( data->count != 1 ) {
166 data->deref();
167 Data *newDat = new Data;
168 newDat->sound = data->sound;
169 newDat->file = data->file;
170 data = newDat;
171 }
172}
173/************************/
174struct OPimReminder::Data : public QShared {
175 Data() : QShared(), record( 0) {
176 }
177 int record;
178
179};
180OPimReminder::OPimReminder( int uid, const QDateTime& start, int dur, int parent )
181 : OPimNotify( start, dur, parent )
182{
183 data = new Data;
184 data->record = uid;
185}
186OPimReminder::OPimReminder( const OPimReminder& rem )
187 : OPimNotify( rem ), data( rem.data )
188{
189 data->ref();
190}
191OPimReminder& OPimReminder::operator=( const OPimReminder& rem) {
192 OPimNotify::operator=(rem );
193
194 deref();
195 rem.data->ref();
196 data = rem.data;
197
198 return *this;
199}
200bool OPimReminder::operator==( const OPimReminder& rem) {
201 if ( data->record != rem.data->record ) return false;
202
203 return OPimNotify::operator==( rem );
204}
205QString OPimReminder::type()const {
206 return QString::fromLatin1("OPimReminder");
207}
208int OPimReminder::recordUid()const {
209 return data->record;
210}
211void OPimReminder::setRecordUid( int uid ) {
212 copyIntern();
213 data->record = uid;
214}
215void OPimReminder::deref() {
216 if ( data->deref() ) {
217 delete data;
218 data = 0l;
219 }
220}
221void OPimReminder::copyIntern() {
222 if ( data->count != 1 ) {
223 Data* da = new Data;
224 da->record = data->record;
225 data = da;
226 }
227}
diff --git a/noncore/unsupported/libopie/pim/opimnotify.h b/noncore/unsupported/libopie/pim/opimnotify.h
new file mode 100644
index 0000000..58417db
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimnotify.h
@@ -0,0 +1,144 @@
1#ifndef OPIE_PIM_NOTIFY_H
2#define OPIE_PIM_NOTIFY_H
3
4#include <qdatetime.h>
5#include <qvaluelist.h>
6
7/**
8 * This is the base class of Notifiers. Possible
9 * notifiers would be Alarms, Reminders
10 * What they share is that they have
11 * A DateTime, Type, Duration
12 * This is what this base class takes care of
13 * on top of that it's shared
14 */
15/*
16 * TALK to eilers: have a class OPimDuration which sets the Duration
17 * given on the Due/Start Date? -zecke
18 * discuss: do we need a uid for the notify? -zecke
19 */
20class OPimNotify {
21public:
22 typedef QValueList<OPimNotify> ValueList;
23 OPimNotify( const QDateTime& start = QDateTime(), int duration = 0, int parent = 0 );
24 OPimNotify( const OPimNotify& );
25 virtual ~OPimNotify();
26
27 OPimNotify &operator=(const OPimNotify& );
28 bool operator==( const OPimNotify& );
29
30 virtual QString type()const = 0;
31
32 /** start date */
33 QDateTime dateTime()const;
34 QString service()const;
35
36 /**
37 * RETURN the parent uid
38 */
39 int parent()const;
40
41 /**
42 * in Seconds
43 */
44 int duration()const;
45
46 /**
47 * Start Time + Duration
48 */
49 QDateTime endTime()const;
50
51 void setDateTime( const QDateTime& );
52 void setDuration( int dur );
53 void setParent(int uid );
54 void setService( const QString& );
55
56
57private:
58 inline void copyIntern();
59 void deref();
60 struct Data;
61 Data* data;
62
63 /* d-pointer */
64 class NotifyPrivate;
65 NotifyPrivate* d;
66
67};
68/**
69 * An alarm is a sound/mail/buzzer played/send
70 * at a given time to inform about
71 * an Event
72 */
73class OPimAlarm : public OPimNotify {
74public:
75 enum Sound{Loud=1, Silent=0, Custom=2 };
76 OPimAlarm( int sound = Silent, const QDateTime& start = QDateTime(), int duration = 0, int parent = 0 );
77 OPimAlarm( const OPimAlarm& );
78 ~OPimAlarm();
79
80 OPimAlarm &operator=( const OPimAlarm& );
81 bool operator==( const OPimAlarm& );
82 QString type()const;
83
84 int sound()const;
85 QString file()const;
86
87 void setSound( int );
88 /* only when sound is custom... */
89 void setFile( const QString& sound );
90
91private:
92 void deref();
93 void copyIntern();
94 struct Data;
95 Data * data;
96
97 class Private;
98 Private* d;
99
100};
101
102/**
103 * A Reminder will be put into the
104 * datebook
105 * Note that the returned dateTime() may be not valid.
106 * In these cases one must resolve the uid and get the OEvent
107 */
108class OPimReminder : public OPimNotify {
109public:
110
111 /**
112 * c'tor of a reminder
113 * @param uid The uid of the Record inside the Datebook
114 * @param start the StartDate invalid for all day...
115 * @param duration The duration of the event ( -1 for all day )
116 * @param parent The 'parent' record of this reminder
117 */
118 OPimReminder( int uid = 0, const QDateTime& start = QDateTime(),
119 int duration = 0, int parent = 0 );
120 OPimReminder( const OPimReminder& );
121 OPimReminder &operator=(const OPimReminder& );
122
123 QString type()const;
124
125 bool operator==( const OPimReminder& );
126
127 /**
128 * the uid of the alarm
129 * inside the 'datebook' application
130 */
131 int recordUid()const;
132 void setRecordUid( int uid );
133
134private:
135 void deref();
136 void copyIntern();
137
138 struct Data;
139 Data* data;
140 class Private;
141 Private *d;
142};
143
144#endif
diff --git a/noncore/unsupported/libopie/pim/opimnotifymanager.cpp b/noncore/unsupported/libopie/pim/opimnotifymanager.cpp
new file mode 100644
index 0000000..d6f0ead
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimnotifymanager.cpp
@@ -0,0 +1,162 @@
1#include "opimnotifymanager.h"
2
3#include "oconversion.h"
4
5#include <qstringlist.h>
6
7OPimNotifyManager::OPimNotifyManager( const Reminders& rem, const Alarms& al)
8 : m_rem( rem ), m_al( al )
9{}
10OPimNotifyManager::~OPimNotifyManager() {
11}
12/* use static_cast and type instead of dynamic... */
13void OPimNotifyManager::add( const OPimNotify& noti) {
14 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
15 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
16 m_rem.append( rem );
17 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
18 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
19 m_al.append( al );
20 }
21}
22void OPimNotifyManager::remove( const OPimNotify& noti) {
23 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
24 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
25 m_rem.remove( rem );
26 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
27 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
28 m_al.remove( al );
29 }
30}
31void OPimNotifyManager::replace( const OPimNotify& noti) {
32 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
33 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
34 m_rem.remove( rem );
35 m_rem.append( rem );
36 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
37 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
38 m_al.remove( al );
39 m_al.append( al );
40 }
41}
42OPimNotifyManager::Reminders OPimNotifyManager::reminders()const {
43 return m_rem;
44}
45OPimNotifyManager::Alarms OPimNotifyManager::alarms()const {
46 return m_al;
47}
48OPimAlarm OPimNotifyManager::alarmAtDateTime( const QDateTime& when, bool& found ) const {
49 Alarms::ConstIterator it;
50 found = true;
51
52 for ( it = m_al.begin(); it != m_al.end(); ++it ){
53 if ( (*it).dateTime() == when )
54 return (*it);
55 }
56
57 // Fall through if nothing could be found
58 found = false;
59 OPimAlarm empty;
60 return empty;
61}
62
63
64void OPimNotifyManager::setAlarms( const Alarms& al) {
65 m_al = al;
66}
67void OPimNotifyManager::setReminders( const Reminders& rem) {
68 m_rem = rem;
69}
70/* FIXME!!! */
71/**
72 * The idea is to check if the provider for our service
73 * is online
74 * if it is we will use QCOP
75 * if not the Factory to get the backend...
76 * Qtopia1.6 services would be kewl to have here....
77 */
78void OPimNotifyManager::registerNotify( const OPimNotify& ) {
79
80}
81/* FIXME!!! */
82/**
83 * same as above...
84 * Also implement Url model
85 * have a MainWindow....
86 */
87void OPimNotifyManager::deregister( const OPimNotify& ) {
88
89}
90
91bool OPimNotifyManager::isEmpty()const {
92 qWarning("is Empty called on OPimNotifyManager %d %d", m_rem.count(), m_al.count() );
93 if ( m_rem.isEmpty() && m_al.isEmpty() ) return true;
94 else return false;
95}
96
97// Taken from otodoaccessxml..
98QString OPimNotifyManager::alarmsToString() const
99{
100 QString str;
101
102 OPimNotifyManager::Alarms alarms = m_al;
103 if ( !alarms.isEmpty() ) {
104 QStringList als;
105 OPimNotifyManager::Alarms::Iterator it = alarms.begin();
106 for ( ; it != alarms.end(); ++it ) {
107 /* only if time is valid */
108 if ( (*it).dateTime().isValid() ) {
109 als << OConversion::dateTimeToString( (*it).dateTime() )
110 + ":" + QString::number( (*it).duration() )
111 + ":" + QString::number( (*it).sound() )
112 + ":";
113 }
114 }
115 // now write the list
116 qWarning("als: %s", als.join("____________").latin1() );
117 str = als.join(";");
118 }
119
120 return str;
121}
122QString OPimNotifyManager::remindersToString() const
123{
124 QString str;
125
126 OPimNotifyManager::Reminders reminders = m_rem;
127 if (!reminders.isEmpty() ) {
128 OPimNotifyManager::Reminders::Iterator it = reminders.begin();
129 QStringList records;
130 for ( ; it != reminders.end(); ++it ) {
131 records << QString::number( (*it).recordUid() );
132 }
133 str = records.join(";");
134 }
135
136 return str;
137}
138
139void OPimNotifyManager::alarmsFromString( const QString& str )
140{
141 QStringList als = QStringList::split(";", str );
142 for (QStringList::Iterator it = als.begin(); it != als.end(); ++it ) {
143 QStringList alarm = QStringList::split(":", (*it), TRUE ); // allow empty
144 qWarning("alarm: %s", alarm.join("___").latin1() );
145 qWarning("alarm[0]: %s %s", alarm[0].latin1(),
146 OConversion::dateTimeFromString( alarm[0] ).toString().latin1() );
147 OPimAlarm al( alarm[2].toInt(), OConversion::dateTimeFromString( alarm[0] ),
148 alarm[1].toInt() );
149 add( al );
150 }
151}
152
153void OPimNotifyManager::remindersFromString( const QString& str )
154{
155
156 QStringList rems = QStringList::split(";", str );
157 for (QStringList::Iterator it = rems.begin(); it != rems.end(); ++it ) {
158 OPimReminder rem( (*it).toInt() );
159 add( rem );
160 }
161
162}
diff --git a/noncore/unsupported/libopie/pim/opimnotifymanager.h b/noncore/unsupported/libopie/pim/opimnotifymanager.h
new file mode 100644
index 0000000..f3c22f9
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimnotifymanager.h
@@ -0,0 +1,91 @@
1#ifndef OPIE_PIM_NOTIFY_MANAGER_H
2#define OPIE_PIM_NOTIFY_MANAGER_H
3
4#include <qvaluelist.h>
5
6#include <opie/opimnotify.h>
7
8/**
9 * The notify manager keeps track of the Notifiers....
10 */
11class OPimNotifyManager {
12public:
13 typedef QValueList<OPimReminder> Reminders;
14 typedef QValueList<OPimAlarm> Alarms;
15 OPimNotifyManager( const Reminders& rems = Reminders(), const Alarms& alarms = Alarms() );
16 ~OPimNotifyManager();
17
18 /* we will cast it for you ;) */
19 void add( const OPimNotify& );
20 void remove( const OPimNotify& );
21 /* replaces all with this one! */
22 void replace( const OPimNotify& );
23
24 Reminders reminders()const;
25
26 /**
27 * Return
28 */
29 Alarms alarms()const;
30
31 /**
32 * Return alarm at DateTime "when". If more than one is registered at this
33 * DateTime, the first one is returned.
34 * If none was found, an empty Alarm is returned.
35 * @param when The date and time of the returned alarm
36 * @param found Returns true if anything was found.
37 * @return Returns the found alarm at given DateTime. It is empty if found is false
38 * (nothing could be found at given date and time)
39 */
40 OPimAlarm alarmAtDateTime( const QDateTime& when, bool& found ) const;
41
42 void setAlarms( const Alarms& );
43 void setReminders( const Reminders& );
44
45 /* register is a Ansi C keyword... */
46 /**
47 * This function will register the Notify to the Alarm Server
48 * or datebook depending on the type of the notify
49 */
50 void registerNotify( const OPimNotify& );
51
52 /**
53 * this will do the opposite..
54 */
55 void deregister( const OPimNotify& );
56
57 bool isEmpty()const;
58
59 /**
60 * Return all alarms as string
61 */
62 QString alarmsToString() const;
63 /**
64 * Return all notifiers as string
65 */
66 QString remindersToString() const;
67
68 /**
69 * Convert string to alarms
70 * @param str String created by alarmsToString()
71 */
72 void alarmsFromString( const QString& str );
73
74 /**
75 * Convert string to reminders
76 * @param str String created by remindersToString()
77 */
78 void remindersFromString( const QString& str );
79
80
81
82private:
83 Reminders m_rem;
84 Alarms m_al;
85
86 class Private;
87 Private *d;
88
89};
90
91#endif
diff --git a/noncore/unsupported/libopie/pim/opimrecord.cpp b/noncore/unsupported/libopie/pim/opimrecord.cpp
new file mode 100644
index 0000000..2365748
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimrecord.cpp
@@ -0,0 +1,182 @@
1#include <qarray.h>
2
3#include <qpe/categories.h>
4#include <qpe/categoryselect.h>
5
6#include "opimrecord.h"
7
8Qtopia::UidGen OPimRecord::m_uidGen( Qtopia::UidGen::Qtopia );
9
10
11OPimRecord::OPimRecord( int uid )
12 : Qtopia::Record() {
13
14 m_lastHit = -1;
15 setUid( uid );
16}
17OPimRecord::~OPimRecord() {
18}
19OPimRecord::OPimRecord( const OPimRecord& rec )
20 : Qtopia::Record( rec )
21{
22 (*this) = rec;
23}
24
25OPimRecord &OPimRecord::operator=( const OPimRecord& rec) {
26 if ( this == &rec ) return *this;
27
28 Qtopia::Record::operator=( rec );
29 m_xrefman = rec.m_xrefman;
30 m_lastHit = rec.m_lastHit;
31
32 return *this;
33}
34/*
35 * category names
36 */
37QStringList OPimRecord::categoryNames( const QString& appname ) const {
38 QStringList list;
39 QArray<int> cats = categories();
40 Categories catDB;
41 catDB.load( categoryFileName() );
42
43 for (uint i = 0; i < cats.count(); i++ ) {
44 list << catDB.label( appname, cats[i] );
45 }
46
47 return list;
48}
49void OPimRecord::setCategoryNames( const QStringList& ) {
50
51}
52void OPimRecord::addCategoryName( const QString& ) {
53 Categories catDB;
54 catDB.load( categoryFileName() );
55
56
57}
58bool OPimRecord::isEmpty()const {
59 return ( uid() == 0 );
60}
61/*QString OPimRecord::crossToString()const {
62 QString str;
63 QMap<QString, QArray<int> >::ConstIterator it;
64 for (it = m_relations.begin(); it != m_relations.end(); ++it ) {
65 QArray<int> id = it.data();
66 for ( uint i = 0; i < id.size(); ++i ) {
67 str += it.key() + "," + QString::number( i ) + ";";
68 }
69 }
70 str = str.remove( str.length()-1, 1); // strip the ;
71 //qWarning("IDS " + str );
72
73 return str;
74 }*/
75/* if uid = 1 assign a new one */
76void OPimRecord::setUid( int uid ) {
77 if ( uid == 1)
78 uid = uidGen().generate();
79
80 Qtopia::Record::setUid( uid );
81};
82Qtopia::UidGen &OPimRecord::uidGen() {
83 return m_uidGen;
84}
85OPimXRefManager &OPimRecord::xrefmanager() {
86 return m_xrefman;
87}
88int OPimRecord::rtti(){
89 return 0;
90}
91
92/**
93 * now let's put our data into the stream
94 */
95/*
96 * First read UID
97 * Categories
98 * XRef
99 */
100bool OPimRecord::loadFromStream( QDataStream& stream ) {
101 int Int;
102 uint UInt;
103 stream >> Int;
104 setUid(Int);
105
106 /** Categories */
107 stream >> UInt;
108 QArray<int> array(UInt);
109 for (uint i = 0; i < UInt; i++ ) {
110 stream >> array[i];
111 }
112 setCategories( array );
113
114 /*
115 * now we do the X-Ref stuff
116 */
117 OPimXRef xref;
118 stream >> UInt;
119 for ( uint i = 0; i < UInt; i++ ) {
120 xref.setPartner( OPimXRef::One, partner( stream ) );
121 xref.setPartner( OPimXRef::Two, partner( stream ) );
122 m_xrefman.add( xref );
123 }
124
125 return true;
126}
127bool OPimRecord::saveToStream( QDataStream& stream )const {
128 /** UIDs */
129
130 stream << uid();
131
132 /** Categories */
133 stream << categories().count();
134 for ( uint i = 0; i < categories().count(); i++ ) {
135 stream << categories()[i];
136 }
137
138 /*
139 * first the XRef count
140 * then the xrefs
141 */
142 stream << m_xrefman.list().count();
143 for ( OPimXRef::ValueList::ConstIterator it = m_xrefman.list().begin();
144 it != m_xrefman.list().end(); ++it ) {
145 flush( (*it).partner( OPimXRef::One), stream );
146 flush( (*it).partner( OPimXRef::Two), stream );
147 }
148 return true;
149}
150void OPimRecord::flush( const OPimXRefPartner& par, QDataStream& str ) const{
151 str << par.service();
152 str << par.uid();
153 str << par.field();
154}
155OPimXRefPartner OPimRecord::partner( QDataStream& stream ) {
156 OPimXRefPartner par;
157 QString str;
158 int i;
159
160 stream >> str;
161 par.setService( str );
162
163 stream >> i;
164 par.setUid( i );
165
166 stream >> i ;
167 par.setField( i );
168
169 return par;
170}
171void OPimRecord::setLastHitField( int lastHit )const {
172 m_lastHit = lastHit;
173}
174int OPimRecord::lastHitField()const{
175 return m_lastHit;
176}
177QMap<QString, QString> OPimRecord::toExtraMap()const {
178 return customMap;
179}
180void OPimRecord::setExtraMap( const QMap<QString, QString>& map) {
181 customMap = map;
182}
diff --git a/noncore/unsupported/libopie/pim/opimrecord.h b/noncore/unsupported/libopie/pim/opimrecord.h
new file mode 100644
index 0000000..3d774e2
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimrecord.h
@@ -0,0 +1,158 @@
1#ifndef OPIE_PIM_RECORD_H
2#define OPIE_PIM_RECORD_H
3
4#include <qdatastream.h>
5#include <qmap.h>
6#include <qstring.h>
7#include <qstringlist.h>
8
9/*
10 * we need to get customMap which is private...
11 */
12#define private protected
13#include <qpe/palmtoprecord.h>
14#undef private
15
16#include <opie/opimxrefmanager.h>
17
18/**
19 * This is the base class for
20 * all PIM Records
21 *
22 */
23class OPimRecord : public Qtopia::Record {
24public:
25 /**
26 * c'tor
27 * uid of 0 isEmpty
28 * uid of 1 will be assigned a new one
29 */
30 OPimRecord(int uid = 0);
31 ~OPimRecord();
32
33 /**
34 * copy c'tor
35 */
36 OPimRecord( const OPimRecord& rec );
37
38 /**
39 * copy operator
40 */
41 OPimRecord &operator=( const OPimRecord& );
42
43 /**
44 * category names resolved
45 */
46 QStringList categoryNames( const QString& appname )const;
47
48 /**
49 * set category names they will be resolved
50 */
51 void setCategoryNames( const QStringList& );
52
53 /**
54 * addCategoryName adds a name
55 * to the internal category list
56 */
57 void addCategoryName( const QString& );
58
59 /**
60 * if a Record isEmpty
61 * it's empty if it's 0
62 */
63 virtual bool isEmpty()const;
64
65 /**
66 * toRichText summary
67 */
68 virtual QString toRichText()const = 0;
69
70 /**
71 * a small one line summary
72 */
73 virtual QString toShortText()const = 0;
74
75 /**
76 * the name of the Record
77 */
78 virtual QString type()const = 0;
79
80 /**
81 * matches the Records the regular expression?
82 */
83 virtual bool match( const QString &regexp ) const
84 {setLastHitField( -1 );
85 return Qtopia::Record::match(QRegExp(regexp));};
86
87 /**
88 * if implemented this function returns which item has been
89 * last hit by the match() function.
90 * or -1 if not implemented or no hit has occured
91 */
92 int lastHitField()const;
93
94 /**
95 * converts the internal structure to a map
96 */
97 virtual QMap<int, QString> toMap()const = 0;
98 // virtual fromMap( const <int, QString>& map ) = 0; // Should be added in the future (eilers)
99
100 /**
101 * key value representation of extra items
102 */
103 QMap<QString, QString> toExtraMap()const;
104 void setExtraMap( const QMap<QString, QString>& );
105
106 /**
107 * the name for a recordField
108 */
109 virtual QString recordField(int)const = 0;
110
111 /**
112 * returns a reference of the
113 * Cross Reference Manager
114 * Partner 'One' is THIS PIM RECORD!
115 * 'Two' is the Partner where we link to
116 */
117 OPimXRefManager& xrefmanager();
118
119 /**
120 * set the uid
121 */
122 virtual void setUid( int uid );
123
124 /*
125 * used inside the Templates for casting
126 * REIMPLEMENT in your ....
127 */
128 static int rtti();
129
130 /**
131 * some marshalling and de marshalling code
132 * saves the OPimRecord
133 * to and from a DataStream
134 */
135 virtual bool loadFromStream(QDataStream& );
136 virtual bool saveToStream( QDataStream& stream )const;
137
138protected:
139 // need to be const cause it is called from const methods
140 mutable int m_lastHit;
141 void setLastHitField( int lastHit )const;
142 Qtopia::UidGen &uidGen();
143// QString crossToString()const;
144
145private:
146 class OPimRecordPrivate;
147 OPimRecordPrivate *d;
148 OPimXRefManager m_xrefman;
149 static Qtopia::UidGen m_uidGen;
150
151private:
152 void flush( const OPimXRefPartner&, QDataStream& stream )const;
153 OPimXRefPartner partner( QDataStream& );
154};
155
156
157
158#endif
diff --git a/noncore/unsupported/libopie/pim/opimresolver.cpp b/noncore/unsupported/libopie/pim/opimresolver.cpp
new file mode 100644
index 0000000..4ebbd6e
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimresolver.cpp
@@ -0,0 +1,198 @@
1#include <qcopchannel_qws.h>
2
3#include <qpe/qcopenvelope_qws.h>
4
5#include "otodoaccess.h"
6#include "ocontactaccess.h"
7
8//#include "opimfactory.h"
9#include "opimresolver.h"
10
11OPimResolver* OPimResolver::m_self = 0l;
12
13OPimResolver::OPimResolver() {
14 /* the built in channels */
15 m_builtIns << "Todolist" << "Addressbook" << "Datebook";
16}
17OPimResolver* OPimResolver::self() {
18 if (!m_self)
19 m_self = new OPimResolver();
20
21 return m_self;
22}
23
24/*
25 * FIXME use a cache here too
26 */
27OPimRecord* OPimResolver::record( const QString& service, int uid ) {
28 OPimRecord* rec = 0l;
29 OPimBase* base = backend( service );
30
31 if ( base )
32 rec = base->record( uid );
33 delete base;
34
35 return rec;
36}
37OPimRecord* OPimResolver::record( const QString& service ) {
38 return record( serviceId( service ) );
39}
40OPimRecord* OPimResolver::record( int rtti ) {
41 OPimRecord* rec = 0l;
42 switch( rtti ) {
43 case 1: /* todolist */
44 rec = new OTodo();
45 case 2: /* contact */
46 rec = new OContact();
47 default:
48 break;
49 }
50 /*
51 * FIXME resolve externally
52 */
53 if (!rec ) {
54 ;
55 }
56 return 0l;
57}
58bool OPimResolver::isBuiltIn( const QString& str) const{
59 return m_builtIns.contains( str );
60}
61QCString OPimResolver::qcopChannel( enum BuiltIn& built)const {
62 QCString str("QPE/");
63 switch( built ) {
64 case TodoList:
65 str += "Todolist";
66 break;
67 case DateBook:
68 str += "Datebook";
69 break;
70 case AddressBook:
71 str += "Addressbook";
72 break;
73 default:
74 break;
75 }
76
77 return str;
78}
79QCString OPimResolver::qcopChannel( const QString& service )const {
80 QCString str("QPE/");
81 str += service.latin1();
82 return str;
83}
84/*
85 * Implement services!!
86 * FIXME
87 */
88QCString OPimResolver::applicationChannel( enum BuiltIn& built)const {
89 QCString str("QPE/Application/");
90 switch( built ) {
91 case TodoList:
92 str += "todolist";
93 break;
94 case DateBook:
95 str += "datebook";
96 break;
97 case AddressBook:
98 str += "addressbook";
99 break;
100 }
101
102 return str;
103}
104QCString OPimResolver::applicationChannel( const QString& service )const {
105 QCString str("QPE/Application/");
106
107 if ( isBuiltIn( service ) ) {
108 if ( service == "Todolist" )
109 str += "todolist";
110 else if ( service == "Datebook" )
111 str += "datebook";
112 else if ( service == "Addressbook" )
113 str += "addressbook";
114 }else
115 ; // FIXME for additional stuff
116
117 return str;
118}
119QStringList OPimResolver::services()const {
120 return m_builtIns;
121}
122QString OPimResolver::serviceName( int rtti ) const{
123 QString str;
124 switch ( rtti ) {
125 case TodoList:
126 str = "Todolist";
127 break;
128 case DateBook:
129 str = "Datebook";
130 break;
131 case AddressBook:
132 str = "Addressbook";
133 break;
134 default:
135 break;
136 }
137 return str;
138 // FIXME me for 3rd party
139}
140int OPimResolver::serviceId( const QString& service ) {
141 int rtti = 0;
142 if ( service == "Todolist" )
143 rtti = TodoList;
144 else if ( service == "Datebook" )
145 rtti = DateBook;
146 else if ( service == "Addressbook" )
147 rtti = AddressBook;
148
149 return rtti;
150}
151/**
152 * check if the 'service' is registered and if so we'll
153 */
154bool OPimResolver::add( const QString& service, const OPimRecord& rec) {
155 if ( QCopChannel::isRegistered( applicationChannel( service ) ) ) {
156 QByteArray data;
157 QDataStream arg(data, IO_WriteOnly );
158 if ( rec.saveToStream( arg ) ) {
159 QCopEnvelope env( applicationChannel( service ), "add(int,QByteArray)" );
160 env << rec.rtti();
161 env << data;
162 }else
163 return false;
164 }else{
165 OPimBase* base = backend( service );
166 if (!base ) return false;
167
168 base->load();
169 base->add( rec );
170 base->save();
171 delete base;
172 }
173
174 return true;
175}
176OPimBase* OPimResolver::backend( const QString& service ) {
177 return backend( serviceId( service ) );
178}
179OPimBase* OPimResolver::backend( int rtti ) {
180 OPimBase* base = 0l;
181 switch( rtti ) {
182 case TodoList:
183 base = new OTodoAccess();
184 break;
185 case DateBook:
186 break;
187 case AddressBook:
188 base = new OContactAccess("Resolver");
189 break;
190 default:
191 break;
192 }
193 // FIXME for 3rd party
194 if (!base )
195 ;
196
197 return base;
198}
diff --git a/noncore/unsupported/libopie/pim/opimresolver.h b/noncore/unsupported/libopie/pim/opimresolver.h
new file mode 100644
index 0000000..1ce1619
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimresolver.h
@@ -0,0 +1,90 @@
1#ifndef OPIE_PIM_RESOLVER
2#define OPIE_PIM_RESOLVER
3
4#include <qstring.h>
5#include <qvaluelist.h>
6
7#include <opie/otemplatebase.h>
8
9/**
10 * OPimResolver is a MetaClass to access
11 * available backends read only.
12 * It will be used to resolve uids + app names
13 * to full informations
14 * to traverse through a list of alarms, reminders
15 * to get access to built in PIM functionality
16 * and to more stuff
17 * THE PERFORMANCE will depend on THE BACKEND
18 * USING XML is a waste of memory!!!!!
19 */
20class OPimResolver {
21public:
22 enum BuiltIn { TodoList = 0,
23 DateBook,
24 AddressBook
25 };
26 static OPimResolver* self();
27
28
29 /**
30 * return a record for a uid
31 * and an service
32 * You've THE OWNERSHIP NOW!
33 */
34 OPimRecord *record( const QString& service, int uid );
35
36 /**
37 * return the QCopChannel for service
38 * When we will use Qtopia Services it will be used here
39 */
40 QCString qcopChannel( enum BuiltIn& )const;
41 QCString qcopChannel( const QString& service )const;
42
43 /**
44 * The Application channel (QPE/Application/name)
45 */
46 QCString applicationChannel( enum BuiltIn& )const;
47 QCString applicationChannel( const QString& service )const;
48
49 /**
50 * return a list of available services
51 */
52 QStringList services()const;
53 inline QString serviceName(int rrti )const;
54 int serviceId( const QString& Service);
55 /**
56 * add a record to a service... ;)
57 */
58 bool add( const QString& service, const OPimRecord& );
59
60
61 /**
62 * record returns an empty record for a given service.
63 * Be sure to delete it!!!
64 *
65 */
66 OPimRecord* record( const QString& service );
67 OPimRecord* record( int rtti );
68
69 /**
70 * you can cast to your
71 */
72 OPimBase* backend( const QString& service );
73 OPimBase* backend( int rtti );
74private:
75 OPimResolver();
76 void loadData();
77 inline bool isBuiltIn( const QString& )const;
78 OPimRecord* recordExtern( const QString&, int );
79 OPimRecord* recordExtern( const QString& );
80
81 static OPimResolver* m_self;
82 struct Data;
83 class Private;
84
85 Data* data;
86 Private* d;
87 QStringList m_builtIns;
88};
89
90#endif
diff --git a/noncore/unsupported/libopie/pim/opimstate.cpp b/noncore/unsupported/libopie/pim/opimstate.cpp
new file mode 100644
index 0000000..6fb2feb
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimstate.cpp
@@ -0,0 +1,64 @@
1#include <qshared.h>
2
3#include "opimstate.h"
4
5/*
6 * for one int this does not make
7 * much sense but never the less
8 * we will do it for the future
9 */
10struct OPimState::Data : public QShared {
11 Data() : QShared(),state(Undefined) {
12 }
13 int state;
14};
15
16OPimState::OPimState( int state ) {
17 data = new Data;
18 data->state = state;
19}
20OPimState::OPimState( const OPimState& st) :
21 data( st.data ) {
22 /* ref up */
23 data->ref();
24}
25OPimState::~OPimState() {
26 if ( data->deref() ) {
27 delete data ;
28 data = 0;
29 }
30}
31bool OPimState::operator==( const OPimState& st) {
32 if ( data->state == st.data->state ) return true;
33
34 return false;
35}
36OPimState &OPimState::operator=( const OPimState& st) {
37 st.data->ref();
38 deref();
39 data = st.data;
40
41 return *this;
42}
43void OPimState::setState( int st) {
44 copyInternally();
45 data->state = st;
46}
47int OPimState::state()const {
48 return data->state;
49}
50void OPimState::deref() {
51 if ( data->deref() ) {
52 delete data;
53 data = 0l;
54 }
55}
56void OPimState::copyInternally() {
57 /* we need to change it */
58 if ( data->count != 1 ) {
59 data->deref();
60 Data* d2 = new Data;
61 d2->state = data->state;
62 data = d2;
63 }
64}
diff --git a/noncore/unsupported/libopie/pim/opimstate.h b/noncore/unsupported/libopie/pim/opimstate.h
new file mode 100644
index 0000000..cf6af46
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimstate.h
@@ -0,0 +1,46 @@
1#ifndef OPIE_PIM_STATE_H
2#define OPIE_PIM_STATE_H
3
4#include <qstring.h>
5
6/**
7 * The State of a Task
8 * This class encapsules the state of a todo
9 * and it's shared too
10 */
11/*
12 * in c a simple struct would be enough ;)
13 * g_new_state();
14 * g_do_some_thing( state_t* );
15 * ;)
16 */
17class OPimState {
18public:
19 enum State {
20 Started = 0,
21 Postponed,
22 Finished,
23 NotStarted,
24 Undefined
25 };
26 OPimState( int state = Undefined );
27 OPimState( const OPimState& );
28 ~OPimState();
29
30 bool operator==( const OPimState& );
31 OPimState &operator=( const OPimState& );
32 void setState( int state);
33 int state()const;
34private:
35 void deref();
36 inline void copyInternally();
37
38 struct Data;
39 Data* data;
40
41 class Private;
42 Private *d;
43};
44
45
46#endif
diff --git a/noncore/unsupported/libopie/pim/opimxref.cpp b/noncore/unsupported/libopie/pim/opimxref.cpp
new file mode 100644
index 0000000..8eefbd8
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimxref.cpp
@@ -0,0 +1,47 @@
1#include "opimxref.h"
2
3OPimXRef::OPimXRef( const OPimXRefPartner& one, const OPimXRefPartner& two )
4 : m_partners(2)
5{
6 m_partners[0] = one;
7 m_partners[1] = two;
8}
9OPimXRef::OPimXRef()
10 : m_partners(2)
11{
12
13}
14OPimXRef::OPimXRef( const OPimXRef& ref) {
15 *this = ref;
16}
17OPimXRef::~OPimXRef() {
18}
19OPimXRef &OPimXRef::operator=( const OPimXRef& ref) {
20 m_partners = ref.m_partners;
21 m_partners.detach();
22
23 return* this;
24}
25bool OPimXRef::operator==( const OPimXRef& oper ) {
26 if ( m_partners == oper.m_partners ) return true;
27
28 return false;
29}
30OPimXRefPartner OPimXRef::partner( enum Partners par) const{
31 return m_partners[par];
32}
33void OPimXRef::setPartner( enum Partners par, const OPimXRefPartner& part) {
34 m_partners[par] = part;
35}
36bool OPimXRef::containsString( const QString& string ) const{
37 if ( m_partners[One].service() == string ||
38 m_partners[Two].service() == string ) return true;
39
40 return false;
41}
42bool OPimXRef::containsUid( int uid ) const{
43 if ( m_partners[One].uid() == uid ||
44 m_partners[Two].uid() == uid ) return true;
45
46 return false;
47}
diff --git a/noncore/unsupported/libopie/pim/opimxref.h b/noncore/unsupported/libopie/pim/opimxref.h
new file mode 100644
index 0000000..6852651
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimxref.h
@@ -0,0 +1,39 @@
1#ifndef OPIM_XREF_H
2#define OPIM_XREF_H
3
4#include <qarray.h>
5#include <qvaluelist.h>
6
7#include <opie/opimxrefpartner.h>
8
9/**
10 * this is a Cross Referecne between
11 * two Cross Reference Partners
12 */
13class OPimXRef {
14public:
15 typedef QValueList<OPimXRef> ValueList;
16 enum Partners { One, Two };
17 OPimXRef( const OPimXRefPartner& ONE, const OPimXRefPartner& );
18 OPimXRef();
19 OPimXRef( const OPimXRef& );
20 ~OPimXRef();
21
22 OPimXRef &operator=( const OPimXRef& );
23 bool operator==( const OPimXRef& );
24
25 OPimXRefPartner partner( enum Partners )const;
26
27 void setPartner( enum Partners, const OPimXRefPartner& );
28
29 bool containsString( const QString& service)const;
30 bool containsUid( int uid )const;
31
32private:
33 QArray<OPimXRefPartner> m_partners;
34
35 class Private;
36 Private *d;
37};
38
39#endif
diff --git a/noncore/unsupported/libopie/pim/opimxrefmanager.cpp b/noncore/unsupported/libopie/pim/opimxrefmanager.cpp
new file mode 100644
index 0000000..58bfd24
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimxrefmanager.cpp
@@ -0,0 +1,71 @@
1#include "opimxrefmanager.h"
2
3
4OPimXRefManager::OPimXRefManager() {
5}
6OPimXRefManager::OPimXRefManager( const OPimXRefManager& ref) {
7 m_list = ref.m_list;
8}
9OPimXRefManager::~OPimXRefManager() {
10}
11OPimXRefManager &OPimXRefManager::operator=( const OPimXRefManager& ref) {
12 m_list = ref.m_list;
13 return *this;
14}
15bool OPimXRefManager::operator==( const OPimXRefManager& /*ref*/) {
16 // if ( m_list == ref.m_list ) return true;
17
18 return false;
19}
20void OPimXRefManager::add( const OPimXRef& ref) {
21 m_list.append( ref );
22}
23void OPimXRefManager::remove( const OPimXRef& ref) {
24 m_list.remove( ref );
25}
26void OPimXRefManager::replace( const OPimXRef& ref) {
27 m_list.remove( ref );
28 m_list.append( ref );
29}
30void OPimXRefManager::clear() {
31 m_list.clear();
32}
33QStringList OPimXRefManager::apps()const {
34 OPimXRef::ValueList::ConstIterator it;
35 QStringList list;
36
37 QString str;
38 for ( it = m_list.begin(); it != m_list.end(); ++it ) {
39 str = (*it).partner( OPimXRef::One ).service();
40 if ( !list.contains( str ) ) list << str;
41
42 str = (*it).partner( OPimXRef::Two ).service();
43 if ( !list.contains( str ) ) list << str;
44 }
45 return list;
46}
47OPimXRef::ValueList OPimXRefManager::list()const {
48 return m_list;
49}
50OPimXRef::ValueList OPimXRefManager::list( const QString& appName )const{
51 OPimXRef::ValueList list;
52 OPimXRef::ValueList::ConstIterator it;
53
54 for ( it = m_list.begin(); it != m_list.end(); ++it ) {
55 if ( (*it).containsString( appName ) )
56 list.append( (*it) );
57 }
58
59 return list;
60}
61OPimXRef::ValueList OPimXRefManager::list( int uid )const {
62 OPimXRef::ValueList list;
63 OPimXRef::ValueList::ConstIterator it;
64
65 for ( it = m_list.begin(); it != m_list.end(); ++it ) {
66 if ( (*it).containsUid( uid ) )
67 list.append( (*it) );
68 }
69
70 return list;
71}
diff --git a/noncore/unsupported/libopie/pim/opimxrefmanager.h b/noncore/unsupported/libopie/pim/opimxrefmanager.h
new file mode 100644
index 0000000..c485e98
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimxrefmanager.h
@@ -0,0 +1,43 @@
1#ifndef OPIM_XREF_MANAGER_H
2#define OPIM_XREF_MANAGER_H
3
4#include <qstringlist.h>
5
6#include <opie/opimxref.h>
7
8/**
9 * This is a simple manager for
10 * OPimXRefs.
11 * It allows addition, removing, replacing
12 * clearing and 'querying' the XRef...
13 */
14class OPimXRefManager {
15public:
16 OPimXRefManager();
17 OPimXRefManager( const OPimXRefManager& );
18 ~OPimXRefManager();
19
20 OPimXRefManager& operator=( const OPimXRefManager& );
21 bool operator==( const OPimXRefManager& );
22
23 void add( const OPimXRef& );
24 void remove( const OPimXRef& );
25 void replace( const OPimXRef& );
26
27 void clear();
28
29 /**
30 * apps participating
31 */
32 QStringList apps()const;
33 OPimXRef::ValueList list()const;
34 OPimXRef::ValueList list( const QString& service )const;
35 OPimXRef::ValueList list( int uid )const;
36
37private:
38 OPimXRef::ValueList m_list;
39 class Private;
40 Private *d;
41};
42
43#endif
diff --git a/noncore/unsupported/libopie/pim/opimxrefpartner.cpp b/noncore/unsupported/libopie/pim/opimxrefpartner.cpp
new file mode 100644
index 0000000..6ef3efb
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimxrefpartner.cpp
@@ -0,0 +1,43 @@
1#include "opimxrefpartner.h"
2
3OPimXRefPartner::OPimXRefPartner( const QString& appName,
4 int uid, int field )
5 : m_app(appName), m_uid(uid), m_field( field ) {
6}
7OPimXRefPartner::OPimXRefPartner( const OPimXRefPartner& ref ) {
8 *this = ref;
9}
10OPimXRefPartner::~OPimXRefPartner() {
11}
12OPimXRefPartner &OPimXRefPartner::operator=( const OPimXRefPartner& par ) {
13 m_app = par.m_app;
14 m_uid = par.m_uid;
15 m_field = par.m_field;
16
17 return *this;
18}
19bool OPimXRefPartner::operator==( const OPimXRefPartner& par ) {
20 if ( m_app != par.m_app ) return false;
21 if ( m_uid != par.m_uid ) return false;
22 if ( m_field != par.m_field ) return false;
23
24 return true;
25}
26QString OPimXRefPartner::service()const {
27 return m_app;
28}
29int OPimXRefPartner::uid()const {
30 return m_uid;
31}
32int OPimXRefPartner::field()const {
33 return m_field;
34}
35void OPimXRefPartner::setService( const QString& appName ) {
36 m_app = appName;
37}
38void OPimXRefPartner::setUid( int uid ) {
39 m_uid = uid;
40}
41void OPimXRefPartner::setField( int field ) {
42 m_field = field;
43}
diff --git a/noncore/unsupported/libopie/pim/opimxrefpartner.h b/noncore/unsupported/libopie/pim/opimxrefpartner.h
new file mode 100644
index 0000000..d76e384
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/opimxrefpartner.h
@@ -0,0 +1,40 @@
1#ifndef OPIM_XREF_PARTNER_H
2#define OPIM_XREF_PARTNER_H
3
4#include <qstring.h>
5
6/**
7 * This class represents one partner
8 * of a Cross Reference.
9 * In Opie one application
10 * can link one uid
11 * with one tableId( fieldId ) to another.
12 */
13class OPimXRefPartner {
14public:
15 OPimXRefPartner( const QString& service = QString::null,
16 int uid = 0, int field = -1 );
17 OPimXRefPartner( const OPimXRefPartner& );
18 OPimXRefPartner& operator=( const OPimXRefPartner& );
19 ~OPimXRefPartner();
20
21 bool operator==(const OPimXRefPartner& );
22
23 QString service()const;
24 int uid()const;
25 int field()const;
26
27 void setService( const QString& service );
28 void setUid( int uid );
29 void setField( int field );
30private:
31 QString m_app;
32 int m_uid;
33 int m_field;
34
35 class Private;
36 Private* d;
37};
38
39
40#endif
diff --git a/noncore/unsupported/libopie/pim/orecordlist.h b/noncore/unsupported/libopie/pim/orecordlist.h
new file mode 100644
index 0000000..5211f57
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/orecordlist.h
@@ -0,0 +1,306 @@
1
2#ifndef OPIE_RECORD_LIST_H
3#define OPIE_RECORD_LIST_H
4
5#include <qarray.h>
6
7#include "otemplatebase.h"
8#include "opimrecord.h"
9
10class ORecordListIteratorPrivate;
11/**
12 * Our List Iterator
13 * it behaves like STL or Qt
14 *
15 * for(it = list.begin(); it != list.end(); ++it )
16 * doSomeCoolStuff( (*it) );
17 */
18template <class T> class ORecordList;
19template <class T = OPimRecord>
20class ORecordListIterator {
21 friend class ORecordList<T>;
22public:
23 typedef OTemplateBase<T> Base;
24
25 /**
26 * The c'tor used internally from
27 * ORecordList
28 */
29 ORecordListIterator( const QArray<int>, const Base* );
30
31 /**
32 * The standard c'tor
33 */
34 ORecordListIterator();
35 ~ORecordListIterator();
36
37 ORecordListIterator( const ORecordListIterator& );
38 ORecordListIterator &operator=(const ORecordListIterator& );
39
40 /**
41 * a * operator ;)
42 * use it like this T = (*it);
43 */
44 T operator*();
45 ORecordListIterator &operator++();
46 ORecordListIterator &operator--();
47
48 bool operator==( const ORecordListIterator& it );
49 bool operator!=( const ORecordListIterator& it );
50
51 /**
52 * the current item
53 */
54 uint current()const;
55
56 /**
57 * the number of items
58 */
59 uint count()const;
60
61 /**
62 * sets the current item
63 */
64 void setCurrent( uint cur );
65
66private:
67 QArray<int> m_uids;
68 uint m_current;
69 const Base* m_temp;
70 bool m_end : 1;
71 T m_record;
72 bool m_direction :1;
73
74 /* d pointer for future versions */
75 ORecordListIteratorPrivate *d;
76};
77
78class ORecordListPrivate;
79/**
80 * The recordlist used as a return type
81 * from OPimAccessTemplate
82 */
83template <class T = OPimRecord >
84class ORecordList {
85public:
86 typedef OTemplateBase<T> Base;
87 typedef ORecordListIterator<T> Iterator;
88
89 /**
90 * c'tor
91 */
92 ORecordList () {
93 }
94ORecordList( const QArray<int>& ids,
95 const Base* );
96 ~ORecordList();
97
98 /**
99 * the first iterator
100 */
101 Iterator begin();
102
103 /**
104 * the end
105 */
106 Iterator end();
107
108 /**
109 * the number of items in the list
110 */
111 uint count()const;
112
113 T operator[]( uint i );
114 int uidAt(uint i );
115
116 /**
117 * Remove the contact with given uid
118 */
119 bool remove( int uid );
120
121 /*
122 ConstIterator begin()const;
123 ConstIterator end()const;
124 */
125private:
126 QArray<int> m_ids;
127 const Base* m_acc;
128 ORecordListPrivate *d;
129};
130
131/* ok now implement it */
132template <class T>
133ORecordListIterator<T>::ORecordListIterator() {
134 m_current = 0;
135 m_temp = 0l;
136 m_end = true;
137 m_record = T();
138 /* forward */
139 m_direction = TRUE;
140}
141template <class T>
142ORecordListIterator<T>::~ORecordListIterator() {
143/* nothing to delete */
144}
145
146template <class T>
147ORecordListIterator<T>::ORecordListIterator( const ORecordListIterator<T>& it) {
148// qWarning("ORecordListIterator copy c'tor");
149 m_uids = it.m_uids;
150 m_current = it.m_current;
151 m_temp = it.m_temp;
152 m_end = it.m_end;
153 m_record = it.m_record;
154 m_direction = it.m_direction;
155}
156
157template <class T>
158ORecordListIterator<T> &ORecordListIterator<T>::operator=( const ORecordListIterator<T>& it) {
159 m_uids = it.m_uids;
160 m_current = it.m_current;
161 m_temp = it.m_temp;
162 m_end = it.m_end;
163 m_record = it.m_record;
164
165 return *this;
166}
167
168template <class T>
169T ORecordListIterator<T>::operator*() {
170 //qWarning("operator* %d %d", m_current, m_uids[m_current] );
171 if (!m_end )
172 m_record = m_temp->find( m_uids[m_current], m_uids, m_current,
173 m_direction ? Base::Forward :
174 Base::Reverse );
175 else
176 m_record = T();
177
178 return m_record;
179}
180
181template <class T>
182ORecordListIterator<T> &ORecordListIterator<T>::operator++() {
183 m_direction = true;
184 if (m_current < m_uids.count() ) {
185 m_end = false;
186 ++m_current;
187 }else
188 m_end = true;
189
190 return *this;
191}
192template <class T>
193ORecordListIterator<T> &ORecordListIterator<T>::operator--() {
194 m_direction = false;
195 if ( m_current > 0 ) {
196 --m_current;
197 m_end = false;
198 } else
199 m_end = true;
200
201 return *this;
202}
203
204template <class T>
205bool ORecordListIterator<T>::operator==( const ORecordListIterator<T>& it ) {
206
207 /* if both are at we're the same.... */
208 if ( m_end == it.m_end ) return true;
209
210 if ( m_uids != it.m_uids ) return false;
211 if ( m_current != it.m_current ) return false;
212 if ( m_temp != it.m_temp ) return false;
213
214 return true;
215}
216template <class T>
217bool ORecordListIterator<T>::operator!=( const ORecordListIterator<T>& it ) {
218 return !(*this == it );
219}
220template <class T>
221ORecordListIterator<T>::ORecordListIterator( const QArray<int> uids,
222 const Base* t )
223 : m_uids( uids ), m_current( 0 ), m_temp( t ), m_end( false ),
224 m_direction( false )
225{
226 /* if the list is empty we're already at the end of the list */
227 if (uids.count() == 0 )
228 m_end = true;
229}
230template <class T>
231uint ORecordListIterator<T>::current()const {
232 return m_current;
233}
234template <class T>
235void ORecordListIterator<T>::setCurrent( uint cur ) {
236 if( cur < m_uids.count() ) {
237 m_end = false;
238 m_current= cur;
239 }
240}
241template <class T>
242uint ORecordListIterator<T>::count()const {
243 return m_uids.count();
244}
245template <class T>
246ORecordList<T>::ORecordList( const QArray<int>& ids,
247 const Base* acc )
248 : m_ids( ids ), m_acc( acc )
249{
250}
251template <class T>
252ORecordList<T>::~ORecordList() {
253/* nothing to do here */
254}
255template <class T>
256typename ORecordList<T>::Iterator ORecordList<T>::begin() {
257 Iterator it( m_ids, m_acc );
258 return it;
259}
260template <class T>
261typename ORecordList<T>::Iterator ORecordList<T>::end() {
262 Iterator it( m_ids, m_acc );
263 it.m_end = true;
264 it.m_current = m_ids.count();
265
266 return it;
267}
268template <class T>
269uint ORecordList<T>::count()const {
270return m_ids.count();
271}
272template <class T>
273T ORecordList<T>::operator[]( uint i ) {
274 if ( i >= m_ids.count() )
275 return T();
276 /* forward */
277 return m_acc->find( m_ids[i], m_ids, i );
278}
279template <class T>
280int ORecordList<T>::uidAt( uint i ) {
281 return m_ids[i];
282}
283
284template <class T>
285bool ORecordList<T>::remove( int uid ) {
286 QArray<int> copy( m_ids.count() );
287 int counter = 0;
288 bool ret_val = false;
289
290 for (uint i = 0; i < m_ids.count(); i++){
291 if ( m_ids[i] != uid ){
292 copy[counter++] = m_ids[i];
293
294 }else
295 ret_val = true;
296 }
297
298 copy.resize( counter );
299 m_ids = copy;
300
301
302 return ret_val;
303}
304
305
306#endif
diff --git a/noncore/unsupported/libopie/pim/orecur.cpp b/noncore/unsupported/libopie/pim/orecur.cpp
new file mode 100644
index 0000000..f46f22e
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/orecur.cpp
@@ -0,0 +1,593 @@
1#include <time.h>
2
3#include <qshared.h>
4
5#include <qtopia/timeconversion.h>
6
7#include "otimezone.h"
8#include "orecur.h"
9
10struct ORecur::Data : public QShared {
11 Data() : QShared() {
12 type = ORecur::NoRepeat;
13 freq = -1;
14 days = 0;
15 pos = 0;
16 create = QDateTime::currentDateTime();
17 hasEnd = FALSE;
18 end = QDate::currentDate();
19 }
20 char days; // Q_UINT8 for 8 seven days;)
21 ORecur::RepeatType type;
22 int freq;
23 int pos;
24 bool hasEnd : 1;
25 QDate end;
26 QDateTime create;
27 int rep;
28 QString app;
29 ExceptionList list;
30 QDate start;
31};
32
33
34ORecur::ORecur() {
35 data = new Data;
36}
37
38ORecur::ORecur( const QMap<int, QString>& map )
39{
40 ORecur();
41 fromMap( map );
42}
43
44
45ORecur::ORecur( const ORecur& rec)
46 : data( rec.data )
47{
48 data->ref();
49}
50ORecur::~ORecur() {
51 if ( data->deref() ) {
52 delete data;
53 data = 0l;
54 }
55}
56void ORecur::deref() {
57 if ( data->deref() ) {
58 delete data;
59 data = 0l;
60 }
61}
62bool ORecur::operator==( const ORecur& )const {
63 return false;
64}
65ORecur &ORecur::operator=( const ORecur& re) {
66 if ( *this == re ) return *this;
67
68 re.data->ref();
69 deref();
70 data = re.data;
71
72 return *this;
73}
74bool ORecur::doesRecur()const {
75 return !( type() == NoRepeat );
76}
77/*
78 * we try to be smart here
79 *
80 */
81bool ORecur::doesRecur( const QDate& date ) {
82 /* the day before the recurrance */
83 QDate da = date.addDays(-1);
84
85 QDate recur;
86 if (!nextOcurrence( da, recur ) )
87 return false;
88
89 return (recur == date);
90}
91// FIXME unuglify!
92// GPL from Datebookdb.cpp
93// FIXME exception list!
94bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
95 bool stillLooking;
96 stillLooking = p_nextOccurrence( from, next );
97 while ( stillLooking && data->list.contains(next) )
98 stillLooking = p_nextOccurrence( next.addDays(1), next );
99
100 return stillLooking;
101}
102bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) {
103
104 // easy checks, first are we too far in the future or too far in the past?
105 QDate tmpDate;
106 int freq = frequency();
107 int diff, diff2, a;
108 int iday, imonth, iyear;
109 int dayOfWeek = 0;
110 int firstOfWeek = 0;
111 int weekOfMonth;
112
113
114 if (hasEndDate() && endDate() < from)
115 return FALSE;
116
117 if (start() >= from ) {
118 next = start();
119 return TRUE;
120 }
121
122 switch ( type() ) {
123 case Weekly:
124 /* weekly is just daily by 7 */
125 /* first convert the repeatPattern.Days() mask to the next
126 day of week valid after from */
127 dayOfWeek = from.dayOfWeek();
128 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */
129
130 /* this is done in case freq > 1 and from in week not
131 for this round */
132 // firstOfWeek = 0; this is already done at decl.
133 while(!((1 << firstOfWeek) & days() ))
134 firstOfWeek++;
135
136 /* there is at least one 'day', or there would be no event */
137 while(!((1 << (dayOfWeek % 7)) & days() ))
138 dayOfWeek++;
139
140 dayOfWeek = dayOfWeek % 7; /* the actual day of week */
141 dayOfWeek -= start().dayOfWeek() -1;
142
143 firstOfWeek = firstOfWeek % 7; /* the actual first of week */
144 firstOfWeek -= start().dayOfWeek() -1;
145
146 // dayOfWeek may be negitive now
147 // day of week is number of days to add to start day
148
149 freq *= 7;
150 // FALL-THROUGH !!!!!
151 case Daily:
152 // the add is for the possible fall through from weekly */
153 if(start().addDays(dayOfWeek) > from) {
154 /* first week exception */
155 next = QDate(start().addDays(dayOfWeek) );
156 if ((next > endDate())
157 && hasEndDate() )
158 return FALSE;
159 return TRUE;
160 }
161 /* if from is middle of a non-week */
162
163 diff = start().addDays(dayOfWeek).daysTo(from) % freq;
164 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq;
165
166 if(diff != 0)
167 diff = freq - diff;
168 if(diff2 != 0)
169 diff2 = freq - diff2;
170 diff = QMIN(diff, diff2);
171
172 next = QDate(from.addDays(diff));
173 if ( (next > endDate())
174 && hasEndDate() )
175 return FALSE;
176 return TRUE;
177 case MonthlyDay:
178 iday = from.day();
179 iyear = from.year();
180 imonth = from.month();
181 /* find equivelent day of month for this month */
182 dayOfWeek = start().dayOfWeek();
183 weekOfMonth = (start().day() - 1) / 7;
184
185 /* work out when the next valid month is */
186 a = from.year() - start().year();
187 a *= 12;
188 a = a + (imonth - start().month());
189 /* a is e.start()monthsFrom(from); */
190 if(a % freq) {
191 a = freq - (a % freq);
192 imonth = from.month() + a;
193 if (imonth > 12) {
194 imonth--;
195 iyear += imonth / 12;
196 imonth = imonth % 12;
197 imonth++;
198 }
199 }
200 /* imonth is now the first month after or on
201 from that matches the frequency given */
202
203 /* find for this month */
204 tmpDate = QDate( iyear, imonth, 1 );
205
206 iday = 1;
207 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
208 iday += 7 * weekOfMonth;
209 while (iday > tmpDate.daysInMonth()) {
210 imonth += freq;
211 if (imonth > 12) {
212 imonth--;
213 iyear += imonth / 12;
214 imonth = imonth % 12;
215 imonth++;
216 }
217 tmpDate = QDate( iyear, imonth, 1 );
218 /* these loops could go for a while, check end case now */
219 if ((tmpDate > endDate()) && hasEndDate() )
220 return FALSE;
221 iday = 1;
222 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
223 iday += 7 * weekOfMonth;
224 }
225 tmpDate = QDate(iyear, imonth, iday);
226
227 if (tmpDate >= from) {
228 next = tmpDate;
229 if ((next > endDate() ) && hasEndDate() )
230 return FALSE;
231 return TRUE;
232 }
233
234 /* need to find the next iteration */
235 do {
236 imonth += freq;
237 if (imonth > 12) {
238 imonth--;
239 iyear += imonth / 12;
240 imonth = imonth % 12;
241 imonth++;
242 }
243 tmpDate = QDate( iyear, imonth, 1 );
244 /* these loops could go for a while, check end case now */
245 if ((tmpDate > endDate()) && hasEndDate() )
246 return FALSE;
247 iday = 1;
248 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
249 iday += 7 * weekOfMonth;
250 } while (iday > tmpDate.daysInMonth());
251 tmpDate = QDate(iyear, imonth, iday);
252
253 next = tmpDate;
254 if ((next > endDate()) && hasEndDate() )
255 return FALSE;
256 return TRUE;
257 case MonthlyDate:
258 iday = start().day();
259 iyear = from.year();
260 imonth = from.month();
261
262 a = from.year() - start().year();
263 a *= 12;
264 a = a + (imonth - start().month());
265 /* a is e.start()monthsFrom(from); */
266 if(a % freq) {
267 a = freq - (a % freq);
268 imonth = from.month() + a;
269 if (imonth > 12) {
270 imonth--;
271 iyear += imonth / 12;
272 imonth = imonth % 12;
273 imonth++;
274 }
275 }
276 /* imonth is now the first month after or on
277 from that matches the frequencey given */
278
279 /* this could go for a while, worse case, 4*12 iterations, probably */
280 while(!QDate::isValid(iyear, imonth, iday) ) {
281 imonth += freq;
282 if (imonth > 12) {
283 imonth--;
284 iyear += imonth / 12;
285 imonth = imonth % 12;
286 imonth++;
287 }
288 /* these loops could go for a while, check end case now */
289 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
290 return FALSE;
291 }
292
293 if(QDate(iyear, imonth, iday) >= from) {
294 /* done */
295 next = QDate(iyear, imonth, iday);
296 if ((next > endDate()) && hasEndDate() )
297 return FALSE;
298 return TRUE;
299 }
300
301 /* ok, need to cycle */
302 imonth += freq;
303 imonth--;
304 iyear += imonth / 12;
305 imonth = imonth % 12;
306 imonth++;
307
308 while(!QDate::isValid(iyear, imonth, iday) ) {
309 imonth += freq;
310 imonth--;
311 iyear += imonth / 12;
312 imonth = imonth % 12;
313 imonth++;
314 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
315 return FALSE;
316 }
317
318 next = QDate(iyear, imonth, iday);
319 if ((next > endDate()) && hasEndDate() )
320 return FALSE;
321 return TRUE;
322 case Yearly:
323 iday = start().day();
324 imonth = start().month();
325 iyear = from.year(); // after all, we want to start in this year
326
327 diff = 1;
328 if(imonth == 2 && iday > 28) {
329 /* leap year, and it counts, calculate actual frequency */
330 if(freq % 4)
331 if (freq % 2)
332 freq = freq * 4;
333 else
334 freq = freq * 2;
335 /* else divides by 4 already, leave freq alone */
336 diff = 4;
337 }
338
339 a = from.year() - start().year();
340 if(a % freq) {
341 a = freq - (a % freq);
342 iyear = iyear + a;
343 }
344
345 /* under the assumption we won't hit one of the special not-leap years twice */
346 if(!QDate::isValid(iyear, imonth, iday)) {
347 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
348 iyear += freq;
349 }
350
351 if(QDate(iyear, imonth, iday) >= from) {
352 next = QDate(iyear, imonth, iday);
353
354 if ((next > endDate()) && hasEndDate() )
355 return FALSE;
356 return TRUE;
357 }
358 /* iyear == from.year(), need to advance again */
359 iyear += freq;
360 /* under the assumption we won't hit one of the special not-leap years twice */
361 if(!QDate::isValid(iyear, imonth, iday)) {
362 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
363 iyear += freq;
364 }
365
366 next = QDate(iyear, imonth, iday);
367 if ((next > endDate()) && hasEndDate() )
368 return FALSE;
369 return TRUE;
370 default:
371 return FALSE;
372 }
373}
374ORecur::RepeatType ORecur::type()const{
375 return data->type;
376}
377int ORecur::frequency()const {
378 return data->freq;
379}
380int ORecur::position()const {
381 return data->pos;
382}
383char ORecur::days() const{
384 return data->days;
385}
386bool ORecur::hasEndDate()const {
387 return data->hasEnd;
388}
389QDate ORecur::endDate()const {
390 return data->end;
391}
392QDate ORecur::start()const{
393 return data->start;
394}
395QDateTime ORecur::createdDateTime()const {
396 return data->create;
397}
398int ORecur::repetition()const {
399 return data->rep;
400}
401QString ORecur::service()const {
402 return data->app;
403}
404ORecur::ExceptionList& ORecur::exceptions() {
405 return data->list;
406}
407void ORecur::setType( const RepeatType& z) {
408 checkOrModify();
409 data->type = z;
410}
411void ORecur::setFrequency( int freq ) {
412 checkOrModify();
413 data->freq = freq;
414}
415void ORecur::setPosition( int pos ) {
416 checkOrModify();
417 data->pos = pos;
418}
419void ORecur::setDays( char c ) {
420 checkOrModify();
421 data->days = c;
422}
423void ORecur::setEndDate( const QDate& dt) {
424 checkOrModify();
425 data->end = dt;
426}
427void ORecur::setCreatedDateTime( const QDateTime& t) {
428 checkOrModify();
429 data->create = t;
430}
431void ORecur::setHasEndDate( bool b) {
432 checkOrModify();
433 data->hasEnd = b;
434}
435void ORecur::setRepitition( int rep ) {
436 checkOrModify();
437 data->rep = rep;
438}
439void ORecur::setService( const QString& app ) {
440 checkOrModify();
441 data->app = app;
442}
443void ORecur::setStart( const QDate& dt ) {
444 checkOrModify();
445 data->start = dt;
446}
447void ORecur::checkOrModify() {
448 if ( data->count != 1 ) {
449 data->deref();
450 Data* d2 = new Data;
451 d2->days = data->days;
452 d2->type = data->type;
453 d2->freq = data->freq;
454 d2->pos = data->pos;
455 d2->hasEnd = data->hasEnd;
456 d2->end = data->end;
457 d2->create = data->create;
458 d2->rep = data->rep;
459 d2->app = data->app;
460 d2->list = data->list;
461 d2->start = data->start;
462 data = d2;
463 }
464}
465QString ORecur::toString()const {
466 QString buf;
467 QMap<int, QString> recMap = toMap();
468
469 buf += " rtype=\"";
470 buf += recMap[ORecur::RType];
471 buf += "\"";
472 if (data->days > 0 )
473 buf += " rweekdays=\"" + recMap[ORecur::RWeekdays] + "\"";
474 if ( data->pos != 0 )
475 buf += " rposition=\"" + recMap[ORecur::RPosition] + "\"";
476
477 buf += " rfreq=\"" + recMap[ORecur::RFreq] + "\"";
478 buf += " rhasenddate=\"" + recMap[ORecur::RHasEndDate]+ "\"";
479 if ( data->hasEnd )
480 buf += " enddt=\""
481 + recMap[ORecur::EndDate]
482 + "\"";
483 buf += " created=\"" + recMap[ORecur::Created] + "\"";
484
485 if ( data->list.isEmpty() ) return buf;
486 buf += " exceptions=\"";
487 buf += recMap[ORecur::Exceptions];
488 buf += "\" ";
489
490 return buf;
491}
492
493QString ORecur::rTypeString() const
494{
495 QString retString;
496 switch ( data->type ) {
497 case ORecur::Daily:
498 retString = "Daily";
499 break;
500 case ORecur::Weekly:
501 retString = "Weekly";
502 break;
503 case ORecur::MonthlyDay:
504 retString = "MonthlyDay";
505 break;
506 case ORecur::MonthlyDate:
507 retString = "MonthlyDate";
508 break;
509 case ORecur::Yearly:
510 retString = "Yearly";
511 break;
512 default:
513 retString = "NoRepeat";
514 break;
515
516 }
517
518 return retString;
519}
520
521QMap<QString, ORecur::RepeatType> ORecur::rTypeValueConvertMap() const
522{
523 QMap<QString, RepeatType> convertMap;
524
525 convertMap.insert( QString( "Daily" ), ORecur::Daily );
526 convertMap.insert( QString( "Weekly" ), ORecur::Weekly );
527 convertMap.insert( QString( "MonthlyDay" ), ORecur::MonthlyDay );
528 convertMap.insert( QString( "MonthlyDate" ), ORecur::MonthlyDate );
529 convertMap.insert( QString( "Yearly" ), ORecur::Yearly );
530 convertMap.insert( QString( "NoRepeat" ), ORecur::NoRepeat );
531
532 return convertMap;
533}
534
535
536QMap<int, QString> ORecur::toMap() const
537{
538 QMap<int, QString> retMap;
539
540 retMap.insert( ORecur::RType, rTypeString() );
541 retMap.insert( ORecur::RWeekdays, QString::number( static_cast<int>( data->days ) ) );
542 retMap.insert( ORecur::RPosition, QString::number(data->pos ) );
543 retMap.insert( ORecur::RFreq, QString::number( data->freq ) );
544 retMap.insert( ORecur::RHasEndDate, QString::number( static_cast<int>( data->hasEnd ) ) );
545 if( data -> hasEnd )
546 retMap.insert( ORecur::EndDate, QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) ) );
547 retMap.insert( ORecur::Created, QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) );
548
549 if ( data->list.isEmpty() ) return retMap;
550
551 // save exceptions list here!!
552 ExceptionList::ConstIterator it;
553 ExceptionList list = data->list;
554 QString exceptBuf;
555 QDate date;
556 for ( it = list.begin(); it != list.end(); ++it ) {
557 date = (*it);
558 if ( it != list.begin() ) exceptBuf += " ";
559
560 exceptBuf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() );
561 }
562
563 retMap.insert( ORecur::Exceptions, exceptBuf );
564
565 return retMap;
566}
567
568void ORecur::fromMap( const QMap<int, QString>& map )
569{
570 QMap<QString, RepeatType> repTypeMap = rTypeValueConvertMap();
571
572 data -> type = repTypeMap[ map [ORecur::RType] ];
573 data -> days = (char) map[ ORecur::RWeekdays ].toInt();
574 data -> pos = map[ ORecur::RPosition ].toInt();
575 data -> freq = map[ ORecur::RFreq ].toInt();
576 data -> hasEnd= map[ ORecur::RHasEndDate ].toInt() ? true : false;
577 OTimeZone utc = OTimeZone::utc();
578 if ( data -> hasEnd ){
579 data -> end = utc.fromUTCDateTime( (time_t) map[ ORecur::EndDate ].toLong() ).date();
580 }
581 data -> create = utc.fromUTCDateTime( (time_t) map[ ORecur::Created ].toLong() ).date();
582
583#if 0
584 // FIXME: Exceptions currently not supported...
585 // Convert the list of exceptions from QString into ExceptionList
586 data -> list.clear();
587 QString exceptStr = map[ ORecur::Exceptions ];
588 QStringList exceptList = QStringList::split( " ", exceptStr );
589 ...
590#endif
591
592
593}
diff --git a/noncore/unsupported/libopie/pim/orecur.h b/noncore/unsupported/libopie/pim/orecur.h
new file mode 100644
index 0000000..d7ecd90
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/orecur.h
@@ -0,0 +1,107 @@
1/*
2 * GPL from TT
3 */
4
5#ifndef OPIE_RECUR_H
6#define OPIE_RECUR_H
7
8#include <sys/types.h>
9
10#include <qdatetime.h>
11#include <qvaluelist.h>
12#include <qmap.h>
13
14
15/**
16 * Class to handle Recurrencies..
17 */
18
19class ORecur {
20public:
21 typedef QValueList<QDate> ExceptionList;
22 enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay,
23 MonthlyDate, Yearly };
24 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08,
25 FRI = 0x10, SAT = 0x20, SUN = 0x40 };
26 enum Fields{ RType = 0, RWeekdays, RPosition, RFreq, RHasEndDate,
27 EndDate, Created, Exceptions };
28
29 ORecur();
30 ORecur( const QMap<int, QString>& map );
31 ORecur( const ORecur& );
32 ~ORecur();
33
34 ORecur &operator=( const ORecur& );
35 bool operator==(const ORecur& )const;
36
37 bool doesRecur()const;
38 /* if it recurrs on that day */
39 bool doesRecur( const QDate& );
40 RepeatType type()const;
41 int frequency()const;
42 int position()const;
43 char days()const;
44 bool hasEndDate()const;
45 QDate start()const;
46 QDate endDate()const;
47 QDateTime createdDateTime()const;
48 /**
49 * starting on monday=0, sunday=6
50 * for convience
51 */
52 bool repeatOnWeekDay( int day )const;
53
54 /**
55 * FromWhereToStart is not included!!!
56 */
57 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate );
58
59 /**
60 * The module this ORecur belongs to
61 */
62 QString service()const;
63
64 /*
65 * reference to the exception list
66 */
67 ExceptionList &exceptions();
68
69 /**
70 * the current repetition
71 */
72 int repetition()const;
73
74 void setType( const RepeatType& );
75 void setFrequency( int freq );
76 void setPosition( int pos );
77 void setDays( char c);
78 void setEndDate( const QDate& dt );
79 void setStart( const QDate& dt );
80 void setCreatedDateTime( const QDateTime& );
81 void setHasEndDate( bool b );
82 void setRepitition(int );
83
84 void setService( const QString& ser );
85
86 QMap<int, QString> toMap() const;
87 void fromMap( const QMap<int, QString>& map );
88
89 /* almost internal */
90 QString toString()const;
91private:
92 bool p_nextOccurrence( const QDate& from, QDate& next );
93 void deref();
94 inline void checkOrModify();
95
96 /* Converts rType to String */
97 QString rTypeString() const;
98 /* Returns a map to convert Stringname for RType to RepeatType */
99 QMap<QString, RepeatType> rTypeValueConvertMap() const;
100
101 class Data;
102 Data* data;
103 class ORecurPrivate;
104 ORecurPrivate *d;
105};
106
107#endif
diff --git a/noncore/unsupported/libopie/pim/otemplatebase.h b/noncore/unsupported/libopie/pim/otemplatebase.h
new file mode 100644
index 0000000..cadac74
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otemplatebase.h
@@ -0,0 +1,98 @@
1#ifndef OPIE_TEMPLATE_BASE_H
2#define OPIE_TEMPLATE_BASE_H
3
4#include <qarray.h>
5
6#include <opie/opimrecord.h>
7
8
9/**
10 * Templates do not have a base class, This is why
11 * we've this class
12 * this is here to give us the possibility
13 * to have a common base class
14 * You may not want to use that interface internaly
15 * POOR mans interface
16 */
17class OPimBasePrivate;
18struct OPimBase {
19 /**
20 * return the rtti
21 */
22 virtual int rtti()= 0;
23 virtual OPimRecord* record()const = 0;
24 virtual OPimRecord* record(int uid)const = 0;
25 virtual bool add( const OPimRecord& ) = 0;
26 virtual bool remove( int uid ) = 0;
27 virtual bool remove( const OPimRecord& ) = 0;
28 virtual void clear() = 0;
29 virtual bool load() = 0;
30 virtual bool save() = 0;
31 virtual QArray<int> records()const = 0;
32 /*
33 * ADD editing here?
34 * -zecke
35 */
36private:
37 OPimBasePrivate* d;
38
39};
40/**
41 * internal template base
42 * T needs to implement the copy c'tor!!!
43 */
44class OTemplateBasePrivate;
45template <class T = OPimRecord>
46class OTemplateBase : public OPimBase {
47public:
48 enum CacheDirection { Forward=0, Reverse };
49 OTemplateBase() {
50 };
51 virtual ~OTemplateBase() {
52 }
53 virtual T find( int uid )const = 0;
54
55 /**
56 * read ahead find
57 */
58 virtual T find( int uid, const QArray<int>& items,
59 uint current, CacheDirection dir = Forward )const = 0;
60 virtual void cache( const T& )const = 0;
61 virtual void setSaneCacheSize( int ) = 0;
62
63 /* reimplement of OPimBase */
64 int rtti();
65 OPimRecord* record()const;
66 OPimRecord* record(int uid )const;
67 static T* rec();
68
69private:
70 OTemplateBasePrivate *d;
71};
72
73/*
74 * implementation
75 */
76template <class T>
77int
78OTemplateBase<T>::rtti() {
79 return T::rtti();
80}
81template <class T>
82OPimRecord* OTemplateBase<T>::record()const {
83 T* t = new T;
84 return t;
85}
86template <class T>
87OPimRecord* OTemplateBase<T>::record(int uid )const {
88 T t2 = find(uid );
89 T* t1 = new T(t2);
90
91 return t1;
92};
93template <class T>
94T* OTemplateBase<T>::rec() {
95 return new T;
96}
97
98#endif
diff --git a/noncore/unsupported/libopie/pim/otimezone.cpp b/noncore/unsupported/libopie/pim/otimezone.cpp
new file mode 100644
index 0000000..34659c3
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otimezone.cpp
@@ -0,0 +1,113 @@
1#include <stdio.h>
2#include <stdlib.h>
3
4#include <sys/types.h>
5
6#include "otimezone.h"
7
8namespace {
9
10 QDateTime utcTime( time_t t) {
11 tm* broken = ::gmtime( &t );
12 QDateTime ret;
13 ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) );
14 ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) );
15 return ret;
16 }
17 QDateTime utcTime( time_t t, const QString& zone) {
18 QCString org = ::getenv( "TZ" );
19#ifndef Q_OS_MACX // Following line causes bus errors on Mac
20 ::setenv( "TZ", zone.latin1(), true );
21 ::tzset();
22
23 tm* broken = ::localtime( &t );
24 ::setenv( "TZ", org, true );
25#else
26#warning "Need a replacement for MacOSX!!"
27 tm* broken = ::localtime( &t );
28#endif
29
30 QDateTime ret;
31 ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) );
32 ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) );
33
34 return ret;
35 }
36 time_t to_Time_t( const QDateTime& utc, const QString& str ) {
37 QDate d = utc.date();
38 QTime t = utc.time();
39
40 tm broken;
41 broken.tm_year = d.year() - 1900;
42 broken.tm_mon = d.month() - 1;
43 broken.tm_mday = d.day();
44 broken.tm_hour = t.hour();
45 broken.tm_min = t.minute();
46 broken.tm_sec = t.second();
47
48 QCString org = ::getenv( "TZ" );
49#ifndef Q_OS_MACX // Following line causes bus errors on Mac
50 ::setenv( "TZ", str.latin1(), true );
51 ::tzset();
52
53 time_t ti = ::mktime( &broken );
54 ::setenv( "TZ", org, true );
55#else
56#warning "Need a replacement for MacOSX!!"
57 time_t ti = ::mktime( &broken );
58#endif
59 return ti;
60 }
61}
62OTimeZone::OTimeZone( const ZoneName& zone )
63 : m_name(zone) {
64}
65OTimeZone::~OTimeZone() {
66}
67
68bool OTimeZone::isValid()const {
69 return !m_name.isEmpty();
70}
71
72/*
73 * we will get the current timezone
74 * and ask it to convert to the timezone date
75 */
76QDateTime OTimeZone::toLocalDateTime( const QDateTime& dt) {
77 return OTimeZone::current().toDateTime( dt, *this );
78}
79QDateTime OTimeZone::toUTCDateTime( const QDateTime& dt ) {
80 return OTimeZone::utc().toDateTime( dt, *this );
81}
82QDateTime OTimeZone::fromUTCDateTime( time_t t) {
83 return utcTime( t );
84}
85QDateTime OTimeZone::toDateTime( time_t t) {
86 return utcTime( t, m_name );
87}
88/*
89 * convert dt to utc using zone.m_name
90 * convert utc -> timeZoneDT using this->m_name
91 */
92QDateTime OTimeZone::toDateTime( const QDateTime& dt, const OTimeZone& zone ) {
93 time_t utc = to_Time_t( dt, zone.m_name );
94 qWarning("%d %s", utc, zone.m_name.latin1() );
95 return utcTime( utc, m_name );
96}
97time_t OTimeZone::fromDateTime( const QDateTime& time ) {
98 return to_Time_t( time, m_name );
99}
100time_t OTimeZone::fromUTCDateTime( const QDateTime& time ) {
101 return to_Time_t( time, "UTC" );
102}
103OTimeZone OTimeZone::current() {
104 QCString str = ::getenv("TZ");
105 OTimeZone zone( str );
106 return zone;
107}
108OTimeZone OTimeZone::utc() {
109 return OTimeZone("UTC");
110}
111QString OTimeZone::timeZone()const {
112 return m_name;
113}
diff --git a/noncore/unsupported/libopie/pim/otimezone.h b/noncore/unsupported/libopie/pim/otimezone.h
new file mode 100644
index 0000000..bb08349
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otimezone.h
@@ -0,0 +1,71 @@
1#ifndef OPIE_TIME_ZONE_H
2#define OPIE_TIME_ZONE_H
3
4#include <time.h>
5#include <qdatetime.h>
6
7/**
8 * A very primitive class to convert time
9 * from one timezone to another
10 * and to localtime
11 * and time_t
12 */
13class OTimeZone {
14 public:
15 typedef QString ZoneName;
16 OTimeZone( const ZoneName& = ZoneName::null );
17 virtual ~OTimeZone(); // just in case.
18
19 bool isValid()const;
20
21 /**
22 * converts the QDateTime to a DateTime
23 * in the local timezone
24 * if QDateTime is 25th Jan and takes place in Europe/Berlin at 12h
25 * and the current timezone is Europe/London the returned
26 * time will be 11h.
27 */
28 QDateTime toLocalDateTime( const QDateTime& dt );
29
30 /**
31 * converts the QDateTime to UTC time
32 */
33 QDateTime toUTCDateTime( const QDateTime& dt );
34
35 /**
36 * reads the time_t into a QDateTime using UTC as timezone!
37 */
38 QDateTime fromUTCDateTime( time_t );
39
40 /**
41 * converts the time_t to the time in the timezone
42 */
43 QDateTime toDateTime( time_t );
44
45 /**
46 * converts the QDateTime from one timezone to this timeZone
47 */
48 QDateTime toDateTime( const QDateTime&, const OTimeZone& timeZone );
49
50 /**
51 * converts the date time into a time_t. It takes the timezone into account
52 */
53 time_t fromDateTime( const QDateTime& );
54
55 /**
56 * converts the datetime with timezone UTC
57 */
58 time_t fromUTCDateTime( const QDateTime& );
59
60 static OTimeZone current();
61 static OTimeZone utc();
62
63 QString timeZone()const;
64 private:
65 ZoneName m_name;
66 class Private;
67 Private* d;
68};
69
70
71#endif
diff --git a/noncore/unsupported/libopie/pim/otodo.cpp b/noncore/unsupported/libopie/pim/otodo.cpp
new file mode 100644
index 0000000..b2c76f8
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodo.cpp
@@ -0,0 +1,519 @@
1
2#include <qobject.h>
3#include <qshared.h>
4
5
6
7#include <qpe/palmtopuidgen.h>
8#include <qpe/palmtoprecord.h>
9#include <qpe/categories.h>
10#include <qpe/categoryselect.h>
11#include <qpe/stringutil.h>
12
13
14#include "opimstate.h"
15#include "orecur.h"
16#include "opimmaintainer.h"
17#include "opimnotifymanager.h"
18#include "opimresolver.h"
19
20#include "otodo.h"
21
22
23struct OTodo::OTodoData : public QShared {
24 OTodoData() : QShared() {
25 recur = 0;
26 state = 0;
27 maintainer = 0;
28 notifiers = 0;
29 };
30 ~OTodoData() {
31 delete recur;
32 delete maintainer;
33 delete notifiers;
34 }
35
36 QDate date;
37 bool isCompleted:1;
38 bool hasDate:1;
39 int priority;
40 QString desc;
41 QString sum;
42 QMap<QString, QString> extra;
43 ushort prog;
44 OPimState *state;
45 ORecur *recur;
46 OPimMaintainer *maintainer;
47 QDate start;
48 QDate completed;
49 OPimNotifyManager *notifiers;
50};
51
52OTodo::OTodo(const OTodo &event )
53 : OPimRecord( event ), data( event.data )
54{
55 data->ref();
56// qWarning("ref up");
57}
58OTodo::~OTodo() {
59
60// qWarning("~OTodo " );
61 if ( data->deref() ) {
62// qWarning("OTodo::dereffing");
63 delete data;
64 data = 0l;
65 }
66}
67OTodo::OTodo(bool completed, int priority,
68 const QArray<int> &category,
69 const QString& summary,
70 const QString &description,
71 ushort progress,
72 bool hasDate, QDate date, int uid )
73 : OPimRecord( uid )
74{
75// qWarning("OTodoData " + summary);
76 setCategories( category );
77
78 data = new OTodoData;
79
80 data->date = date;
81 data->isCompleted = completed;
82 data->hasDate = hasDate;
83 data->priority = priority;
84 data->sum = summary;
85 data->prog = progress;
86 data->desc = Qtopia::simplifyMultiLineSpace(description );
87}
88OTodo::OTodo(bool completed, int priority,
89 const QStringList &category,
90 const QString& summary,
91 const QString &description,
92 ushort progress,
93 bool hasDate, QDate date, int uid )
94 : OPimRecord( uid )
95{
96// qWarning("OTodoData" + summary);
97 setCategories( idsFromString( category.join(";") ) );
98
99 data = new OTodoData;
100
101 data->date = date;
102 data->isCompleted = completed;
103 data->hasDate = hasDate;
104 data->priority = priority;
105 data->sum = summary;
106 data->prog = progress;
107 data->desc = Qtopia::simplifyMultiLineSpace(description );
108}
109bool OTodo::match( const QRegExp &regExp )const
110{
111 if( QString::number( data->priority ).find( regExp ) != -1 ){
112 setLastHitField( Priority );
113 return true;
114 }else if( data->hasDate && data->date.toString().find( regExp) != -1 ){
115 setLastHitField( HasDate );
116 return true;
117 }else if(data->desc.find( regExp ) != -1 ){
118 setLastHitField( Description );
119 return true;
120 }else if(data->sum.find( regExp ) != -1 ) {
121 setLastHitField( Summary );
122 return true;
123 }
124 return false;
125}
126bool OTodo::isCompleted() const
127{
128 return data->isCompleted;
129}
130bool OTodo::hasDueDate() const
131{
132 return data->hasDate;
133}
134bool OTodo::hasStartDate()const {
135 return data->start.isValid();
136}
137bool OTodo::hasCompletedDate()const {
138 return data->completed.isValid();
139}
140int OTodo::priority()const
141{
142 return data->priority;
143}
144QString OTodo::summary() const
145{
146 return data->sum;
147}
148ushort OTodo::progress() const
149{
150 return data->prog;
151}
152QDate OTodo::dueDate()const
153{
154 return data->date;
155}
156QDate OTodo::startDate()const {
157 return data->start;
158}
159QDate OTodo::completedDate()const {
160 return data->completed;
161}
162QString OTodo::description()const
163{
164 return data->desc;
165}
166bool OTodo::hasState() const{
167 if (!data->state ) return false;
168 return ( data->state->state() != OPimState::Undefined );
169}
170OPimState OTodo::state()const {
171 if (!data->state ) {
172 OPimState state;
173 return state;
174 }
175
176 return (*data->state);
177}
178bool OTodo::hasRecurrence()const {
179 if (!data->recur) return false;
180 return data->recur->doesRecur();
181}
182ORecur OTodo::recurrence()const {
183 if (!data->recur) return ORecur();
184
185 return (*data->recur);
186}
187bool OTodo::hasMaintainer()const {
188 if (!data->maintainer) return false;
189
190 return (data->maintainer->mode() != OPimMaintainer::Undefined );
191}
192OPimMaintainer OTodo::maintainer()const {
193 if (!data->maintainer) return OPimMaintainer();
194
195 return (*data->maintainer);
196}
197void OTodo::setCompleted( bool completed )
198{
199 changeOrModify();
200 data->isCompleted = completed;
201}
202void OTodo::setHasDueDate( bool hasDate )
203{
204 changeOrModify();
205 data->hasDate = hasDate;
206}
207void OTodo::setDescription(const QString &desc )
208{
209// qWarning( "desc " + desc );
210 changeOrModify();
211 data->desc = Qtopia::simplifyMultiLineSpace(desc );
212}
213void OTodo::setSummary( const QString& sum )
214{
215 changeOrModify();
216 data->sum = sum;
217}
218void OTodo::setPriority(int prio )
219{
220 changeOrModify();
221 data->priority = prio;
222}
223void OTodo::setDueDate( const QDate& date )
224{
225 changeOrModify();
226 data->date = date;
227}
228void OTodo::setStartDate( const QDate& date ) {
229 changeOrModify();
230 data->start = date;
231}
232void OTodo::setCompletedDate( const QDate& date ) {
233 changeOrModify();
234 data->completed = date;
235}
236void OTodo::setState( const OPimState& state ) {
237 changeOrModify();
238 if (data->state )
239 (*data->state) = state;
240 else
241 data->state = new OPimState( state );
242}
243void OTodo::setRecurrence( const ORecur& rec) {
244 changeOrModify();
245 if (data->recur )
246 (*data->recur) = rec;
247 else
248 data->recur = new ORecur( rec );
249}
250void OTodo::setMaintainer( const OPimMaintainer& pim ) {
251 changeOrModify();
252
253 if (data->maintainer )
254 (*data->maintainer) = pim;
255 else
256 data->maintainer = new OPimMaintainer( pim );
257}
258bool OTodo::isOverdue( )
259{
260 if( data->hasDate && !data->isCompleted)
261 return QDate::currentDate() > data->date;
262 return false;
263}
264void OTodo::setProgress(ushort progress )
265{
266 changeOrModify();
267 data->prog = progress;
268}
269QString OTodo::toShortText() const {
270 return summary();
271}
272/*!
273 Returns a richt text string
274*/
275QString OTodo::toRichText() const
276{
277 QString text;
278 QStringList catlist;
279
280 // summary
281 text += "<b><h3><img src=\"todo/TodoList\"> ";
282 if ( !summary().isEmpty() ) {
283 text += Qtopia::escapeString(summary() ).replace(QRegExp( "[\n]"), "" );
284 }
285 text += "</h3></b><br><hr><br>";
286
287 // description
288 if( !description().isEmpty() ){
289 text += "<b>" + QObject::tr( "Description:" ) + "</b><br>";
290 text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
291 }
292
293 // priority
294 int priorityval = priority();
295 text += "<b>" + QObject::tr( "Priority:") +" </b><img src=\"todo/priority" +
296 QString::number( priorityval ) + "\"> ";
297
298 switch ( priorityval )
299 {
300 case 1 : text += QObject::tr( "Very high" );
301 break;
302 case 2 : text += QObject::tr( "High" );
303 break;
304 case 3 : text += QObject::tr( "Normal" );
305 break;
306 case 4 : text += QObject::tr( "Low" );
307 break;
308 case 5 : text += QObject::tr( "Very low" );
309 break;
310 };
311 text += "<br>";
312
313 // progress
314 text += "<b>" + QObject::tr( "Progress:") + " </b>"
315 + QString::number( progress() ) + " %<br>";
316
317 // due date
318 if (hasDueDate() ){
319 QDate dd = dueDate();
320 int off = QDate::currentDate().daysTo( dd );
321
322 text += "<b>" + QObject::tr( "Deadline:" ) + " </b><font color=\"";
323 if ( off < 0 )
324 text += "#FF0000";
325 else if ( off == 0 )
326 text += "#FFFF00";
327 else if ( off > 0 )
328 text += "#00FF00";
329
330 text += "\">" + dd.toString() + "</font><br>";
331 }
332
333 // categories
334 text += "<b>" + QObject::tr( "Category:") + "</b> ";
335 text += categoryNames( "Todo List" ).join(", ");
336 text += "<br>";
337
338 return text;
339}
340bool OTodo::hasNotifiers()const {
341 if (!data->notifiers) return false;
342 return !data->notifiers->isEmpty();
343}
344OPimNotifyManager& OTodo::notifiers() {
345 if (!data->notifiers )
346 data->notifiers = new OPimNotifyManager;
347 return (*data->notifiers);
348}
349const OPimNotifyManager& OTodo::notifiers()const{
350 if (!data->notifiers )
351 data->notifiers = new OPimNotifyManager;
352
353 return (*data->notifiers);
354}
355
356bool OTodo::operator<( const OTodo &toDoEvent )const{
357 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
358 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
359 if( hasDueDate() && toDoEvent.hasDueDate() ){
360 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
361 return priority() < toDoEvent.priority();
362 }else{
363 return dueDate() < toDoEvent.dueDate();
364 }
365 }
366 return false;
367}
368bool OTodo::operator<=(const OTodo &toDoEvent )const
369{
370 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
371 if( !hasDueDate() && toDoEvent.hasDueDate() ) return true;
372 if( hasDueDate() && toDoEvent.hasDueDate() ){
373 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
374 return priority() <= toDoEvent.priority();
375 }else{
376 return dueDate() <= toDoEvent.dueDate();
377 }
378 }
379 return true;
380}
381bool OTodo::operator>(const OTodo &toDoEvent )const
382{
383 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return false;
384 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
385 if( hasDueDate() && toDoEvent.hasDueDate() ){
386 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
387 return priority() > toDoEvent.priority();
388 }else{
389 return dueDate() > toDoEvent.dueDate();
390 }
391 }
392 return false;
393}
394bool OTodo::operator>=(const OTodo &toDoEvent )const
395{
396 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
397 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
398 if( hasDueDate() && toDoEvent.hasDueDate() ){
399 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
400 return priority() > toDoEvent.priority();
401 }else{
402 return dueDate() > toDoEvent.dueDate();
403 }
404 }
405 return true;
406}
407bool OTodo::operator==(const OTodo &toDoEvent )const
408{
409 if ( data->priority != toDoEvent.data->priority ) return false;
410 if ( data->priority != toDoEvent.data->prog ) return false;
411 if ( data->isCompleted != toDoEvent.data->isCompleted ) return false;
412 if ( data->hasDate != toDoEvent.data->hasDate ) return false;
413 if ( data->date != toDoEvent.data->date ) return false;
414 if ( data->sum != toDoEvent.data->sum ) return false;
415 if ( data->desc != toDoEvent.data->desc ) return false;
416 if ( data->maintainer != toDoEvent.data->maintainer )
417 return false;
418
419 return OPimRecord::operator==( toDoEvent );
420}
421void OTodo::deref() {
422
423// qWarning("deref in ToDoEvent");
424 if ( data->deref() ) {
425// qWarning("deleting");
426 delete data;
427 data= 0;
428 }
429}
430OTodo &OTodo::operator=(const OTodo &item )
431{
432 if ( this == &item ) return *this;
433
434 OPimRecord::operator=( item );
435 //qWarning("operator= ref ");
436 item.data->ref();
437 deref();
438 data = item.data;
439
440 return *this;
441}
442
443QMap<int, QString> OTodo::toMap() const {
444 QMap<int, QString> map;
445
446 map.insert( Uid, QString::number( uid() ) );
447 map.insert( Category, idsToString( categories() ) );
448 map.insert( HasDate, QString::number( data->hasDate ) );
449 map.insert( Completed, QString::number( data->isCompleted ) );
450 map.insert( Description, data->desc );
451 map.insert( Summary, data->sum );
452 map.insert( Priority, QString::number( data->priority ) );
453 map.insert( DateDay, QString::number( data->date.day() ) );
454 map.insert( DateMonth, QString::number( data->date.month() ) );
455 map.insert( DateYear, QString::number( data->date.year() ) );
456 map.insert( Progress, QString::number( data->prog ) );
457// map.insert( CrossReference, crossToString() );
458 /* FIXME!!! map.insert( State, );
459 map.insert( Recurrence, );
460 map.insert( Reminders, );
461 map.
462 */
463 return map;
464}
465
466/**
467 * change or modify looks at the ref count and either
468 * creates a new QShared Object or it can modify it
469 * right in place
470 */
471void OTodo::changeOrModify() {
472 if ( data->count != 1 ) {
473 qWarning("changeOrModify");
474 data->deref();
475 OTodoData* d2 = new OTodoData();
476 copy(data, d2 );
477 data = d2;
478 }
479}
480// WATCHOUT
481/*
482 * if you add something to the Data struct
483 * be sure to copy it here
484 */
485void OTodo::copy( OTodoData* src, OTodoData* dest ) {
486 dest->date = src->date;
487 dest->isCompleted = src->isCompleted;
488 dest->hasDate = src->hasDate;
489 dest->priority = src->priority;
490 dest->desc = src->desc;
491 dest->sum = src->sum;
492 dest->extra = src->extra;
493 dest->prog = src->prog;
494
495 if (src->state )
496 dest->state = new OPimState( *src->state );
497
498 if (src->recur )
499 dest->recur = new ORecur( *src->recur );
500
501 if (src->maintainer )
502 dest->maintainer = new OPimMaintainer( *src->maintainer )
503 ;
504 dest->start = src->start;
505 dest->completed = src->completed;
506
507 if (src->notifiers )
508 dest->notifiers = new OPimNotifyManager( *src->notifiers );
509}
510QString OTodo::type() const {
511 return QString::fromLatin1("OTodo");
512}
513QString OTodo::recordField(int /*id*/ )const {
514 return QString::null;
515}
516
517int OTodo::rtti(){
518 return OPimResolver::TodoList;
519}
diff --git a/noncore/unsupported/libopie/pim/otodo.h b/noncore/unsupported/libopie/pim/otodo.h
new file mode 100644
index 0000000..6df98b9
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodo.h
@@ -0,0 +1,285 @@
1
2#ifndef OPIE_TODO_EVENT_H
3#define OPIE_TODO_EVENT_H
4
5
6#include <qarray.h>
7#include <qmap.h>
8#include <qregexp.h>
9#include <qstringlist.h>
10#include <qdatetime.h>
11#include <qvaluelist.h>
12
13#include <qpe/recordfields.h>
14#include <qpe/palmtopuidgen.h>
15
16#include <opie/opimrecord.h>
17
18
19class OPimState;
20class ORecur;
21class OPimMaintainer;
22class OPimNotifyManager;
23class OTodo : public OPimRecord {
24public:
25 typedef QValueList<OTodo> ValueList;
26 enum RecordFields {
27 Uid = Qtopia::UID_ID,
28 Category = Qtopia::CATEGORY_ID,
29 HasDate,
30 Completed,
31 Description,
32 Summary,
33 Priority,
34 DateDay,
35 DateMonth,
36 DateYear,
37 Progress,
38 CrossReference,
39 State,
40 Recurrence,
41 Alarms,
42 Reminders,
43 Notifiers,
44 Maintainer,
45 StartDate,
46 CompletedDate
47 };
48 public:
49 // priorities from Very low to very high
50 enum TaskPriority { VeryHigh=1, High, Normal, Low, VeryLow };
51
52 /* Constructs a new ToDoEvent
53 @param completed Is the TodoEvent completed
54 @param priority What is the priority of this ToDoEvent
55 @param category Which category does it belong( uid )
56 @param summary A small summary of the todo
57 @param description What is this ToDoEvent about
58 @param hasDate Does this Event got a deadline
59 @param date what is the deadline?
60 @param uid what is the UUID of this Event
61 **/
62 OTodo( bool completed = false, int priority = Normal,
63 const QStringList &category = QStringList(),
64 const QString &summary = QString::null ,
65 const QString &description = QString::null,
66 ushort progress = 0,
67 bool hasDate = false, QDate date = QDate::currentDate(),
68 int uid = 0 /*empty*/ );
69
70 OTodo( bool completed, int priority,
71 const QArray<int>& category,
72 const QString& summary = QString::null,
73 const QString& description = QString::null,
74 ushort progress = 0,
75 bool hasDate = false, QDate date = QDate::currentDate(),
76 int uid = 0 /* empty */ );
77
78 /** Copy c'tor
79 *
80 */
81 OTodo(const OTodo & );
82
83 /**
84 *destructor
85 */
86 ~OTodo();
87
88 /**
89 * Is this event completed?
90 */
91 bool isCompleted() const;
92
93 /**
94 * Does this Event have a deadline
95 */
96 bool hasDueDate() const;
97 bool hasStartDate()const;
98 bool hasCompletedDate()const;
99
100 /**
101 * What is the priority?
102 */
103 int priority()const ;
104
105 /**
106 * progress as ushort 0, 20, 40, 60, 80 or 100%
107 */
108 ushort progress() const;
109
110 /**
111 * The due Date
112 */
113 QDate dueDate()const;
114
115 /**
116 * When did it start?
117 */
118 QDate startDate()const;
119
120 /**
121 * When was it completed?
122 */
123 QDate completedDate()const;
124
125 /**
126 * does it have a state?
127 */
128 bool hasState()const;
129
130 /**
131 * What is the state of this OTodo?
132 */
133 OPimState state()const;
134
135 /**
136 * has recurrence?
137 */
138 bool hasRecurrence()const;
139
140 /**
141 * the recurrance of this
142 */
143 ORecur recurrence()const;
144
145 /**
146 * does this OTodo have a maintainer?
147 */
148 bool hasMaintainer()const;
149
150 /**
151 * the Maintainer of this OTodo
152 */
153 OPimMaintainer maintainer()const;
154
155 /**
156 * The description of the todo
157 */
158 QString description()const;
159
160 /**
161 * A small summary of the todo
162 */
163 QString summary() const;
164
165 /**
166 * @reimplemented
167 * Return this todoevent in a RichText formatted QString
168 */
169 QString toRichText() const;
170
171 bool hasNotifiers()const;
172 /*
173 * FIXME check if the sharing is still fine!! -zecke
174 * ### CHECK If API is fine
175 */
176 /**
177 * return a reference to our notifiers...
178 */
179 OPimNotifyManager &notifiers();
180
181 /**
182 *
183 */
184 const OPimNotifyManager &notifiers()const;
185
186 /**
187 * reimplementations
188 */
189 QString type()const;
190 QString toShortText()const;
191 QString recordField(int id )const;
192
193 /**
194 * toMap puts all data into the map. int relates
195 * to ToDoEvent RecordFields enum
196 */
197 QMap<int, QString> toMap()const;
198
199 /**
200 * Set if this Todo is completed
201 */
202 void setCompleted(bool completed );
203
204 /**
205 * set if this todo got an end data
206 */
207 void setHasDueDate( bool hasDate );
208 // FIXME we do not have these for start, completed
209 // cause we'll use the isNull() of QDate for figuring
210 // out if it's has a date...
211 // decide what to do here? -zecke
212
213 /**
214 * Set the priority of the Todo
215 */
216 void setPriority(int priority );
217
218 /**
219 * Set the progress.
220 */
221 void setProgress( ushort progress );
222
223 /**
224 * set the end date
225 */
226 void setDueDate( const QDate& date );
227
228 /**
229 * set the start date
230 */
231 void setStartDate( const QDate& date );
232
233 /**
234 * set the completed date
235 */
236 void setCompletedDate( const QDate& date );
237
238 void setRecurrence( const ORecur& );
239
240 void setDescription(const QString& );
241 void setSummary(const QString& );
242
243 /**
244 * set the state of a Todo
245 * @param state State what the todo should take
246 */
247 void setState( const OPimState& state);
248
249 /**
250 * set the Maintainer Mode
251 */
252 void setMaintainer( const OPimMaintainer& );
253
254 bool isOverdue();
255
256
257 virtual bool match( const QRegExp &r )const;
258
259 bool operator<(const OTodo &toDoEvent )const;
260 bool operator<=(const OTodo &toDoEvent )const;
261 bool operator!=(const OTodo &toDoEvent )const;
262 bool operator>(const OTodo &toDoEvent )const;
263 bool operator>=(const OTodo &toDoEvent)const;
264 bool operator==(const OTodo &toDoEvent )const;
265 OTodo &operator=(const OTodo &toDoEvent );
266
267 static int rtti();
268
269 private:
270 class OTodoPrivate;
271 struct OTodoData;
272
273 void deref();
274 inline void changeOrModify();
275 void copy( OTodoData* src, OTodoData* dest );
276 OTodoPrivate *d;
277 OTodoData *data;
278
279};
280inline bool OTodo::operator!=(const OTodo &toDoEvent )const {
281 return !(*this == toDoEvent);
282}
283
284
285#endif
diff --git a/noncore/unsupported/libopie/pim/otodoaccess.cpp b/noncore/unsupported/libopie/pim/otodoaccess.cpp
new file mode 100644
index 0000000..37f6fbc
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodoaccess.cpp
@@ -0,0 +1,62 @@
1#include <qdatetime.h>
2
3#include <qpe/alarmserver.h>
4
5// #include "otodoaccesssql.h"
6#include "otodoaccess.h"
7#include "obackendfactory.h"
8
9OTodoAccess::OTodoAccess( OTodoAccessBackend* end, enum Access )
10 : QObject(), OPimAccessTemplate<OTodo>( end ), m_todoBackEnd( end )
11{
12// if (end == 0l )
13// m_todoBackEnd = new OTodoAccessBackendSQL( QString::null);
14
15 // Zecke: Du musst hier noch für das XML-Backend einen Appnamen übergeben !
16 if (end == 0l )
17 m_todoBackEnd = OBackendFactory<OTodoAccessBackend>::Default ("todo", QString::null);
18
19 setBackEnd( m_todoBackEnd );
20}
21OTodoAccess::~OTodoAccess() {
22// qWarning("~OTodoAccess");
23}
24void OTodoAccess::mergeWith( const QValueList<OTodo>& list ) {
25 QValueList<OTodo>::ConstIterator it;
26 for ( it = list.begin(); it != list.end(); ++it ) {
27 replace( (*it) );
28 }
29}
30OTodoAccess::List OTodoAccess::effectiveToDos( const QDate& start,
31 const QDate& end,
32 bool includeNoDates ) {
33 QArray<int> ints = m_todoBackEnd->effectiveToDos( start, end, includeNoDates );
34
35 List lis( ints, this );
36 return lis;
37}
38OTodoAccess::List OTodoAccess::effectiveToDos( const QDate& start,
39 bool includeNoDates ) {
40 return effectiveToDos( start, QDate::currentDate(),
41 includeNoDates );
42}
43OTodoAccess::List OTodoAccess::overDue() {
44 List lis( m_todoBackEnd->overDue(), this );
45 return lis;
46}
47/* sort order */
48OTodoAccess::List OTodoAccess::sorted( bool ascending, int sort,int filter, int cat ) {
49 QArray<int> ints = m_todoBackEnd->sorted( ascending, sort,
50 filter, cat );
51 OTodoAccess::List list( ints, this );
52 return list;
53}
54void OTodoAccess::removeAllCompleted() {
55 m_todoBackEnd->removeAllCompleted();
56}
57QBitArray OTodoAccess::backendSupport( const QString& ) const{
58 return m_todoBackEnd->supports();
59}
60bool OTodoAccess::backendSupports( int attr, const QString& ar) const{
61 return backendSupport(ar).testBit( attr );
62}
diff --git a/noncore/unsupported/libopie/pim/otodoaccess.h b/noncore/unsupported/libopie/pim/otodoaccess.h
new file mode 100644
index 0000000..916923f
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodoaccess.h
@@ -0,0 +1,105 @@
1#ifndef OPIE_TODO_ACCESS_H
2#define OPIE_TODO_ACCESS_H
3
4#include <qobject.h>
5#include <qvaluelist.h>
6
7#include "otodo.h"
8#include "otodoaccessbackend.h"
9#include "opimaccesstemplate.h"
10
11
12/**
13 * OTodoAccess
14 * the class to get access to
15 * the todolist
16 */
17class OTodoAccess : public QObject, public OPimAccessTemplate<OTodo> {
18 Q_OBJECT
19public:
20 enum SortOrder { Completed = 0,
21 Priority,
22 Description,
23 Deadline };
24 enum SortFilter{ Category =1,
25 OnlyOverDue= 2,
26 DoNotShowCompleted =4 };
27 /**
28 * if you use 0l
29 * the default resource will be
30 * picked up
31 */
32 OTodoAccess( OTodoAccessBackend* = 0l, enum Access acc = Random );
33 ~OTodoAccess();
34
35
36 /* our functions here */
37 /**
38 * include todos from start to end
39 * includeNoDates whether or not to include
40 * events with no dates
41 */
42 List effectiveToDos( const QDate& start,
43 const QDate& end,
44 bool includeNoDates = true );
45
46 /**
47 * start
48 * end date taken from the currentDate()
49 */
50 List effectiveToDos( const QDate& start,
51 bool includeNoDates = true );
52
53
54 /**
55 * return overdue OTodos
56 */
57 List overDue();
58
59 /**
60 *
61 */
62 List sorted( bool ascending, int sortOrder, int sortFilter, int cat );
63
64 /**
65 * merge a list of OTodos into
66 * the resource
67 */
68 void mergeWith( const QValueList<OTodo>& );
69
70 /**
71 * delete all already completed items
72 */
73 void removeAllCompleted();
74
75 /**
76 * request information about what a backend supports.
77 * Supports in the sense of beeing able to store.
78 * This is related to the enum in OTodo
79 *
80 * @param backend Will be used in the future when we support multiple backend
81 */
82 QBitArray backendSupport( const QString& backend = QString::null )const;
83
84 /**
85 * see above but for a specefic attribute. This method was added for convience
86 * @param attr The attribute to be queried for
87 * @param backend Will be used in the future when we support multiple backends
88 */
89 bool backendSupports( int attr, const QString& backend = QString::null )const;
90signals:
91 /**
92 * if the OTodoAccess was changed
93 */
94 void changed( const OTodoAccess* );
95 void changed( const OTodoAccess*, int uid );
96 void added( const OTodoAccess*, int uid );
97 void removed( const OTodoAccess*, int uid );
98private:
99 int m_cat;
100 OTodoAccessBackend* m_todoBackEnd;
101 class OTodoAccessPrivate;
102 OTodoAccessPrivate* d;
103};
104
105#endif
diff --git a/noncore/unsupported/libopie/pim/otodoaccessbackend.cpp b/noncore/unsupported/libopie/pim/otodoaccessbackend.cpp
new file mode 100644
index 0000000..baaeecc
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodoaccessbackend.cpp
@@ -0,0 +1,10 @@
1
2#include "otodoaccessbackend.h"
3
4OTodoAccessBackend::OTodoAccessBackend()
5 : OPimAccessBackend<OTodo>()
6{
7}
8OTodoAccessBackend::~OTodoAccessBackend() {
9
10}
diff --git a/noncore/unsupported/libopie/pim/otodoaccessbackend.h b/noncore/unsupported/libopie/pim/otodoaccessbackend.h
new file mode 100644
index 0000000..6be95bc
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodoaccessbackend.h
@@ -0,0 +1,28 @@
1#ifndef OPIE_TODO_ACCESS_BACKEND_H
2#define OPIE_TODO_ACCESS_BACKEND_H
3
4#include <qbitarray.h>
5
6#include "otodo.h"
7#include "opimaccessbackend.h"
8
9class OTodoAccessBackend : public OPimAccessBackend<OTodo> {
10public:
11 OTodoAccessBackend();
12 ~OTodoAccessBackend();
13 virtual QArray<int> effectiveToDos( const QDate& start,
14 const QDate& end,
15 bool includeNoDates ) = 0;
16 virtual QArray<int> overDue() = 0;
17 virtual QArray<int> sorted( bool asc, int sortOrder, int sortFilter,
18 int cat ) = 0;
19 virtual void removeAllCompleted() = 0;
20 virtual QBitArray supports()const = 0;
21
22private:
23 class Private;
24 Private *d;
25
26};
27
28#endif
diff --git a/noncore/unsupported/libopie/pim/otodoaccesssql.cpp b/noncore/unsupported/libopie/pim/otodoaccesssql.cpp
new file mode 100644
index 0000000..fd01a42
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodoaccesssql.cpp
@@ -0,0 +1,694 @@
1
2#include <qdatetime.h>
3
4#include <qpe/global.h>
5
6#include <opie2/osqldriver.h>
7#include <opie2/osqlresult.h>
8#include <opie2/osqlmanager.h>
9#include <opie2/osqlquery.h>
10
11#include "otodoaccesssql.h"
12#include "opimstate.h"
13#include "opimnotifymanager.h"
14#include "orecur.h"
15
16using namespace Opie::DB;
17/*
18 * first some query
19 * CREATE query
20 * LOAD query
21 * INSERT
22 * REMOVE
23 * CLEAR
24 */
25namespace {
26 /**
27 * CreateQuery for the Todolist Table
28 */
29 class CreateQuery : public OSQLQuery {
30 public:
31 CreateQuery();
32 ~CreateQuery();
33 QString query()const;
34 };
35
36 /**
37 * LoadQuery
38 * this one queries for all uids
39 */
40 class LoadQuery : public OSQLQuery {
41 public:
42 LoadQuery();
43 ~LoadQuery();
44 QString query()const;
45 };
46
47 /**
48 * inserts/adds a OTodo to the table
49 */
50 class InsertQuery : public OSQLQuery {
51 public:
52 InsertQuery(const OTodo& );
53 ~InsertQuery();
54 QString query()const;
55 private:
56 OTodo m_todo;
57 };
58
59 /**
60 * removes one from the table
61 */
62 class RemoveQuery : public OSQLQuery {
63 public:
64 RemoveQuery(int uid );
65 ~RemoveQuery();
66 QString query()const;
67 private:
68 int m_uid;
69 };
70
71 /**
72 * Clears (delete) a Table
73 */
74 class ClearQuery : public OSQLQuery {
75 public:
76 ClearQuery();
77 ~ClearQuery();
78 QString query()const;
79
80 };
81
82 /**
83 * a find query
84 */
85 class FindQuery : public OSQLQuery {
86 public:
87 FindQuery(int uid);
88 FindQuery(const QArray<int>& );
89 ~FindQuery();
90 QString query()const;
91 private:
92 QString single()const;
93 QString multi()const;
94 QArray<int> m_uids;
95 int m_uid;
96 };
97
98 /**
99 * overdue query
100 */
101 class OverDueQuery : public OSQLQuery {
102 public:
103 OverDueQuery();
104 ~OverDueQuery();
105 QString query()const;
106 };
107 class EffQuery : public OSQLQuery {
108 public:
109 EffQuery( const QDate&, const QDate&, bool inc );
110 ~EffQuery();
111 QString query()const;
112 private:
113 QString with()const;
114 QString out()const;
115 QDate m_start;
116 QDate m_end;
117 bool m_inc :1;
118 };
119
120
121 CreateQuery::CreateQuery() : OSQLQuery() {}
122 CreateQuery::~CreateQuery() {}
123 QString CreateQuery::query()const {
124 QString qu;
125 qu += "create table todolist( uid PRIMARY KEY, categories, completed, ";
126 qu += "description, summary, priority, DueDate, progress , state, ";
127 // This is the recurrance-stuff .. Exceptions are currently not supported (see ORecur.cpp) ! (eilers)
128 qu += "RType, RWeekdays, RPosition, RFreq, RHasEndDate, EndDate, Created, Exceptions, ";
129 qu += "reminders, alarms, maintainer, startdate, completeddate);";
130 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );";
131 return qu;
132 }
133
134 LoadQuery::LoadQuery() : OSQLQuery() {}
135 LoadQuery::~LoadQuery() {}
136 QString LoadQuery::query()const {
137 QString qu;
138 // We do not need "distinct" here. The primary key is always unique..
139 //qu += "select distinct uid from todolist";
140 qu += "select uid from todolist";
141
142 return qu;
143 }
144
145 InsertQuery::InsertQuery( const OTodo& todo )
146 : OSQLQuery(), m_todo( todo ) {
147 }
148 InsertQuery::~InsertQuery() {
149 }
150 /*
151 * converts from a OTodo to a query
152 * we leave out X-Ref + Alarms
153 */
154 QString InsertQuery::query()const{
155
156 int year, month, day;
157 year = month = day = 0;
158 if (m_todo.hasDueDate() ) {
159 QDate date = m_todo.dueDate();
160 year = date.year();
161 month = date.month();
162 day = date.day();
163 }
164 int sYear = 0, sMonth = 0, sDay = 0;
165 if( m_todo.hasStartDate() ){
166 QDate sDate = m_todo.startDate();
167 sYear = sDate.year();
168 sMonth= sDate.month();
169 sDay = sDate.day();
170 }
171
172 int eYear = 0, eMonth = 0, eDay = 0;
173 if( m_todo.hasCompletedDate() ){
174 QDate eDate = m_todo.completedDate();
175 eYear = eDate.year();
176 eMonth= eDate.month();
177 eDay = eDate.day();
178 }
179 QString qu;
180 QMap<int, QString> recMap = m_todo.recurrence().toMap();
181 qu = "insert into todolist VALUES("
182 + QString::number( m_todo.uid() ) + ","
183 + "'" + m_todo.idsToString( m_todo.categories() ) + "'" + ","
184 + QString::number( m_todo.isCompleted() ) + ","
185 + "'" + m_todo.description() + "'" + ","
186 + "'" + m_todo.summary() + "'" + ","
187 + QString::number(m_todo.priority() ) + ","
188 + "'" + QString::number(year) + "-"
189 + QString::number(month)
190 + "-" + QString::number( day ) + "'" + ","
191 + QString::number( m_todo.progress() ) + ","
192 + QString::number( m_todo.state().state() ) + ","
193 + "'" + recMap[ ORecur::RType ] + "'" + ","
194 + "'" + recMap[ ORecur::RWeekdays ] + "'" + ","
195 + "'" + recMap[ ORecur::RPosition ] + "'" + ","
196 + "'" + recMap[ ORecur::RFreq ] + "'" + ","
197 + "'" + recMap[ ORecur::RHasEndDate ] + "'" + ","
198 + "'" + recMap[ ORecur::EndDate ] + "'" + ","
199 + "'" + recMap[ ORecur::Created ] + "'" + ","
200 + "'" + recMap[ ORecur::Exceptions ] + "'" + ",";
201
202 if ( m_todo.hasNotifiers() ) {
203 OPimNotifyManager manager = m_todo.notifiers();
204 qu += "'" + manager.remindersToString() + "'" + ","
205 + "'" + manager.alarmsToString() + "'" + ",";
206 }
207 else{
208 qu += QString( "''" ) + ","
209 + "''" + ",";
210 }
211
212 qu += QString( "''" ) + QString( "," ) // Maintainers (cur. not supported !)
213 + "'" + QString::number(sYear) + "-"
214 + QString::number(sMonth)
215 + "-" + QString::number(sDay) + "'" + ","
216 + "'" + QString::number(eYear) + "-"
217 + QString::number(eMonth)
218 + "-"+QString::number(eDay) + "'"
219 + ")";
220
221 qWarning("add %s", qu.latin1() );
222 return qu;
223 }
224
225 RemoveQuery::RemoveQuery(int uid )
226 : OSQLQuery(), m_uid( uid ) {}
227 RemoveQuery::~RemoveQuery() {}
228 QString RemoveQuery::query()const {
229 QString qu = "DELETE from todolist where uid = " + QString::number(m_uid);
230 return qu;
231 }
232
233
234 ClearQuery::ClearQuery()
235 : OSQLQuery() {}
236 ClearQuery::~ClearQuery() {}
237 QString ClearQuery::query()const {
238 QString qu = "drop table todolist";
239 return qu;
240 }
241 FindQuery::FindQuery(int uid)
242 : OSQLQuery(), m_uid(uid ) {
243 }
244 FindQuery::FindQuery(const QArray<int>& ints)
245 : OSQLQuery(), m_uids(ints){
246 }
247 FindQuery::~FindQuery() {
248 }
249 QString FindQuery::query()const{
250 if (m_uids.count() == 0 )
251 return single();
252 else
253 return multi();
254 }
255 QString FindQuery::single()const{
256 QString qu = "select * from todolist where uid = " + QString::number(m_uid);
257 return qu;
258 }
259 QString FindQuery::multi()const {
260 QString qu = "select * from todolist where ";
261 for (uint i = 0; i < m_uids.count(); i++ ) {
262 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
263 }
264 qu.remove( qu.length()-2, 2 );
265 return qu;
266 }
267
268 OverDueQuery::OverDueQuery(): OSQLQuery() {}
269 OverDueQuery::~OverDueQuery() {}
270 QString OverDueQuery::query()const {
271 QDate date = QDate::currentDate();
272 QString str;
273 str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() );
274
275 return str;
276 }
277
278
279 EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc )
280 : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {}
281 EffQuery::~EffQuery() {}
282 QString EffQuery::query()const {
283 return m_inc ? with() : out();
284 }
285 QString EffQuery::with()const {
286 QString str;
287 str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ")
288 .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() )
289 .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() );
290 return str;
291 }
292 QString EffQuery::out()const {
293 QString str;
294 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'")
295 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() )
296 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() );
297
298 return str;
299 }
300};
301
302OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file )
303 : OTodoAccessBackend(), m_dict(15), m_driver(NULL), m_dirty(true)
304{
305 QString fi = file;
306 if ( fi.isEmpty() )
307 fi = Global::applicationFileName( "todolist", "todolist.db" );
308 OSQLManager man;
309 m_driver = man.standard();
310 m_driver->setUrl(fi);
311 // fillDict();
312}
313
314OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){
315 if( m_driver )
316 delete m_driver;
317}
318
319bool OTodoAccessBackendSQL::load(){
320 if (!m_driver->open() )
321 return false;
322
323 CreateQuery creat;
324 OSQLResult res = m_driver->query(&creat );
325
326 m_dirty = true;
327 return true;
328}
329bool OTodoAccessBackendSQL::reload(){
330 return load();
331}
332
333bool OTodoAccessBackendSQL::save(){
334 return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
335}
336QArray<int> OTodoAccessBackendSQL::allRecords()const {
337 if (m_dirty )
338 update();
339
340 return m_uids;
341}
342QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){
343 QArray<int> ints(0);
344 return ints;
345}
346OTodo OTodoAccessBackendSQL::find(int uid ) const{
347 FindQuery query( uid );
348 return todo( m_driver->query(&query) );
349
350}
351OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints,
352 uint cur, Frontend::CacheDirection dir ) const{
353 uint CACHE = readAhead();
354 qWarning("searching for %d", uid );
355 QArray<int> search( CACHE );
356 uint size =0;
357 OTodo to;
358
359 // we try to cache CACHE items
360 switch( dir ) {
361 /* forward */
362 case 0: // FIXME: Not a good style to use magic numbers here (eilers)
363 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) {
364 qWarning("size %d %d", size, ints[i] );
365 search[size] = ints[i];
366 size++;
367 }
368 break;
369 /* reverse */
370 case 1: // FIXME: Not a good style to use magic numbers here (eilers)
371 for (uint i = cur; i != 0 && size < CACHE; i-- ) {
372 search[size] = ints[i];
373 size++;
374 }
375 break;
376 }
377 search.resize( size );
378 FindQuery query( search );
379 OSQLResult res = m_driver->query( &query );
380 if ( res.state() != OSQLResult::Success )
381 return to;
382
383 return todo( res );
384}
385void OTodoAccessBackendSQL::clear() {
386 ClearQuery cle;
387 OSQLResult res = m_driver->query( &cle );
388 CreateQuery qu;
389 res = m_driver->query(&qu);
390}
391bool OTodoAccessBackendSQL::add( const OTodo& t) {
392 InsertQuery ins( t );
393 OSQLResult res = m_driver->query( &ins );
394
395 if ( res.state() == OSQLResult::Failure )
396 return false;
397 int c = m_uids.count();
398 m_uids.resize( c+1 );
399 m_uids[c] = t.uid();
400
401 return true;
402}
403bool OTodoAccessBackendSQL::remove( int uid ) {
404 RemoveQuery rem( uid );
405 OSQLResult res = m_driver->query(&rem );
406
407 if ( res.state() == OSQLResult::Failure )
408 return false;
409
410 m_dirty = true;
411 return true;
412}
413/*
414 * FIXME better set query
415 * but we need the cache for that
416 * now we remove
417 */
418bool OTodoAccessBackendSQL::replace( const OTodo& t) {
419 remove( t.uid() );
420 bool b= add(t);
421 m_dirty = false; // we changed some stuff but the UID stayed the same
422 return b;
423}
424QArray<int> OTodoAccessBackendSQL::overDue() {
425 OverDueQuery qu;
426 return uids( m_driver->query(&qu ) );
427}
428QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s,
429 const QDate& t,
430 bool u) {
431 EffQuery ef(s, t, u );
432 return uids (m_driver->query(&ef) );
433}
434/*
435 *
436 */
437QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder,
438 int sortFilter, int cat ) {
439 qWarning("sorted %d, %d", asc, sortOrder );
440 QString query;
441 query = "select uid from todolist WHERE ";
442
443 /*
444 * Sort Filter stuff
445 * not that straight forward
446 * FIXME: Replace magic numbers
447 *
448 */
449 /* Category */
450 if ( sortFilter & 1 ) {
451 QString str;
452 if (cat != 0 ) str = QString::number( cat );
453 query += " categories like '%" +str+"%' AND";
454 }
455 /* Show only overdue */
456 if ( sortFilter & 2 ) {
457 QDate date = QDate::currentDate();
458 QString due;
459 QString base;
460 base = QString("DueDate <= '%1-%2-%3' AND completed = 0").arg( date.year() ).arg( date.month() ).arg( date.day() );
461 query += " " + base + " AND";
462 }
463 /* not show completed */
464 if ( sortFilter & 4 ) {
465 query += " completed = 0 AND";
466 }else{
467 query += " ( completed = 1 OR completed = 0) AND";
468 }
469 /* srtip the end */
470 query = query.remove( query.length()-3, 3 );
471
472
473 /*
474 * sort order stuff
475 * quite straight forward
476 */
477 query += "ORDER BY ";
478 switch( sortOrder ) {
479 /* completed */
480 case 0:
481 query += "completed";
482 break;
483 case 1:
484 query += "priority";
485 break;
486 case 2:
487 query += "summary";
488 break;
489 case 3:
490 query += "DueDate";
491 break;
492 }
493
494 if ( !asc ) {
495 qWarning("not ascending!");
496 query += " DESC";
497 }
498
499 qWarning( query );
500 OSQLRawQuery raw(query );
501 return uids( m_driver->query(&raw) );
502}
503bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{
504 if ( str == "0-0-0" )
505 return false;
506 else{
507 int day, year, month;
508 QStringList list = QStringList::split("-", str );
509 year = list[0].toInt();
510 month = list[1].toInt();
511 day = list[2].toInt();
512 da.setYMD( year, month, day );
513 return true;
514 }
515}
516OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{
517 if ( res.state() == OSQLResult::Failure ) {
518 OTodo to;
519 return to;
520 }
521
522 OSQLResultItem::ValueList list = res.results();
523 OSQLResultItem::ValueList::Iterator it = list.begin();
524 qWarning("todo1");
525 OTodo to = todo( (*it) );
526 cache( to );
527 ++it;
528
529 for ( ; it != list.end(); ++it ) {
530 qWarning("caching");
531 cache( todo( (*it) ) );
532 }
533 return to;
534}
535OTodo OTodoAccessBackendSQL::todo( OSQLResultItem& item )const {
536 qWarning("todo");
537 bool hasDueDate = false; QDate dueDate = QDate::currentDate();
538 hasDueDate = date( dueDate, item.data("DueDate") );
539 QStringList cats = QStringList::split(";", item.data("categories") );
540
541 qWarning("Item is completed: %d", item.data("completed").toInt() );
542
543 OTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(),
544 cats, item.data("summary"), item.data("description"),
545 item.data("progress").toUShort(), hasDueDate, dueDate,
546 item.data("uid").toInt() );
547
548 bool isOk;
549 int prioInt = QString( item.data("priority") ).toInt( &isOk );
550 if ( isOk )
551 to.setPriority( prioInt );
552
553 bool hasStartDate = false; QDate startDate = QDate::currentDate();
554 hasStartDate = date( startDate, item.data("startdate") );
555 bool hasCompletedDate = false; QDate completedDate = QDate::currentDate();
556 hasCompletedDate = date( completedDate, item.data("completeddate") );
557
558 if ( hasStartDate )
559 to.setStartDate( startDate );
560 if ( hasCompletedDate )
561 to.setCompletedDate( completedDate );
562
563 OPimNotifyManager& manager = to.notifiers();
564 manager.alarmsFromString( item.data("alarms") );
565 manager.remindersFromString( item.data("reminders") );
566
567 OPimState pimState;
568 pimState.setState( QString( item.data("state") ).toInt() );
569 to.setState( pimState );
570
571 QMap<int, QString> recMap;
572 recMap.insert( ORecur::RType , item.data("RType") );
573 recMap.insert( ORecur::RWeekdays , item.data("RWeekdays") );
574 recMap.insert( ORecur::RPosition , item.data("RPosition") );
575 recMap.insert( ORecur::RFreq , item.data("RFreq") );
576 recMap.insert( ORecur::RHasEndDate, item.data("RHasEndDate") );
577 recMap.insert( ORecur::EndDate , item.data("EndDate") );
578 recMap.insert( ORecur::Created , item.data("Created") );
579 recMap.insert( ORecur::Exceptions , item.data("Exceptions") );
580
581 ORecur recur;
582 recur.fromMap( recMap );
583 to.setRecurrence( recur );
584
585 return to;
586}
587OTodo OTodoAccessBackendSQL::todo( int uid )const {
588 FindQuery find( uid );
589 return todo( m_driver->query(&find) );
590}
591/*
592 * update the dict
593 */
594void OTodoAccessBackendSQL::fillDict() {
595 /* initialize dict */
596 /*
597 * UPDATE dict if you change anything!!!
598 * FIXME: Isn't this dict obsolete ? (eilers)
599 */
600 m_dict.setAutoDelete( TRUE );
601 m_dict.insert("Categories" , new int(OTodo::Category) );
602 m_dict.insert("Uid" , new int(OTodo::Uid) );
603 m_dict.insert("HasDate" , new int(OTodo::HasDate) );
604 m_dict.insert("Completed" , new int(OTodo::Completed) );
605 m_dict.insert("Description" , new int(OTodo::Description) );
606 m_dict.insert("Summary" , new int(OTodo::Summary) );
607 m_dict.insert("Priority" , new int(OTodo::Priority) );
608 m_dict.insert("DateDay" , new int(OTodo::DateDay) );
609 m_dict.insert("DateMonth" , new int(OTodo::DateMonth) );
610 m_dict.insert("DateYear" , new int(OTodo::DateYear) );
611 m_dict.insert("Progress" , new int(OTodo::Progress) );
612 m_dict.insert("Completed", new int(OTodo::Completed) ); // Why twice ? (eilers)
613 m_dict.insert("CrossReference", new int(OTodo::CrossReference) );
614// m_dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); // old stuff (eilers)
615// m_dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); // old stuff (eilers)
616}
617/*
618 * need to be const so let's fool the
619 * compiler :(
620 */
621void OTodoAccessBackendSQL::update()const {
622 ((OTodoAccessBackendSQL*)this)->m_dirty = false;
623 LoadQuery lo;
624 OSQLResult res = m_driver->query(&lo);
625 if ( res.state() != OSQLResult::Success )
626 return;
627
628 ((OTodoAccessBackendSQL*)this)->m_uids = uids( res );
629}
630QArray<int> OTodoAccessBackendSQL::uids( const OSQLResult& res) const{
631
632 OSQLResultItem::ValueList list = res.results();
633 OSQLResultItem::ValueList::Iterator it;
634 QArray<int> ints(list.count() );
635 qWarning(" count = %d", list.count() );
636
637 int i = 0;
638 for (it = list.begin(); it != list.end(); ++it ) {
639 ints[i] = (*it).data("uid").toInt();
640 i++;
641 }
642 return ints;
643}
644
645QArray<int> OTodoAccessBackendSQL::matchRegexp( const QRegExp &r ) const
646{
647
648#warning OTodoAccessBackendSQL::matchRegexp() not implemented !!
649
650#if 0
651
652 Copied from xml-backend by not adapted to sql (eilers)
653
654 QArray<int> m_currentQuery( m_events.count() );
655 uint arraycounter = 0;
656
657
658
659 QMap<int, OTodo>::ConstIterator it;
660 for (it = m_events.begin(); it != m_events.end(); ++it ) {
661 if ( it.data().match( r ) )
662 m_currentQuery[arraycounter++] = it.data().uid();
663
664 }
665 // Shrink to fit..
666 m_currentQuery.resize(arraycounter);
667
668 return m_currentQuery;
669#endif
670 QArray<int> empty;
671 return empty;
672}
673QBitArray OTodoAccessBackendSQL::supports()const {
674
675 return sup();
676}
677
678QBitArray OTodoAccessBackendSQL::sup() const{
679
680 QBitArray ar( OTodo::CompletedDate + 1 );
681 ar.fill( true );
682 ar[OTodo::CrossReference] = false;
683 ar[OTodo::State ] = false;
684 ar[OTodo::Reminders] = false;
685 ar[OTodo::Notifiers] = false;
686 ar[OTodo::Maintainer] = false;
687
688 return ar;
689}
690
691void OTodoAccessBackendSQL::removeAllCompleted(){
692#warning OTodoAccessBackendSQL::removeAllCompleted() not implemented !!
693
694}
diff --git a/noncore/unsupported/libopie/pim/otodoaccesssql.h b/noncore/unsupported/libopie/pim/otodoaccesssql.h
new file mode 100644
index 0000000..72214de
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodoaccesssql.h
@@ -0,0 +1,61 @@
1#ifndef OPIE_PIM_ACCESS_SQL_H
2#define OPIE_PIM_ACCESS_SQL_H
3
4#include <qasciidict.h>
5
6#include "otodoaccessbackend.h"
7
8namespace Opie{
9namespace DB {
10class OSQLDriver;
11class OSQLResult;
12class OSQLResultItem;
13}
14}
15
16class OTodoAccessBackendSQL : public OTodoAccessBackend {
17public:
18 OTodoAccessBackendSQL( const QString& file );
19 ~OTodoAccessBackendSQL();
20
21 bool load();
22 bool reload();
23 bool save();
24 QArray<int> allRecords()const;
25
26 QArray<int> queryByExample( const OTodo& t, int settings, const QDateTime& d = QDateTime() );
27 OTodo find(int uid)const;
28 OTodo find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
29 void clear();
30 bool add( const OTodo& t );
31 bool remove( int uid );
32 bool replace( const OTodo& t );
33
34 QArray<int> overDue();
35 QArray<int> effectiveToDos( const QDate& start,
36 const QDate& end, bool includeNoDates );
37 QArray<int> sorted(bool asc, int sortOrder, int sortFilter, int cat );
38
39 QBitArray supports()const;
40 QArray<int> matchRegexp( const QRegExp &r ) const;
41 void removeAllCompleted();
42
43
44private:
45 void update()const;
46 void fillDict();
47 inline bool date( QDate& date, const QString& )const;
48 inline OTodo todo( const Opie::DB::OSQLResult& )const;
49 inline OTodo todo( Opie::DB::OSQLResultItem& )const;
50 inline QArray<int> uids( const Opie::DB::OSQLResult& )const;
51 OTodo todo( int uid )const;
52 QBitArray sup() const;
53
54 QAsciiDict<int> m_dict;
55 Opie::DB::OSQLDriver* m_driver;
56 QArray<int> m_uids;
57 bool m_dirty : 1;
58};
59
60
61#endif
diff --git a/noncore/unsupported/libopie/pim/otodoaccessvcal.cpp b/noncore/unsupported/libopie/pim/otodoaccessvcal.cpp
new file mode 100644
index 0000000..6415952
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodoaccessvcal.cpp
@@ -0,0 +1,249 @@
1#include <qfile.h>
2
3#include <qtopia/private/vobject_p.h>
4#include <qtopia/timeconversion.h>
5#include <qtopia/private/qfiledirect_p.h>
6
7#include "otodoaccessvcal.h"
8
9namespace {
10 static OTodo eventByVObj( VObject *obj ){
11 OTodo event;
12 VObject *ob;
13 QCString name;
14 // no uid, attendees, ... and no fun
15 // description
16 if( ( ob = isAPropertyOf( obj, VCDescriptionProp )) != 0 ){
17 name = vObjectStringZValue( ob );
18#if 0
19 event.setDescription( name );
20#else
21 event.setSummary( name );
22#endif
23 }
24 // summary
25 if ( ( ob = isAPropertyOf( obj, VCSummaryProp ) ) != 0 ) {
26 name = vObjectStringZValue( ob );
27#if 0
28 event.setSummary( name );
29#else
30 event.setDescription( name );
31#endif
32 }
33 // completed
34 if( ( ob = isAPropertyOf( obj, VCStatusProp )) != 0 ){
35 name = vObjectStringZValue( ob );
36 if( name == "COMPLETED" ){
37 event.setCompleted( true );
38 }else{
39 event.setCompleted( false );
40 }
41 }else
42 event.setCompleted( false );
43 // priority
44 if ((ob = isAPropertyOf(obj, VCPriorityProp))) {
45 name = vObjectStringZValue( ob );
46 bool ok;
47 event.setPriority(name.toInt(&ok) );
48 }
49 //due date
50 if((ob = isAPropertyOf(obj, VCDueProp)) ){
51 event.setHasDueDate( true );
52 name = vObjectStringZValue( ob );
53 event.setDueDate( TimeConversion::fromISO8601( name).date() );
54 }
55 // categories
56 if((ob = isAPropertyOf( obj, VCCategoriesProp )) != 0 ){
57 name = vObjectStringZValue( ob );
58 qWarning("Categories:%s", name.data() );
59 }
60
61 event.setUid( 1 );
62 return event;
63 };
64 static VObject *vobjByEvent( const OTodo &event ) {
65 VObject *task = newVObject( VCTodoProp );
66 if( task == 0 )
67 return 0l;
68
69 if( event.hasDueDate() ) {
70 QTime time(0, 0, 0);
71 QDateTime date(event.dueDate(), time );
72 addPropValue( task, VCDueProp,
73 TimeConversion::toISO8601( date ) );
74 }
75
76 if( event.isCompleted() )
77 addPropValue( task, VCStatusProp, "COMPLETED");
78
79 QString string = QString::number(event.priority() );
80 addPropValue( task, VCPriorityProp, string.local8Bit() );
81
82 addPropValue( task, VCCategoriesProp,
83 event.idsToString( event.categories() ).local8Bit() );
84
85#if 0
86
87 // There seems a misrepresentation between summary in otodoevent
88 // and summary in vcard.
89 // The same with description..
90 // Description is summary and vice versa.. Argh.. (eilers)
91
92
93 addPropValue( task, VCDescriptionProp,
94 event.description().local8Bit() );
95
96 addPropValue( task, VCSummaryProp,
97 event.summary().local8Bit() );
98
99#else
100 addPropValue( task, VCDescriptionProp,
101 event.summary().local8Bit() );
102
103 addPropValue( task, VCSummaryProp,
104 event.description().local8Bit() );
105#endif
106 return task;
107};
108}
109
110OTodoAccessVCal::OTodoAccessVCal( const QString& path )
111 : m_dirty(false), m_file( path )
112{
113}
114OTodoAccessVCal::~OTodoAccessVCal() {
115}
116bool OTodoAccessVCal::load() {
117 m_map.clear();
118 m_dirty = false;
119
120 VObject* vcal = 0l;
121 vcal = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
122 if (!vcal )
123 return false;
124
125 // Iterate over the list
126 VObjectIterator it;
127 VObject* vobj;
128
129 initPropIterator(&it, vcal);
130
131 while( moreIteration( &it ) ) {
132 vobj = ::nextVObject( &it );
133 QCString name = ::vObjectName( vobj );
134 if( name == VCTodoProp ){
135 OTodo to = eventByVObj( vobj );
136 m_map.insert( to.uid(), to );
137 }
138 }
139
140 // Should I do a delete vcal?
141
142 return true;
143}
144bool OTodoAccessVCal::reload() {
145 return load();
146}
147bool OTodoAccessVCal::save() {
148 if (!m_dirty )
149 return true;
150
151 QFileDirect file( m_file );
152 if (!file.open(IO_WriteOnly ) )
153 return false;
154
155 VObject *obj;
156 obj = newVObject( VCCalProp );
157 addPropValue( obj, VCVersionProp, "1.0" );
158 VObject *vo;
159 for(QMap<int, OTodo>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
160 vo = vobjByEvent( it.data() );
161 addVObjectProp(obj, vo );
162 }
163 writeVObject( file.directHandle(), obj );
164 cleanVObject( obj );
165 cleanStrTbl();
166
167 m_dirty = false;
168 return true;
169}
170void OTodoAccessVCal::clear() {
171 m_map.clear();
172 m_dirty = true;
173}
174bool OTodoAccessVCal::add( const OTodo& to ) {
175 m_map.insert( to.uid(), to );
176 m_dirty = true;
177 return true;
178}
179bool OTodoAccessVCal::remove( int uid ) {
180 m_map.remove( uid );
181 m_dirty = true;
182 return true;
183}
184void OTodoAccessVCal::removeAllCompleted() {
185 for ( QMap<int, OTodo>::Iterator it = m_map.begin(); it != m_map.end(); ++it ) {
186 if ( (*it).isCompleted() )
187 m_map.remove( it );
188 }
189}
190bool OTodoAccessVCal::replace( const OTodo& to ) {
191 m_map.replace( to.uid(), to );
192 m_dirty = true;
193 return true;
194}
195OTodo OTodoAccessVCal::find(int uid )const {
196 return m_map[uid];
197}
198QArray<int> OTodoAccessVCal::sorted( bool, int, int, int ) {
199 QArray<int> ar(0);
200 return ar;
201}
202QArray<int> OTodoAccessVCal::allRecords()const {
203 QArray<int> ar( m_map.count() );
204 QMap<int, OTodo>::ConstIterator it;
205 int i = 0;
206 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
207 ar[i] = it.key();
208 i++;
209 }
210 return ar;
211}
212QArray<int> OTodoAccessVCal::matchRegexp(const QRegExp& /* r */)const {
213 QArray<int> ar(0);
214 return ar;
215}
216QArray<int> OTodoAccessVCal::queryByExample( const OTodo&, int, const QDateTime& ) {
217 QArray<int> ar(0);
218 return ar;
219}
220QArray<int> OTodoAccessVCal::effectiveToDos( const QDate& ,
221 const QDate& ,
222 bool ) {
223 QArray<int> ar(0);
224 return ar;
225}
226QArray<int> OTodoAccessVCal::overDue() {
227 QArray<int> ar(0);
228 return ar;
229}
230QBitArray OTodoAccessVCal::supports()const {
231 static QBitArray ar = sup();
232
233 return ar;
234}
235QBitArray OTodoAccessVCal::sup() {
236 QBitArray ar ( OTodo::CompletedDate +1 );
237 ar.fill( true );
238
239 ar[OTodo::CrossReference] = false;
240 ar[OTodo::State ] = false;
241 ar[OTodo::Reminders] = false;
242 ar[OTodo::Notifiers] = false;
243 ar[OTodo::Maintainer] = false;
244 ar[OTodo::Progress] = false;
245 ar[OTodo::Alarms ] = false;
246 ar[OTodo::Recurrence] = false;
247
248 return ar;
249}
diff --git a/noncore/unsupported/libopie/pim/otodoaccessvcal.h b/noncore/unsupported/libopie/pim/otodoaccessvcal.h
new file mode 100644
index 0000000..2b17147
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodoaccessvcal.h
@@ -0,0 +1,40 @@
1#ifndef OPIE_OTODO_ACCESS_VCAL_H
2#define OPIE_OTODO_ACCESS_VCAL_H
3
4#include "otodoaccessbackend.h"
5
6class OTodoAccessVCal : public OTodoAccessBackend {
7public:
8 OTodoAccessVCal(const QString& );
9 ~OTodoAccessVCal();
10
11 bool load();
12 bool reload();
13 bool save();
14
15 QArray<int> allRecords()const;
16 QArray<int> matchRegexp(const QRegExp &r) const;
17 QArray<int> queryByExample( const OTodo& t, int sort, const QDateTime& d = QDateTime() );
18 QArray<int> effectiveToDos( const QDate& start,
19 const QDate& end,
20 bool includeNoDates );
21 QArray<int> overDue();
22 QArray<int> sorted( bool asc, int sortOrder, int sortFilter,
23 int cat );
24 OTodo find(int uid)const;
25 void clear();
26 bool add( const OTodo& );
27 bool remove( int uid );
28 bool replace( const OTodo& );
29
30 void removeAllCompleted();
31 virtual QBitArray supports()const;
32
33private:
34 static QBitArray sup();
35 bool m_dirty : 1;
36 QString m_file;
37 QMap<int, OTodo> m_map;
38};
39
40#endif
diff --git a/noncore/unsupported/libopie/pim/otodoaccessxml.cpp b/noncore/unsupported/libopie/pim/otodoaccessxml.cpp
new file mode 100644
index 0000000..4a5cb33
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodoaccessxml.cpp
@@ -0,0 +1,876 @@
1#include <errno.h>
2#include <fcntl.h>
3
4#include <sys/mman.h>
5#include <sys/stat.h>
6#include <sys/types.h>
7
8#include <unistd.h>
9
10
11#include <qfile.h>
12#include <qvector.h>
13
14#include <qpe/global.h>
15#include <qpe/stringutil.h>
16#include <qpe/timeconversion.h>
17
18#include "oconversion.h"
19#include "opimstate.h"
20#include "otimezone.h"
21#include "opimnotifymanager.h"
22#include "orecur.h"
23#include "otodoaccessxml.h"
24
25namespace {
26 time_t rp_end;
27 ORecur* rec;
28 ORecur *recur() {
29 if (!rec ) rec = new ORecur;
30 return rec;
31 }
32 int snd;
33 enum MoreAttributes {
34 FRType = OTodo::CompletedDate + 2,
35 FRWeekdays,
36 FRPosition,
37 FRFreq,
38 FRHasEndDate,
39 FREndDate,
40 FRStart,
41 FREnd
42 };
43 // FROM TT again
44char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
45{
46 char needleChar;
47 char haystackChar;
48 if (!needle || !haystack || !hLen || !nLen)
49 return 0;
50
51 const char* hsearch = haystack;
52
53 if ((needleChar = *needle++) != 0) {
54 nLen--; //(to make up for needle++)
55 do {
56 do {
57 if ((haystackChar = *hsearch++) == 0)
58 return (0);
59 if (hsearch >= haystack + hLen)
60 return (0);
61 } while (haystackChar != needleChar);
62 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
63 hsearch--;
64 }
65 return ((char *)hsearch);
66}
67}
68
69
70OTodoAccessXML::OTodoAccessXML( const QString& appName,
71 const QString& fileName )
72 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
73{
74 if (!fileName.isEmpty() )
75 m_file = fileName;
76 else
77 m_file = Global::applicationFileName( "todolist", "todolist.xml" );
78}
79OTodoAccessXML::~OTodoAccessXML() {
80
81}
82bool OTodoAccessXML::load() {
83 rec = 0;
84 m_opened = true;
85 m_changed = false;
86 /* initialize dict */
87 /*
88 * UPDATE dict if you change anything!!!
89 */
90 QAsciiDict<int> dict(26);
91 dict.setAutoDelete( TRUE );
92 dict.insert("Categories" , new int(OTodo::Category) );
93 dict.insert("Uid" , new int(OTodo::Uid) );
94 dict.insert("HasDate" , new int(OTodo::HasDate) );
95 dict.insert("Completed" , new int(OTodo::Completed) );
96 dict.insert("Description" , new int(OTodo::Description) );
97 dict.insert("Summary" , new int(OTodo::Summary) );
98 dict.insert("Priority" , new int(OTodo::Priority) );
99 dict.insert("DateDay" , new int(OTodo::DateDay) );
100 dict.insert("DateMonth" , new int(OTodo::DateMonth) );
101 dict.insert("DateYear" , new int(OTodo::DateYear) );
102 dict.insert("Progress" , new int(OTodo::Progress) );
103 dict.insert("CompletedDate", new int(OTodo::CompletedDate) );
104 dict.insert("StartDate", new int(OTodo::StartDate) );
105 dict.insert("CrossReference", new int(OTodo::CrossReference) );
106 dict.insert("State", new int(OTodo::State) );
107 dict.insert("Alarms", new int(OTodo::Alarms) );
108 dict.insert("Reminders", new int(OTodo::Reminders) );
109 dict.insert("Notifiers", new int(OTodo::Notifiers) );
110 dict.insert("Maintainer", new int(OTodo::Maintainer) );
111 dict.insert("rtype", new int(FRType) );
112 dict.insert("rweekdays", new int(FRWeekdays) );
113 dict.insert("rposition", new int(FRPosition) );
114 dict.insert("rfreq", new int(FRFreq) );
115 dict.insert("start", new int(FRStart) );
116 dict.insert("rhasenddate", new int(FRHasEndDate) );
117 dict.insert("enddt", new int(FREndDate) );
118
119 // here the custom XML parser from TT it's GPL
120 // but we want to push OpiePIM... to TT.....
121 // mmap part from zecke :)
122 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY );
123 struct stat attribut;
124 if ( fd < 0 ) return false;
125
126 if ( fstat(fd, &attribut ) == -1 ) {
127 ::close( fd );
128 return false;
129 }
130 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 );
131 if ( map_addr == ( (caddr_t)-1) ) {
132 ::close(fd );
133 return false;
134 }
135 /* advise the kernel who we want to read it */
136 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL );
137 /* we do not the file any more */
138 ::close( fd );
139
140 char* dt = (char*)map_addr;
141 int len = attribut.st_size;
142 int i = 0;
143 char *point;
144 const char* collectionString = "<Task ";
145 int strLen = strlen(collectionString);
146 while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) {
147 i = point -dt;
148 i+= strLen;
149 qWarning("Found a start at %d %d", i, (point-dt) );
150
151 OTodo ev;
152 m_year = m_month = m_day = 0;
153
154 while ( TRUE ) {
155 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
156 ++i;
157 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
158 break;
159
160 // we have another attribute, read it.
161 int j = i;
162 while ( j < len && dt[j] != '=' )
163 ++j;
164 QCString attr( dt+i, j-i+1);
165
166 i = ++j; // skip =
167
168 // find the start of quotes
169 while ( i < len && dt[i] != '"' )
170 ++i;
171 j = ++i;
172
173 bool haveUtf = FALSE;
174 bool haveEnt = FALSE;
175 while ( j < len && dt[j] != '"' ) {
176 if ( ((unsigned char)dt[j]) > 0x7f )
177 haveUtf = TRUE;
178 if ( dt[j] == '&' )
179 haveEnt = TRUE;
180 ++j;
181 }
182 if ( i == j ) {
183 // empty value
184 i = j + 1;
185 continue;
186 }
187
188 QCString value( dt+i, j-i+1 );
189 i = j + 1;
190
191 QString str = (haveUtf ? QString::fromUtf8( value )
192 : QString::fromLatin1( value ) );
193 if ( haveEnt )
194 str = Qtopia::plainString( str );
195
196 /*
197 * add key + value
198 */
199 todo( &dict, ev, attr, str );
200
201 }
202 /*
203 * now add it
204 */
205 qWarning("End at %d", i );
206 if (m_events.contains( ev.uid() ) || ev.uid() == 0) {
207 ev.setUid( 1 );
208 m_changed = true;
209 }
210 if ( ev.hasDueDate() ) {
211 ev.setDueDate( QDate(m_year, m_month, m_day) );
212 }
213 if ( rec && rec->doesRecur() ) {
214 OTimeZone utc = OTimeZone::utc();
215 ORecur recu( *rec ); // call copy c'tor
216 recu.setEndDate( utc.fromUTCDateTime( rp_end ).date() );
217 recu.setStart( ev.dueDate() );
218 ev.setRecurrence( recu );
219 }
220 m_events.insert(ev.uid(), ev );
221 m_year = m_month = m_day = -1;
222 delete rec;
223 rec = 0;
224 }
225
226 munmap(map_addr, attribut.st_size );
227
228 qWarning("counts %d records loaded!", m_events.count() );
229 return true;
230}
231bool OTodoAccessXML::reload() {
232 m_events.clear();
233 return load();
234}
235bool OTodoAccessXML::save() {
236// qWarning("saving");
237 if (!m_opened || !m_changed ) {
238// qWarning("not saving");
239 return true;
240 }
241 QString strNewFile = m_file + ".new";
242 QFile f( strNewFile );
243 if (!f.open( IO_WriteOnly|IO_Raw ) )
244 return false;
245
246 int written;
247 QString out;
248 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
249
250 // for all todos
251 QMap<int, OTodo>::Iterator it;
252 for (it = m_events.begin(); it != m_events.end(); ++it ) {
253 out+= "<Task " + toString( (*it) ) + " />\n";
254 QCString cstr = out.utf8();
255 written = f.writeBlock( cstr.data(), cstr.length() );
256
257 /* less written then we wanted */
258 if ( written != (int)cstr.length() ) {
259 f.close();
260 QFile::remove( strNewFile );
261 return false;
262 }
263 out = QString::null;
264 }
265
266 out += "</Tasks>";
267 QCString cstr = out.utf8();
268 written = f.writeBlock( cstr.data(), cstr.length() );
269
270 if ( written != (int)cstr.length() ) {
271 f.close();
272 QFile::remove( strNewFile );
273 return false;
274 }
275 /* flush before renaming */
276 f.close();
277
278 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
279// qWarning("error renaming");
280 QFile::remove( strNewFile );
281 }
282
283 m_changed = false;
284 return true;
285}
286QArray<int> OTodoAccessXML::allRecords()const {
287 QArray<int> ids( m_events.count() );
288 QMap<int, OTodo>::ConstIterator it;
289 int i = 0;
290
291 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
292 ids[i] = it.key();
293 i++;
294 }
295 return ids;
296}
297QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int, const QDateTime& ) {
298 QArray<int> ids(0);
299 return ids;
300}
301OTodo OTodoAccessXML::find( int uid )const {
302 OTodo todo;
303 todo.setUid( 0 ); // isEmpty()
304 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
305 if ( it != m_events.end() )
306 todo = it.data();
307
308 return todo;
309}
310void OTodoAccessXML::clear() {
311 if (m_opened )
312 m_changed = true;
313
314 m_events.clear();
315}
316bool OTodoAccessXML::add( const OTodo& todo ) {
317// qWarning("add");
318 m_changed = true;
319 m_events.insert( todo.uid(), todo );
320
321 return true;
322}
323bool OTodoAccessXML::remove( int uid ) {
324 m_changed = true;
325 m_events.remove( uid );
326
327 return true;
328}
329bool OTodoAccessXML::replace( const OTodo& todo) {
330 m_changed = true;
331 m_events.replace( todo.uid(), todo );
332
333 return true;
334}
335QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
336 const QDate& end,
337 bool includeNoDates ) {
338 QArray<int> ids( m_events.count() );
339 QMap<int, OTodo>::Iterator it;
340
341 int i = 0;
342 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
343 if ( !it.data().hasDueDate() ) {
344 if ( includeNoDates ) {
345 ids[i] = it.key();
346 i++;
347 }
348 }else if ( it.data().dueDate() >= start &&
349 it.data().dueDate() <= end ) {
350 ids[i] = it.key();
351 i++;
352 }
353 }
354 ids.resize( i );
355 return ids;
356}
357QArray<int> OTodoAccessXML::overDue() {
358 QArray<int> ids( m_events.count() );
359 int i = 0;
360
361 QMap<int, OTodo>::Iterator it;
362 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
363 if ( it.data().isOverdue() ) {
364 ids[i] = it.key();
365 i++;
366 }
367 }
368 ids.resize( i );
369 return ids;
370}
371
372
373/* private */
374void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
375 const QCString& attr, const QString& val) {
376// qWarning("parse to do from XMLElement" );
377
378 int *find=0;
379
380 find = (*dict)[ attr.data() ];
381 if (!find ) {
382// qWarning("Unknown option" + it.key() );
383 ev.setCustomField( attr, val );
384 return;
385 }
386
387 switch( *find ) {
388 case OTodo::Uid:
389 ev.setUid( val.toInt() );
390 break;
391 case OTodo::Category:
392 ev.setCategories( ev.idsFromString( val ) );
393 break;
394 case OTodo::HasDate:
395 ev.setHasDueDate( val.toInt() );
396 break;
397 case OTodo::Completed:
398 ev.setCompleted( val.toInt() );
399 break;
400 case OTodo::Description:
401 ev.setDescription( val );
402 break;
403 case OTodo::Summary:
404 ev.setSummary( val );
405 break;
406 case OTodo::Priority:
407 ev.setPriority( val.toInt() );
408 break;
409 case OTodo::DateDay:
410 m_day = val.toInt();
411 break;
412 case OTodo::DateMonth:
413 m_month = val.toInt();
414 break;
415 case OTodo::DateYear:
416 m_year = val.toInt();
417 break;
418 case OTodo::Progress:
419 ev.setProgress( val.toInt() );
420 break;
421 case OTodo::CompletedDate:
422 ev.setCompletedDate( OConversion::dateFromString( val ) );
423 break;
424 case OTodo::StartDate:
425 ev.setStartDate( OConversion::dateFromString( val ) );
426 break;
427 case OTodo::State:
428 ev.setState( val.toInt() );
429 break;
430 case OTodo::Alarms:{
431 OPimNotifyManager &manager = ev.notifiers();
432 QStringList als = QStringList::split(";", val );
433 for (QStringList::Iterator it = als.begin(); it != als.end(); ++it ) {
434 QStringList alarm = QStringList::split(":", (*it), TRUE ); // allow empty
435 qWarning("alarm: %s", alarm.join("___").latin1() );
436 qWarning("alarm[0]: %s %s", alarm[0].latin1(), OConversion::dateTimeFromString( alarm[0] ).toString().latin1() );
437 OPimAlarm al( alarm[2].toInt(), OConversion::dateTimeFromString( alarm[0] ), alarm[1].toInt() );
438 manager.add( al );
439 }
440 }
441 break;
442 case OTodo::Reminders:{
443 OPimNotifyManager &manager = ev.notifiers();
444 QStringList rems = QStringList::split(";", val );
445 for (QStringList::Iterator it = rems.begin(); it != rems.end(); ++it ) {
446 OPimReminder rem( (*it).toInt() );
447 manager.add( rem );
448 }
449 }
450 break;
451 case OTodo::CrossReference:
452 {
453 /*
454 * A cross refernce looks like
455 * appname,id;appname,id
456 * we need to split it up
457 */
458 QStringList refs = QStringList::split(';', val );
459 QStringList::Iterator strIt;
460 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
461 int pos = (*strIt).find(',');
462 if ( pos > -1 )
463 ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() );
464
465 }
466 break;
467 }
468 /* Recurrence stuff below + post processing later */
469 case FRType:
470 if ( val == "Daily" )
471 recur()->setType( ORecur::Daily );
472 else if ( val == "Weekly" )
473 recur()->setType( ORecur::Weekly);
474 else if ( val == "MonthlyDay" )
475 recur()->setType( ORecur::MonthlyDay );
476 else if ( val == "MonthlyDate" )
477 recur()->setType( ORecur::MonthlyDate );
478 else if ( val == "Yearly" )
479 recur()->setType( ORecur::Yearly );
480 else
481 recur()->setType( ORecur::NoRepeat );
482 break;
483 case FRWeekdays:
484 recur()->setDays( val.toInt() );
485 break;
486 case FRPosition:
487 recur()->setPosition( val.toInt() );
488 break;
489 case FRFreq:
490 recur()->setFrequency( val.toInt() );
491 break;
492 case FRHasEndDate:
493 recur()->setHasEndDate( val.toInt() );
494 break;
495 case FREndDate: {
496 rp_end = (time_t) val.toLong();
497 break;
498 }
499 default:
500 ev.setCustomField( attr, val );
501 break;
502 }
503}
504
505// from PalmtopRecord... GPL ### FIXME
506namespace {
507QString customToXml(const QMap<QString, QString>& customMap )
508{
509 //qWarning(QString("writing custom %1").arg(customMap.count()));
510 QString buf(" ");
511 for ( QMap<QString, QString>::ConstIterator cit = customMap.begin();
512 cit != customMap.end(); ++cit) {
513 // qWarning(".ITEM.");
514 buf += cit.key();
515 buf += "=\"";
516 buf += Qtopia::escapeString(cit.data());
517 buf += "\" ";
518 }
519 return buf;
520}
521
522
523}
524
525QString OTodoAccessXML::toString( const OTodo& ev )const {
526 QString str;
527
528 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
529 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
530 str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
531 str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
532
533 str += "Categories=\"" + toString( ev.categories() ) + "\" ";
534 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
535 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
536
537 if ( ev.hasDueDate() ) {
538 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
539 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
540 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
541 }
542// qWarning( "Uid %d", ev.uid() );
543 str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
544
545// append the extra options
546 /* FIXME Qtopia::Record this is currently not
547 * possible you can set custom fields
548 * but don' iterate over the list
549 * I may do #define private protected
550 * for this case - cough --zecke
551 */
552 /*
553 QMap<QString, QString> extras = ev.extras();
554 QMap<QString, QString>::Iterator extIt;
555 for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
556 str += extIt.key() + "=\"" + extIt.data() + "\" ";
557 */
558 // cross refernce
559 if ( ev.hasRecurrence() ) {
560 str += ev.recurrence().toString();
561 }
562 if ( ev.hasStartDate() )
563 str += "StartDate=\""+ OConversion::dateToString( ev.startDate() ) +"\" ";
564 if ( ev.hasCompletedDate() )
565 str += "CompletedDate=\""+ OConversion::dateToString( ev.completedDate() ) +"\" ";
566 if ( ev.hasState() )
567 str += "State=\""+QString::number( ev.state().state() )+"\" ";
568
569 /*
570 * save reminders and notifiers!
571 * DATE_TIME:DURATION:SOUND:NOT_USED_YET;OTHER_DATE_TIME:OTHER_DURATION:SOUND:....
572 */
573 if ( ev.hasNotifiers() ) {
574 OPimNotifyManager manager = ev.notifiers();
575 OPimNotifyManager::Alarms alarms = manager.alarms();
576 if (!alarms.isEmpty() ) {
577 QStringList als;
578 OPimNotifyManager::Alarms::Iterator it = alarms.begin();
579 for ( ; it != alarms.end(); ++it ) {
580 /* only if time is valid */
581 if ( (*it).dateTime().isValid() ) {
582 als << OConversion::dateTimeToString( (*it).dateTime() )
583 + ":" + QString::number( (*it).duration() )
584 + ":" + QString::number( (*it).sound() )
585 + ":";
586 }
587 }
588 // now write the list
589 qWarning("als: %s", als.join("____________").latin1() );
590 str += "Alarms=\""+als.join(";") +"\" ";
591 }
592
593 /*
594 * now the same for reminders but more easy. We just save the uid of the OEvent.
595 */
596 OPimNotifyManager::Reminders reminders = manager.reminders();
597 if (!reminders.isEmpty() ) {
598 OPimNotifyManager::Reminders::Iterator it = reminders.begin();
599 QStringList records;
600 for ( ; it != reminders.end(); ++it ) {
601 records << QString::number( (*it).recordUid() );
602 }
603 str += "Reminders=\""+ records.join(";") +"\" ";
604 }
605 }
606 str += customToXml( ev.toExtraMap() );
607
608
609 return str;
610}
611QString OTodoAccessXML::toString( const QArray<int>& ints ) const {
612 return Qtopia::Record::idsToString( ints );
613}
614
615/* internal class for sorting
616 *
617 * Inspired by todoxmlio.cpp from TT
618 */
619
620struct OTodoXMLContainer {
621 OTodo todo;
622};
623
624namespace {
625 inline QString string( const OTodo& todo) {
626 return todo.summary().isEmpty() ?
627 todo.description().left(20 ) :
628 todo.summary();
629 }
630 inline int completed( const OTodo& todo1, const OTodo& todo2) {
631 int ret = 0;
632 if ( todo1.isCompleted() ) ret++;
633 if ( todo2.isCompleted() ) ret--;
634 return ret;
635 }
636 inline int priority( const OTodo& t1, const OTodo& t2) {
637 return ( t1.priority() - t2.priority() );
638 }
639 inline int description( const OTodo& t1, const OTodo& t2) {
640 return QString::compare( string(t1), string(t2) );
641 }
642 inline int deadline( const OTodo& t1, const OTodo& t2) {
643 int ret = 0;
644 if ( t1.hasDueDate() &&
645 t2.hasDueDate() )
646 ret = t2.dueDate().daysTo( t1.dueDate() );
647 else if ( t1.hasDueDate() )
648 ret = -1;
649 else if ( t2.hasDueDate() )
650 ret = 1;
651 else
652 ret = 0;
653
654 return ret;
655 }
656
657};
658
659/*
660 * Returns:
661 * 0 if item1 == item2
662 *
663 * non-zero if item1 != item2
664 *
665 * This function returns int rather than bool so that reimplementations
666 * can return one of three values and use it to sort by:
667 *
668 * 0 if item1 == item2
669 *
670 * > 0 (positive integer) if item1 > item2
671 *
672 * < 0 (negative integer) if item1 < item2
673 *
674 */
675class OTodoXMLVector : public QVector<OTodoXMLContainer> {
676public:
677 OTodoXMLVector(int size, bool asc, int sort)
678 : QVector<OTodoXMLContainer>( size )
679 {
680 setAutoDelete( true );
681 m_asc = asc;
682 m_sort = sort;
683 }
684 /* return the summary/description */
685 QString string( const OTodo& todo) {
686 return todo.summary().isEmpty() ?
687 todo.description().left(20 ) :
688 todo.summary();
689 }
690 /**
691 * we take the sortorder( switch on it )
692 *
693 */
694 int compareItems( Item d1, Item d2 ) {
695 bool seComp, sePrio, seDesc, seDeadline;
696 seComp = sePrio = seDeadline = seDesc = false;
697 int ret =0;
698 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1;
699 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2;
700
701 /* same item */
702 if ( con1->todo.uid() == con2->todo.uid() )
703 return 0;
704
705 switch ( m_sort ) {
706 /* completed */
707 case 0: {
708 ret = completed( con1->todo, con2->todo );
709 seComp = TRUE;
710 break;
711 }
712 /* priority */
713 case 1: {
714 ret = priority( con1->todo, con2->todo );
715 sePrio = TRUE;
716 break;
717 }
718 /* description */
719 case 2: {
720 ret = description( con1->todo, con2->todo );
721 seDesc = TRUE;
722 break;
723 }
724 /* deadline */
725 case 3: {
726 ret = deadline( con1->todo, con2->todo );
727 seDeadline = TRUE;
728 break;
729 }
730 default:
731 ret = 0;
732 break;
733 };
734 /*
735 * FIXME do better sorting if the first sort criteria
736 * ret equals 0 start with complete and so on...
737 */
738
739 /* twist it we're not ascending*/
740 if (!m_asc)
741 ret = ret * -1;
742
743 if ( ret )
744 return ret;
745
746 // default did not gave difference let's try it other way around
747 /*
748 * General try if already checked if not test
749 * and return
750 * 1.Completed
751 * 2.Priority
752 * 3.Description
753 * 4.DueDate
754 */
755 if (!seComp ) {
756 if ( (ret = completed( con1->todo, con2->todo ) ) ) {
757 if (!m_asc ) ret *= -1;
758 return ret;
759 }
760 }
761 if (!sePrio ) {
762 if ( (ret = priority( con1->todo, con2->todo ) ) ) {
763 if (!m_asc ) ret *= -1;
764 return ret;
765 }
766 }
767 if (!seDesc ) {
768 if ( (ret = description(con1->todo, con2->todo ) ) ) {
769 if (!m_asc) ret *= -1;
770 return ret;
771 }
772 }
773 if (!seDeadline) {
774 if ( (ret = deadline( con1->todo, con2->todo ) ) ) {
775 if (!m_asc) ret *= -1;
776 return ret;
777 }
778 }
779
780 return 0;
781 }
782 private:
783 bool m_asc;
784 int m_sort;
785
786};
787
788QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder,
789 int sortFilter, int cat ) {
790 OTodoXMLVector vector(m_events.count(), asc,sortOrder );
791 QMap<int, OTodo>::Iterator it;
792 int item = 0;
793
794 bool bCat = sortFilter & 1 ? true : false;
795 bool bOnly = sortFilter & 2 ? true : false;
796 bool comp = sortFilter & 4 ? true : false;
797 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
798
799 /* show category */
800 /* -1 == unfiled */
801 if ( bCat && cat == -1 ) {
802 if(!(*it).categories().isEmpty() )
803 continue;
804 }else if ( bCat && cat != 0)
805 if (!(*it).categories().contains( cat ) ) {
806 continue;
807 }
808 /* isOverdue but we should not show overdue - why?*/
809/* if ( (*it).isOverdue() && !bOnly ) {
810 qWarning("item is overdue but !bOnly");
811 continue;
812 }
813*/
814 if ( !(*it).isOverdue() && bOnly ) {
815 continue;
816 }
817
818 if ((*it).isCompleted() && comp ) {
819 continue;
820 }
821
822
823 OTodoXMLContainer* con = new OTodoXMLContainer();
824 con->todo = (*it);
825 vector.insert(item, con );
826 item++;
827 }
828 vector.resize( item );
829 /* sort it now */
830 vector.sort();
831 /* now get the uids */
832 QArray<int> array( vector.count() );
833 for (uint i= 0; i < vector.count(); i++ ) {
834 array[i] = ( vector.at(i) )->todo.uid();
835 }
836 return array;
837};
838void OTodoAccessXML::removeAllCompleted() {
839 QMap<int, OTodo> events = m_events;
840 for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) {
841 if ( (*it).isCompleted() )
842 events.remove( it.key() );
843 }
844 m_events = events;
845}
846QBitArray OTodoAccessXML::supports()const {
847 static QBitArray ar = sup();
848 return ar;
849}
850QBitArray OTodoAccessXML::sup() {
851 QBitArray ar( OTodo::CompletedDate +1 );
852 ar.fill( true );
853 ar[OTodo::CrossReference] = false;
854 ar[OTodo::State ] = false;
855 ar[OTodo::Reminders] = false;
856 ar[OTodo::Notifiers] = false;
857 ar[OTodo::Maintainer] = false;
858
859 return ar;
860}
861QArray<int> OTodoAccessXML::matchRegexp( const QRegExp &r ) const
862{
863 QArray<int> m_currentQuery( m_events.count() );
864 uint arraycounter = 0;
865
866 QMap<int, OTodo>::ConstIterator it;
867 for (it = m_events.begin(); it != m_events.end(); ++it ) {
868 if ( it.data().match( r ) )
869 m_currentQuery[arraycounter++] = it.data().uid();
870
871 }
872 // Shrink to fit..
873 m_currentQuery.resize(arraycounter);
874
875 return m_currentQuery;
876}
diff --git a/noncore/unsupported/libopie/pim/otodoaccessxml.h b/noncore/unsupported/libopie/pim/otodoaccessxml.h
new file mode 100644
index 0000000..e4850a1
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodoaccessxml.h
@@ -0,0 +1,60 @@
1#ifndef OPIE_TODO_ACCESS_XML_H
2#define OPIE_TODO_ACCESS_XML_H
3
4#include <qasciidict.h>
5#include <qmap.h>
6
7#include "otodoaccessbackend.h"
8
9namespace Opie {
10 class XMLElement;
11};
12
13class OTodoAccessXML : public OTodoAccessBackend {
14public:
15 /**
16 * fileName if Empty we will use the default path
17 */
18 OTodoAccessXML( const QString& appName,
19 const QString& fileName = QString::null );
20 ~OTodoAccessXML();
21
22 bool load();
23 bool reload();
24 bool save();
25
26 QArray<int> allRecords()const;
27 QArray<int> matchRegexp(const QRegExp &r) const;
28 QArray<int> queryByExample( const OTodo&, int querysettings, const QDateTime& d = QDateTime() );
29 OTodo find( int uid )const;
30 void clear();
31 bool add( const OTodo& );
32 bool remove( int uid );
33 void removeAllCompleted();
34 bool replace( const OTodo& );
35
36 /* our functions */
37 QArray<int> effectiveToDos( const QDate& start,
38 const QDate& end,
39 bool includeNoDates );
40 QArray<int> overDue();
41 QArray<int> sorted( bool asc, int sortOrder,
42 int sortFilter, int cat );
43 QBitArray supports()const;
44private:
45 static QBitArray sup();
46 void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& );
47 QString toString( const OTodo& )const;
48 QString toString( const QArray<int>& ints ) const;
49 QMap<int, OTodo> m_events;
50 QString m_file;
51 QString m_app;
52 bool m_opened : 1;
53 bool m_changed : 1;
54 class OTodoAccessXMLPrivate;
55 OTodoAccessXMLPrivate* d;
56 int m_year, m_month, m_day;
57
58};
59
60#endif
diff --git a/noncore/unsupported/libopie/sharp_compat.cpp b/noncore/unsupported/libopie/sharp_compat.cpp
new file mode 100644
index 0000000..1d16a09
--- a/dev/null
+++ b/noncore/unsupported/libopie/sharp_compat.cpp
@@ -0,0 +1,18 @@
1/*
2 * This file contains hacks or workarounds, that make it possible to use a normal
3 * libopie arm build (iPAQ or OZ) directly on the Sharp retail ROM.
4 * This way, we only need one 'official' libopie binary for all platforms.
5 */
6
7
8// 1) Opie's libqpe.so has an additional function in Sound, which is utilized
9// in ODevice:
10
11// ok this is really evil ;), but Sound::isFinished is only needed in the
12// iPAQ part of ODevice, which is never called on Z's
13// we add a "weak" symbol here. This will be used, if ld.so does not find
14// a normal ("hard") symbol of the same name - hence only on the retail Z
15
16struct Sound { bool Sound::isFinished ( ) const __attribute__(( weak )); };
17bool Sound::isFinished ( ) const { return true; }
18
diff --git a/noncore/unsupported/libopie/todayconfigwidget.h b/noncore/unsupported/libopie/todayconfigwidget.h
new file mode 100644
index 0000000..f3501a1
--- a/dev/null
+++ b/noncore/unsupported/libopie/todayconfigwidget.h
@@ -0,0 +1,39 @@
1
2#ifndef CONFIG_WIDGET_H
3#define CONFIG_WIDGET_H
4
5
6/**
7 * A base class for all Today Config Widgets.
8 * This will let a Today plugin to add the possibility of configuration.
9 * Plugins need to inherit from this class and need to implement
10 * the pure virtual method to control configuration.
11 * The Plugin should read its configuration during creation of the Widget
12 *
13 *
14 * @author Maximilian Reiß
15 * @short base class of all today config widgets
16 */
17class TodayConfigWidget : public QWidget {
18
19
20public:
21
22 /**
23 * This will construct the widget. The widget gets deleted once the parent
24 * gets deleted as in any Qt application
25 *
26 * @param parent The parent of the widget
27 * @param name The name of the object
28 */
29 TodayConfigWidget( QWidget *parent, const char *name ) : QWidget( parent, name ) {} ;
30 virtual ~TodayConfigWidget() {};
31
32 /**
33 * Plugins need to reimplement this in the config widget
34 * Used when the config dialog is closed to write config stuff
35 */
36 virtual void writeConfig() = 0;
37};
38
39#endif
diff --git a/noncore/unsupported/libopie/todayplugininterface.h b/noncore/unsupported/libopie/todayplugininterface.h
new file mode 100644
index 0000000..5dfeaa8
--- a/dev/null
+++ b/noncore/unsupported/libopie/todayplugininterface.h
@@ -0,0 +1,133 @@
1/*
2                This file is part of the Opie Project
3 Copyright (c) 2002 Maximilian Reiss <max.reiss@gmx.de>
4 =.
5 .=l.
6           .>+-=
7 _;:,     .>    :=|. This program is free software; you can
8.> <`_,   >  .   <= redistribute it and/or modify it under
9:`=1 )Y*s>-.--   : the terms of the GNU General Public
10.="- .-=="i,     .._ License as published by the Free Software
11 - .   .-<_>     .<> Foundation; either version 2 of the License,
12     ._= =}       : or (at your option) any later version.
13    .%`+i>       _;_.
14    .i_,=:_.      -<s. This program is distributed in the hope that
15     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
16    : ..    .:,     . . . without even the implied warranty of
17    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
18  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.=       =       ; Library General Public License for more
20++=   -.     .`     .: details.
21 :     =  ...= . :.=-
22 -.   .:....=;==+<; You should have received a copy of the GNU
23  -_. . .   )=.  = Library General Public License along with
24    --        :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28
29*/
30
31
32#ifndef TODAY_PLUGIN_INTERFACE
33#define TODAY_PLUGIN_INTERFACE
34
35#include <qpe/qcom.h>
36#include "todayconfigwidget.h"
37
38class QString;
39class QWidget;
40
41#ifndef IID_TodayPluginInterface
42#define IID_TodayPluginInterface QUuid( 0x70481804, 0x2b50, 0x4fba, 0x80, 0xbb, 0x0b, 0xf8, 0xdc, 0x72, 0x04, 0x14)
43#endif
44
45/**
46 *
47 * A TodayPluginObject is the base for all Today Plugins.
48 * A plugin author needs to inherit this class and implement
49 * the pure virtual methods
50 *
51 * @short base class for today plugins
52 * @author Maximilian Reiss
53 *
54 */
55class TodayPluginObject {
56
57public:
58
59 virtual ~TodayPluginObject() {};
60
61 /**
62 * The name if the plugin
63 * @return The plugin should return its name here
64 */
65 virtual QString pluginName() const = 0;
66
67 /**
68 * Version numbering
69 * @return The plugin should return the version number
70 */
71 virtual double versionNumber() const = 0;
72
73
74 /**
75 * @return the pixmap name widget?! -- FIXME
76 */
77 virtual QString pixmapNameWidget() const = 0;
78
79 /**
80 * widget for the today view
81 * It _needs_ a parent here.
82 * Plugin authors need to take parent as parent!
83 */
84 virtual QWidget* widget( QWidget *parent ) = 0;
85
86 /**
87 * Pixmap used in the config widget
88 */
89 virtual QString pixmapNameConfig() const = 0;
90
91 /**
92 * Config plugin widget - optional
93 * If the plugin has a config widget, it _needs_ a parent here.
94 * may return 0 if no config widget is needed
95 */
96 virtual TodayConfigWidget* configWidget( QWidget * ) = 0;
97
98 /**
99 * The application that should be assigned to the button (pixmap)
100 * Today will show the plugin icon. On click it tries to execute the
101 * plugin related application.
102 */
103 virtual QString appName() const = 0;
104
105
106 /**
107 * If the plugin should take part in the periodic refresh
108 */
109 virtual bool excludeFromRefresh() const = 0;
110
111 /**
112 * Refresh that plugins view. For updating the plugins
113 */
114 virtual void refresh() {};
115
116 /**
117 * reread the plugins config and act apropiate
118 * This is for example used when returning from the config dialog
119 */
120 virtual void reinitialize() {};
121};
122
123/**
124 * This is part of the QCOM works. See example plugins how to do it right
125 */
126struct TodayPluginInterface : public QUnknownInterface {
127 /**
128 * return the TodayPluginObject implementation
129 */
130 virtual TodayPluginObject *guiPart() = 0;
131};
132
133#endif
diff --git a/noncore/unsupported/libopie/xmltree.cc b/noncore/unsupported/libopie/xmltree.cc
new file mode 100644
index 0000000..27db5b3
--- a/dev/null
+++ b/noncore/unsupported/libopie/xmltree.cc
@@ -0,0 +1,322 @@
1/* This file is part of the KDE project
2 Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20#include <qpe/stringutil.h>
21#include <opie/xmltree.h>
22
23#include <qxml.h>
24
25#include <assert.h>
26
27using namespace Opie;
28
29XMLElement::XMLElement()
30 : m_parent( 0 ), m_next( 0 ), m_prev( 0 ), m_first( 0 ), m_last( 0 )
31{
32}
33
34XMLElement::~XMLElement()
35{
36 XMLElement *n = m_first;
37
38 while ( n )
39 {
40 XMLElement *tmp = n;
41 n = n->m_next;
42 delete tmp;
43 }
44}
45
46void XMLElement::appendChild( XMLElement *child )
47{
48 if ( child->m_parent )
49 child->m_parent->removeChild( child );
50
51 child->m_parent = this;
52
53 if ( m_last )
54 m_last->m_next = child;
55
56 child->m_prev = m_last;
57
58 if ( !m_first )
59 m_first = child;
60
61 m_last = child;
62}
63
64void XMLElement::insertAfter( XMLElement *newChild, XMLElement *refChild )
65{
66 assert( newChild != refChild );
67
68 if ( refChild == m_last )
69 {
70 appendChild( newChild );
71 return;
72 }
73
74 assert( refChild );
75 assert( refChild->m_parent );
76 assert( refChild->m_parent == this );
77
78 if ( newChild->m_parent && newChild != refChild )
79 newChild->m_parent->removeChild( newChild );
80
81 newChild->m_parent = this;
82
83 XMLElement *next = refChild->m_next;
84
85 refChild->m_next = newChild;
86
87 newChild->m_prev = refChild;
88 newChild->m_next = next;
89
90 if ( next )
91 next->m_prev = newChild;
92}
93
94QString XMLElement::attribute( const QString &attr ) const
95{
96 AttributeMap::ConstIterator it = m_attributes.find( attr );
97 if ( it == m_attributes.end() )
98 return QString::null;
99 return it.data();
100}
101
102void XMLElement::setAttribute( const QString &attr, const QString &value )
103{
104 m_attributes.replace( attr, value );
105}
106
107void XMLElement::insertBefore( XMLElement *newChild, XMLElement *refChild )
108{
109 assert( refChild );
110 assert( refChild->m_parent );
111 assert( refChild->m_parent == this );
112 assert( newChild != refChild );
113
114 if ( newChild->m_parent && newChild != refChild )
115 newChild->m_parent->removeChild( newChild );
116
117 newChild->m_parent = this;
118
119 XMLElement *prev = refChild->m_prev;
120
121 refChild->m_prev = newChild;
122
123 newChild->m_prev = prev;
124 newChild->m_next = refChild;
125
126 if ( prev )
127 prev->m_next = newChild;
128
129 if ( refChild == m_first )
130 m_first = newChild;
131}
132
133void XMLElement::removeChild( XMLElement *child )
134{
135 if ( child->m_parent != this )
136 return;
137
138 if ( m_first == child )
139 m_first = child->m_next;
140
141 if ( m_last == child )
142 m_last = child->m_prev;
143
144 if ( child->m_prev )
145 child->m_prev->m_next = child->m_next;
146
147 if ( child->m_next )
148 child->m_next->m_prev = child->m_prev;
149
150 child->m_parent = 0;
151 child->m_prev = 0;
152 child->m_next = 0;
153}
154
155void XMLElement::save( QTextStream &s, uint indent )
156{
157 if ( !m_value.isEmpty() )
158 {
159 s << Qtopia::escapeString( m_value );
160 return;
161 }
162
163 for ( uint i = 0; i < indent; ++i )
164 s << " ";
165
166 s << "<" << m_tag;
167
168 if ( !m_attributes.isEmpty() )
169 {
170 s << " ";
171 AttributeMap::ConstIterator it = m_attributes.begin();
172 AttributeMap::ConstIterator end = m_attributes.end();
173 for (; it != end; ++it )
174 {
175 s << it.key() << "=\"" << Qtopia::escapeString( it.data() ) << "\"";
176 s << " ";
177 }
178 }
179
180 if ( m_last )
181 {
182 if ( ( m_first && !m_first->value().isEmpty() ) || !m_parent )
183 s << ">";
184 else
185 s << ">" << endl;
186
187 int newIndent = indent;
188 if ( m_parent )
189 newIndent++;
190
191 XMLElement *n = m_first;
192 while ( n )
193 {
194 n->save( s, newIndent );
195 n = n->nextChild();
196 }
197
198 if ( m_last && m_last->value().isEmpty() && m_parent )
199 for ( uint i = 0; i < indent; ++i )
200 s << " ";
201
202 if ( m_parent )
203 s << "</" << m_tag << ">" << endl;
204 }
205 else
206 s << "/>" << endl;
207}
208
209class Handler : public QXmlDefaultHandler
210{
211public:
212 Handler() : m_node( 0 ), m_root( 0 ) {}
213
214 XMLElement *root() const { return m_root; }
215
216 virtual bool startDocument();
217 virtual bool endDocument();
218 virtual bool startElement( const QString &ns, const QString &ln, const QString &qName,
219 const QXmlAttributes &attr );
220 virtual bool endElement( const QString &ns, const QString &ln, const QString &qName );
221 virtual bool characters( const QString &ch );
222
223private:
224 XMLElement *m_node;
225 XMLElement *m_root;
226};
227
228bool Handler::startDocument()
229{
230 m_root = m_node = new XMLElement;
231
232 return true;
233}
234
235bool Handler::endDocument()
236{
237 return m_root == m_node;
238}
239
240bool Handler::startElement( const QString &, const QString &, const QString &qName,
241 const QXmlAttributes &attr )
242{
243 XMLElement *bm = new XMLElement;
244
245 XMLElement::AttributeMap attributes;
246 for ( int i = 0; i < attr.length(); ++i )
247 attributes[ attr.qName( i ) ] = attr.value( i );
248
249 bm->setAttributes( attributes );
250
251 bm->setTagName( qName );
252
253 m_node->appendChild( bm );
254 m_node = bm;
255
256 return true;
257}
258
259bool Handler::endElement( const QString &, const QString &, const QString & )
260{
261 if ( m_node == m_root )
262 return false;
263
264 m_node = m_node->parent();
265 return true;
266}
267
268bool Handler::characters( const QString &ch )
269{
270 XMLElement *textNode = new XMLElement;
271 textNode->setValue( ch );
272 m_node->appendChild( textNode );
273 return true;
274}
275
276XMLElement *XMLElement::namedItem( const QString &name )
277{
278 XMLElement *e = m_first;
279
280 for (; e; e = e->nextChild() )
281 if ( e->tagName() == name )
282 return e;
283
284 return 0;
285}
286
287XMLElement *XMLElement::clone() const
288{
289 XMLElement *res = new XMLElement;
290
291 res->setTagName( m_tag );
292 res->setValue( m_value );
293 res->setAttributes( m_attributes );
294
295 XMLElement *e = m_first;
296 for (; e; e = e->m_next )
297 res->appendChild( e->clone() );
298
299 return res;
300}
301
302XMLElement *XMLElement::load( const QString &fileName )
303{
304 QFile f( fileName );
305 if ( !f.open( IO_ReadOnly ) )
306 return 0;
307
308 QTextStream stream( &f );
309 stream.setEncoding( QTextStream::UnicodeUTF8 );
310 QXmlInputSource src( stream );
311 QXmlSimpleReader reader;
312 Handler handler;
313
314 reader.setFeature( "http://trolltech.com/xml/features/report-whitespace-only-CharData", false );
315 reader.setContentHandler( &handler );
316 reader.parse( src );
317
318 return handler.root();;
319}
320
321/* vim: et sw=4
322 */
diff --git a/noncore/unsupported/libopie/xmltree.h b/noncore/unsupported/libopie/xmltree.h
new file mode 100644
index 0000000..4b6bdfa
--- a/dev/null
+++ b/noncore/unsupported/libopie/xmltree.h
@@ -0,0 +1,119 @@
1/* This file is part of the KDE project
2 Copyright (C) 2000,2001 Simon Hausmann <hausmann@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20
21#ifndef __bookmarks_h__
22#define __bookmarks_h__
23
24#include <qstring.h>
25#include <qmap.h>
26#include <qtextstream.h>
27
28namespace Opie
29{
30
31/**
32 * A small xml lib written by Simon Hausmann.
33 */
34class XMLElement
35{
36public:
37 typedef QMap<QString, QString> AttributeMap;
38
39 /**
40 * The constructor of XMLElement
41 */
42 XMLElement();
43 ~XMLElement();
44
45 /** appendChild appends a child to the XMLElement behind the last element.
46 * The ownership of the child get's transfered to the
47 * this XMLElement.
48 * If child is already the child of another parent
49 * it's get removed from the other parent first.
50 */
51 void appendChild( XMLElement *child );
52
53 /** inserts newChild after refChild. If newChild is the child
54 * of another parent the child will get removed.
55 * The ownership of child gets transfered.
56 *
57 */
58 void insertAfter( XMLElement *newChild, XMLElement *refChild );
59
60 /** same as insertAfter but the element get's inserted before refChild.
61 *
62 */
63 void insertBefore( XMLElement *newChild, XMLElement *refChild );
64
65 /** removeChild removes the child from the XMLElement.
66 * The ownership gets dropped. You need to delete the
67 * child yourself.
68 */
69 void removeChild( XMLElement *child );
70
71 /** parent() returns the parent of this XMLElement
72 * If there is no parent 0l gets returned
73 */
74 XMLElement *parent() const { return m_parent; }
75 XMLElement *firstChild() const { return m_first; }
76 XMLElement *nextChild() const { return m_next; }
77 XMLElement *prevChild() const { return m_prev; }
78 XMLElement *lastChild() const { return m_last; }
79
80 void setTagName( const QString &tag ) { m_tag = tag; }
81 QString tagName() const { return m_tag; }
82
83 void setValue( const QString &val ) { m_value = val; }
84 QString value() const { return m_value; }
85
86 void setAttributes( const AttributeMap &attrs ) { m_attributes = attrs; }
87 AttributeMap attributes() const { return m_attributes; }
88 AttributeMap &attributes() { return m_attributes; }
89
90 QString attribute( const QString & ) const;
91 void setAttribute( const QString &attr, const QString &value );
92 void save( QTextStream &stream, uint indent = 0 );
93
94 XMLElement *namedItem( const QString &name );
95
96 XMLElement *clone() const;
97
98 static XMLElement *load( const QString &fileName );
99
100private:
101 QString m_tag;
102 QString m_value;
103 AttributeMap m_attributes;
104
105 XMLElement *m_parent;
106 XMLElement *m_next;
107 XMLElement *m_prev;
108 XMLElement *m_first;
109 XMLElement *m_last;
110
111 XMLElement( const XMLElement &rhs );
112 XMLElement &operator=( const XMLElement &rhs );
113 class Private;
114 Private* d;
115};
116
117} // namespace Opie
118
119#endif