summaryrefslogtreecommitdiff
path: root/noncore/unsupported
Side-by-side diff
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 @@
+*.moc
+Makefile*
+moc_*
+orecurrancebase.cpp
+orecurrancebase.h
+otimepickerbase.cpp
+otimepickerbase.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 @@
+/****************************************************************************
+** $Id$
+**
+** Implementation of OColorDialog class
+**
+** Created : 990222
+**
+** Copyright (C) 1999-2000 Trolltech AS. All rights reserved.
+**
+** This file is part of the dialogs module of the Qt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.QPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for QPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "colordialog.h"
+
+#include "qpainter.h"
+#include "qlayout.h"
+#include "qlabel.h"
+#include "qpushbutton.h"
+#include "qlineedit.h"
+#include "qimage.h"
+#include "qpixmap.h"
+#include "qdrawutil.h"
+#include "qvalidator.h"
+#include "qapplication.h"
+
+static inline void rgb2hsv( QRgb rgb, int&h, int&s, int&v )
+{
+ QColor c;
+ c.setRgb( rgb );
+ c.getHsv(h,s,v);
+}
+
+/*
+ * avoid clashes with the original Qt
+ */
+namespace {
+
+class QColorPicker : public QFrame
+{
+ Q_OBJECT
+public:
+ QColorPicker(QWidget* parent=0, const char* name=0);
+ ~QColorPicker();
+
+public slots:
+ void setCol( int h, int s );
+
+signals:
+ void newCol( int h, int s );
+
+protected:
+ QSize sizeHint() const;
+ QSizePolicy sizePolicy() const;
+ void drawContents(QPainter* p);
+ void mouseMoveEvent( QMouseEvent * );
+ void mousePressEvent( QMouseEvent * );
+
+private:
+ int hue;
+ int sat;
+
+ QPoint colPt();
+ int huePt( const QPoint &pt );
+ int satPt( const QPoint &pt );
+ void setCol( const QPoint &pt );
+
+ QPixmap *pix;
+};
+
+static int pWidth = 200;
+static int pHeight = 200;
+
+class QColorLuminancePicker : public QWidget
+{
+ Q_OBJECT
+public:
+ QColorLuminancePicker(QWidget* parent=0, const char* name=0);
+ ~QColorLuminancePicker();
+
+public slots:
+ void setCol( int h, int s, int v );
+ void setCol( int h, int s );
+
+signals:
+ void newHsv( int h, int s, int v );
+
+protected:
+// QSize sizeHint() const;
+// QSizePolicy sizePolicy() const;
+ void paintEvent( QPaintEvent*);
+ void mouseMoveEvent( QMouseEvent * );
+ void mousePressEvent( QMouseEvent * );
+
+private:
+ enum { foff = 3, coff = 4 }; //frame and contents offset
+ int val;
+ int hue;
+ int sat;
+
+ int y2val( int y );
+ int val2y( int val );
+ void setVal( int v );
+
+ QPixmap *pix;
+};
+
+
+int QColorLuminancePicker::y2val( int y )
+{
+ int d = height() - 2*coff - 1;
+ return 255 - (y - coff)*255/d;
+}
+
+int QColorLuminancePicker::val2y( int v )
+{
+ int d = height() - 2*coff - 1;
+ return coff + (255-v)*d/255;
+}
+
+QColorLuminancePicker::QColorLuminancePicker(QWidget* parent,
+ const char* name)
+ :QWidget( parent, name )
+{
+ hue = 100; val = 100; sat = 100;
+ pix = 0;
+ // setBackgroundMode( NoBackground );
+}
+
+QColorLuminancePicker::~QColorLuminancePicker()
+{
+ delete pix;
+}
+
+void QColorLuminancePicker::mouseMoveEvent( QMouseEvent *m )
+{
+ setVal( y2val(m->y()) );
+}
+void QColorLuminancePicker::mousePressEvent( QMouseEvent *m )
+{
+ setVal( y2val(m->y()) );
+}
+
+void QColorLuminancePicker::setVal( int v )
+{
+ if ( val == v )
+ return;
+ val = QMAX( 0, QMIN(v,255));
+ delete pix; pix=0;
+ repaint( FALSE ); //###
+ emit newHsv( hue, sat, val );
+}
+
+//receives from a hue,sat chooser and relays.
+void QColorLuminancePicker::setCol( int h, int s )
+{
+ setCol( h, s, val );
+ emit newHsv( h, s, val );
+}
+
+void QColorLuminancePicker::paintEvent( QPaintEvent * )
+{
+ int w = width() - 5;
+
+ QRect r( 0, foff, w, height() - 2*foff );
+ int wi = r.width() - 2;
+ int hi = r.height() - 2;
+ if ( !pix || pix->height() != hi || pix->width() != wi ) {
+ delete pix;
+ QImage img( wi, hi, 32 );
+ int y;
+ for ( y = 0; y < hi; y++ ) {
+ QColor c( hue, sat, y2val(y+coff), QColor::Hsv );
+ QRgb r = c.rgb();
+ int x;
+ for ( x = 0; x < wi; x++ )
+ img.setPixel( x, y, r );
+ }
+ pix = new QPixmap;
+ pix->convertFromImage(img);
+ }
+ QPainter p(this);
+ p.drawPixmap( 1, coff, *pix );
+ QColorGroup g = colorGroup();
+ qDrawShadePanel( &p, r, g, TRUE );
+ p.setPen( g.foreground() );
+ p.setBrush( g.foreground() );
+ QPointArray a;
+ int y = val2y(val);
+ a.setPoints( 3, w, y, w+5, y+5, w+5, y-5 );
+ erase( w, 0, 5, height() );
+ p.drawPolygon( a );
+}
+
+void QColorLuminancePicker::setCol( int h, int s , int v )
+{
+ val = v;
+ hue = h;
+ sat = s;
+ delete pix; pix=0;
+ repaint( FALSE );//####
+}
+
+QPoint QColorPicker::colPt()
+{ return QPoint( (360-hue)*(pWidth-1)/360, (255-sat)*(pHeight-1)/255 ); }
+int QColorPicker::huePt( const QPoint &pt )
+{ return 360 - pt.x()*360/(pWidth-1); }
+int QColorPicker::satPt( const QPoint &pt )
+{ return 255 - pt.y()*255/(pHeight-1) ; }
+void QColorPicker::setCol( const QPoint &pt )
+{ setCol( huePt(pt), satPt(pt) ); }
+
+QColorPicker::QColorPicker(QWidget* parent, const char* name )
+ : QFrame( parent, name )
+{
+ hue = 0; sat = 0;
+ setCol( 150, 255 );
+
+ QImage img( pWidth, pHeight, 32 );
+ int x,y;
+ for ( y = 0; y < pHeight; y++ )
+ for ( x = 0; x < pWidth; x++ ) {
+ QPoint p( x, y );
+ img.setPixel( x, y, QColor(huePt(p), satPt(p),
+ 200, QColor::Hsv).rgb() );
+ }
+ pix = new QPixmap;
+ pix->convertFromImage(img);
+ setBackgroundMode( NoBackground );
+}
+
+QColorPicker::~QColorPicker()
+{
+ delete pix;
+}
+
+QSize QColorPicker::sizeHint() const
+{
+ return QSize( pWidth + 2*frameWidth(), pHeight + 2*frameWidth() );
+}
+
+QSizePolicy QColorPicker::sizePolicy() const
+{
+ return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+}
+
+void QColorPicker::setCol( int h, int s )
+{
+ int nhue = QMIN( QMAX(0,h), 360 );
+ int nsat = QMIN( QMAX(0,s), 255);
+ if ( nhue == hue && nsat == sat )
+ return;
+ QRect r( colPt(), QSize(20,20) );
+ hue = nhue; sat = nsat;
+ r = r.unite( QRect( colPt(), QSize(20,20) ) );
+ r.moveBy( contentsRect().x()-9, contentsRect().y()-9 );
+ // update( r );
+ repaint( r, FALSE );
+}
+
+void QColorPicker::mouseMoveEvent( QMouseEvent *m )
+{
+ QPoint p = m->pos() - contentsRect().topLeft();
+ setCol( p );
+ emit newCol( hue, sat );
+}
+
+void QColorPicker::mousePressEvent( QMouseEvent *m )
+{
+ QPoint p = m->pos() - contentsRect().topLeft();
+ setCol( p );
+ emit newCol( hue, sat );
+}
+
+void QColorPicker::drawContents(QPainter* p)
+{
+ QRect r = contentsRect();
+
+ p->drawPixmap( r.topLeft(), *pix );
+ QPoint pt = colPt() + r.topLeft();
+ p->setPen( QPen(black) );
+
+ p->fillRect( pt.x()-9, pt.y(), 20, 2, black );
+ p->fillRect( pt.x(), pt.y()-9, 2, 20, black );
+
+}
+
+class QColorShowLabel;
+
+
+
+class QColIntValidator: public QIntValidator
+{
+public:
+ QColIntValidator( int bottom, int top,
+ QWidget * parent, const char *name = 0 )
+ :QIntValidator( bottom, top, parent, name ) {}
+
+ QValidator::State validate( QString &, int & ) const;
+};
+
+QValidator::State QColIntValidator::validate( QString &s, int &pos ) const
+{
+ State state = QIntValidator::validate(s,pos);
+ if ( state == Valid ) {
+ long int val = s.toLong();
+ // This is not a general solution, assumes that top() > 0 and
+ // bottom >= 0
+ if ( val < 0 ) {
+ s = "0";
+ pos = 1;
+ } else if ( val > top() ) {
+ s.setNum( top() );
+ pos = s.length();
+ }
+ }
+ return state;
+}
+
+
+
+class QColNumLineEdit : public QLineEdit
+{
+public:
+ QColNumLineEdit( QWidget *parent, const char* name = 0 )
+ : QLineEdit( parent, name ) { setMaxLength( 3 );}
+ QSize sizeHint() const {
+ return QSize( 30, //#####
+ QLineEdit::sizeHint().height() ); }
+ void setNum( int i ) {
+ QString s;
+ s.setNum(i);
+ bool block = signalsBlocked();
+ blockSignals(TRUE);
+ setText( s );
+ blockSignals(block);
+ }
+ int val() const { return text().toInt(); }
+};
+
+
+class QColorShower : public QWidget
+{
+ Q_OBJECT
+public:
+ QColorShower( QWidget *parent, const char *name = 0 );
+
+ //things that don't emit signals
+ void setHsv( int h, int s, int v );
+
+ int currentAlpha() const { return alphaEd->val(); }
+ void setCurrentAlpha( int a ) { alphaEd->setNum( a ); }
+ void showAlpha( bool b );
+
+
+ QRgb currentColor() const { return curCol; }
+
+public slots:
+ void setRgb( QRgb rgb );
+
+signals:
+ void newCol( QRgb rgb );
+private slots:
+ void rgbEd();
+ void hsvEd();
+private:
+ void showCurrentColor();
+ int hue, sat, val;
+ QRgb curCol;
+ QColNumLineEdit *hEd;
+ QColNumLineEdit *sEd;
+ QColNumLineEdit *vEd;
+ QColNumLineEdit *rEd;
+ QColNumLineEdit *gEd;
+ QColNumLineEdit *bEd;
+ QColNumLineEdit *alphaEd;
+ QLabel *alphaLab;
+ QColorShowLabel *lab;
+ bool rgbOriginal;
+};
+
+class QColorShowLabel : public QFrame
+{
+ Q_OBJECT
+
+public:
+ QColorShowLabel( QWidget *parent ) :QFrame( parent ) {
+ setFrameStyle( QFrame::Panel|QFrame::Sunken );
+ setBackgroundMode( PaletteBackground );
+ setAcceptDrops( TRUE );
+ mousePressed = FALSE;
+ }
+ void setColor( QColor c ) { col = c; }
+
+signals:
+ void colorDropped( QRgb );
+
+protected:
+ void drawContents( QPainter *p );
+ void mousePressEvent( QMouseEvent *e );
+ void mouseReleaseEvent( QMouseEvent *e );
+
+private:
+ QColor col;
+ bool mousePressed;
+ QPoint pressPos;
+
+};
+
+void QColorShowLabel::drawContents( QPainter *p )
+{
+ p->fillRect( contentsRect(), col );
+}
+
+void QColorShower::showAlpha( bool b )
+{
+ if ( b ) {
+ alphaLab->show();
+ alphaEd->show();
+ } else {
+ alphaLab->hide();
+ alphaEd->hide();
+ }
+}
+
+void QColorShowLabel::mousePressEvent( QMouseEvent *e )
+{
+ mousePressed = TRUE;
+ pressPos = e->pos();
+}
+
+void QColorShowLabel::mouseReleaseEvent( QMouseEvent * )
+{
+ if ( !mousePressed )
+ return;
+ mousePressed = FALSE;
+}
+
+QColorShower::QColorShower( QWidget *parent, const char *name )
+ :QWidget( parent, name)
+{
+ curCol = qRgb( -1, -1, -1 );
+ QColIntValidator *val256 = new QColIntValidator( 0, 255, this );
+ QColIntValidator *val360 = new QColIntValidator( 0, 360, this );
+
+ QGridLayout *gl = new QGridLayout( this, 1, 1, 2 );
+ gl->setMargin( 0 );
+ lab = new QColorShowLabel( this );
+ lab->setMinimumWidth( 60 ); //###
+ gl->addMultiCellWidget(lab, 0,-1,0,0);
+ connect( lab, SIGNAL( colorDropped(QRgb) ),
+ this, SIGNAL( newCol(QRgb) ) );
+ connect( lab, SIGNAL( colorDropped(QRgb) ),
+ this, SLOT( setRgb(QRgb) ) );
+
+ hEd = new QColNumLineEdit( this );
+ hEd->setValidator( val360 );
+ QLabel *l = new QLabel( hEd, OColorDialog::tr("Hue:"), this );
+ l->setAlignment( AlignRight|AlignVCenter );
+ gl->addWidget( l, 0, 1 );
+ gl->addWidget( hEd, 0, 2 );
+
+ sEd = new QColNumLineEdit( this );
+ sEd->setValidator( val256 );
+ l = new QLabel( sEd, OColorDialog::tr("Sat:"), this );
+ l->setAlignment( AlignRight|AlignVCenter );
+ gl->addWidget( l, 1, 1 );
+ gl->addWidget( sEd, 1, 2 );
+
+ vEd = new QColNumLineEdit( this );
+ vEd->setValidator( val256 );
+ l = new QLabel( vEd, OColorDialog::tr("Val:"), this );
+ l->setAlignment( AlignRight|AlignVCenter );
+ gl->addWidget( l, 2, 1 );
+ gl->addWidget( vEd, 2, 2 );
+
+ rEd = new QColNumLineEdit( this );
+ rEd->setValidator( val256 );
+ l = new QLabel( rEd, OColorDialog::tr("Red:"), this );
+ l->setAlignment( AlignRight|AlignVCenter );
+ gl->addWidget( l, 0, 3 );
+ gl->addWidget( rEd, 0, 4 );
+
+ gEd = new QColNumLineEdit( this );
+ gEd->setValidator( val256 );
+ l = new QLabel( gEd, OColorDialog::tr("Green:"), this );
+ l->setAlignment( AlignRight|AlignVCenter );
+ gl->addWidget( l, 1, 3 );
+ gl->addWidget( gEd, 1, 4 );
+
+ bEd = new QColNumLineEdit( this );
+ bEd->setValidator( val256 );
+ l = new QLabel( bEd, OColorDialog::tr("Blue:"), this );
+ l->setAlignment( AlignRight|AlignVCenter );
+ gl->addWidget( l, 2, 3 );
+ gl->addWidget( bEd, 2, 4 );
+
+ alphaEd = new QColNumLineEdit( this );
+ alphaEd->setValidator( val256 );
+ alphaLab = new QLabel( alphaEd, OColorDialog::tr("Alpha channel:"), this );
+ alphaLab->setAlignment( AlignRight|AlignVCenter );
+ gl->addMultiCellWidget( alphaLab, 3, 3, 1, 3 );
+ gl->addWidget( alphaEd, 3, 4 );
+ alphaEd->hide();
+ alphaLab->hide();
+
+ connect( hEd, SIGNAL(textChanged(const QString&)), this, SLOT(hsvEd()) );
+ connect( sEd, SIGNAL(textChanged(const QString&)), this, SLOT(hsvEd()) );
+ connect( vEd, SIGNAL(textChanged(const QString&)), this, SLOT(hsvEd()) );
+
+ connect( rEd, SIGNAL(textChanged(const QString&)), this, SLOT(rgbEd()) );
+ connect( gEd, SIGNAL(textChanged(const QString&)), this, SLOT(rgbEd()) );
+ connect( bEd, SIGNAL(textChanged(const QString&)), this, SLOT(rgbEd()) );
+}
+
+void QColorShower::showCurrentColor()
+{
+ lab->setColor( currentColor() );
+ lab->repaint(FALSE); //###
+}
+
+void QColorShower::rgbEd()
+{
+ rgbOriginal = TRUE;
+ curCol = qRgb( rEd->val(), gEd->val(), bEd->val() );
+ rgb2hsv(currentColor(), hue, sat, val );
+
+ hEd->setNum( hue );
+ sEd->setNum( sat );
+ vEd->setNum( val );
+
+ showCurrentColor();
+ emit newCol( currentColor() );
+}
+
+void QColorShower::hsvEd()
+{
+ rgbOriginal = FALSE;
+ hue = hEd->val();
+ sat = sEd->val();
+ val = vEd->val();
+
+ curCol = QColor( hue, sat, val, QColor::Hsv ).rgb();
+
+ rEd->setNum( qRed(currentColor()) );
+ gEd->setNum( qGreen(currentColor()) );
+ bEd->setNum( qBlue(currentColor()) );
+
+ showCurrentColor();
+ emit newCol( currentColor() );
+}
+
+void QColorShower::setRgb( QRgb rgb )
+{
+ rgbOriginal = TRUE;
+ curCol = rgb;
+
+ rgb2hsv( currentColor(), hue, sat, val );
+
+ hEd->setNum( hue );
+ sEd->setNum( sat );
+ vEd->setNum( val );
+
+ rEd->setNum( qRed(currentColor()) );
+ gEd->setNum( qGreen(currentColor()) );
+ bEd->setNum( qBlue(currentColor()) );
+
+ showCurrentColor();
+}
+
+void QColorShower::setHsv( int h, int s, int v )
+{
+ rgbOriginal = FALSE;
+ hue = h; val = v; sat = s; //Range check###
+ curCol = QColor( hue, sat, val, QColor::Hsv ).rgb();
+
+ hEd->setNum( hue );
+ sEd->setNum( sat );
+ vEd->setNum( val );
+
+ rEd->setNum( qRed(currentColor()) );
+ gEd->setNum( qGreen(currentColor()) );
+ bEd->setNum( qBlue(currentColor()) );
+
+
+ showCurrentColor();
+}
+
+}
+
+class OColorDialogPrivate : public QObject
+{
+Q_OBJECT
+public:
+ OColorDialogPrivate( OColorDialog *p );
+ QRgb currentColor() const { return cs->currentColor(); }
+ void setCurrentColor( const QRgb& rgb );
+
+ int currentAlpha() const { return cs->currentAlpha(); }
+ void setCurrentAlpha( int a ) { cs->setCurrentAlpha( a ); }
+ void showAlpha( bool b ) { cs->showAlpha( b ); }
+
+private slots:
+ void newHsv( int h, int s, int v );
+ void newColorTypedIn( QRgb rgb );
+private:
+ QColorPicker *cp;
+ QColorLuminancePicker *lp;
+ QColorShower *cs;
+};
+
+//sets all widgets to display h,s,v
+void OColorDialogPrivate::newHsv( int h, int s, int v )
+{
+ cs->setHsv( h, s, v );
+ cp->setCol( h, s );
+ lp->setCol( h, s, v );
+}
+
+//sets all widgets to display rgb
+void OColorDialogPrivate::setCurrentColor( const QRgb& rgb )
+{
+ cs->setRgb( rgb );
+ newColorTypedIn( rgb );
+}
+
+//sets all widgets exept cs to display rgb
+void OColorDialogPrivate::newColorTypedIn( QRgb rgb )
+{
+ int h, s, v;
+ rgb2hsv(rgb, h, s, v );
+ cp->setCol( h, s );
+ lp->setCol( h, s, v);
+}
+
+OColorDialogPrivate::OColorDialogPrivate( OColorDialog *dialog ) :
+ QObject(dialog)
+{
+ int border = 2;
+ QVBoxLayout *topLay = new QVBoxLayout( dialog, border, 2 );
+
+ QHBoxLayout *pickLay = new QHBoxLayout( topLay );
+
+
+ cp = new QColorPicker( dialog );
+ cp->setFrameStyle( QFrame::Panel + QFrame::Sunken );
+ pickLay->addWidget( cp );
+
+ pickLay->addStretch();
+
+ lp = new QColorLuminancePicker( dialog );
+ lp->setFixedWidth( 20 ); //###
+ pickLay->addWidget( lp );
+
+ connect( cp, SIGNAL(newCol(int,int)), lp, SLOT(setCol(int,int)) );
+ connect( lp, SIGNAL(newHsv(int,int,int)), this, SLOT(newHsv(int,int,int)) );
+
+ topLay->addStretch();
+
+ cs = new QColorShower( dialog );
+ connect( cs, SIGNAL(newCol(QRgb)), this, SLOT(newColorTypedIn(QRgb)));
+ topLay->addWidget( cs );
+
+}
+
+
+// BEING REVISED: jo
+/*!
+ \class ColorDialog ColorDialog.h
+ \brief The OColorDialog class provides a dialog widget for specifying colors.
+ \ingroup dialogs
+
+ The color dialog's function is to allow users to choose colors -
+ for instance, you might use this in a drawing program to allow the
+ user to set the brush color.
+
+ This version of Qt only provides modal color dialogs. The static
+ getColor() function shows the dialog and allows the user to specify a color,
+ while getRgba() does the same but allows the user to specify a color with an
+ alpha channel (transparency) value.
+
+ The user can store customCount() different custom colors. The custom
+ colors are shared by all color dialogs, and remembered during the
+ execution of the program. Use setCustomColor() to set the
+ custom colors, and customColor() to get them.
+
+ <img src=qcolordlg-m.png> <img src=qcolordlg-w.png>
+*/
+
+/*!
+ Constructs a default color dialog. Use setColor() for setting an initial value.
+
+ \sa getColor()
+*/
+
+OColorDialog::OColorDialog(QWidget* parent, const char* name, bool modal) :
+ QDialog(parent, name, modal )
+{
+ d = new OColorDialogPrivate( this );
+}
+
+
+/*!
+ Pops up a modal color dialog letting the user choose a color and returns
+ that color. The color is initially set to \a initial. Returns an \link QColor::isValid() invalid\endlink color if the user cancels
+ the dialog. All colors allocated by the dialog will be deallocated
+ before this function returns.
+*/
+
+QColor OColorDialog::getColor( const QColor& initial, QWidget *parent,
+ const char *name )
+{
+ int allocContext = QColor::enterAllocContext();
+ OColorDialog *dlg = new OColorDialog( parent, name, TRUE ); //modal
+ if ( parent && parent->icon() && !parent->icon()->isNull() )
+ dlg->setIcon( *parent->icon() );
+ else if ( qApp->mainWidget() && qApp->mainWidget()->icon() && !qApp->mainWidget()->icon()->isNull() )
+ dlg->setIcon( *qApp->mainWidget()->icon() );
+
+ dlg->setCaption( OColorDialog::tr( "Select color" ) );
+ dlg->setColor( initial );
+ dlg->showMaximized();
+ int resultCode = dlg->exec();
+ QColor::leaveAllocContext();
+ QColor result;
+ if ( resultCode == QDialog::Accepted ) {
+ result = dlg->color();
+ } else {
+ result = initial;
+ }
+ QColor::destroyAllocContext(allocContext);
+ delete dlg;
+ return result;
+}
+
+
+/*!
+ Pops up a modal color dialog, letting the user choose a color and an
+ alpha channel value. The color+alpha is initially set to \a initial.
+
+ If \a ok is non-null, \c *ok is set to TRUE if the user clicked OK,
+ and FALSE if the user clicked Cancel.
+
+ If the user clicks Cancel the \a initial value is returned.
+*/
+
+QRgb OColorDialog::getRgba( const QRgb& initial, bool *ok,
+ QWidget *parent, const char* name )
+{
+ int allocContext = QColor::enterAllocContext();
+ OColorDialog *dlg = new OColorDialog( parent, name, TRUE ); //modal
+ dlg->setColor( initial );
+ dlg->setSelectedAlpha( qAlpha(initial) );
+ dlg->showMaximized();
+ int resultCode = dlg->exec();
+ QColor::leaveAllocContext();
+ QRgb result = initial;
+ if ( resultCode == QDialog::Accepted ) {
+ QRgb c = dlg->color().rgb();
+ int alpha = dlg->selectedAlpha();
+ result = qRgba( qRed(c), qGreen(c), qBlue(c), alpha );
+ }
+ if ( ok )
+ *ok = resultCode == QDialog::Accepted;
+
+ QColor::destroyAllocContext(allocContext);
+ delete dlg;
+ return result;
+}
+
+
+
+
+
+/*!
+ Returns the color currently selected in the dialog.
+
+ \sa setColor()
+*/
+
+QColor OColorDialog::color() const
+{
+ return QColor(d->currentColor());
+}
+
+
+/*! Destructs the dialog and frees any memory it allocated.
+
+*/
+
+OColorDialog::~OColorDialog()
+{
+ //d inherits QObject, so it is deleted by Qt.
+}
+
+
+/*!
+ Sets the color shown in the dialog to \a c.
+
+ \sa color()
+*/
+
+void OColorDialog::setColor( const QColor& c )
+{
+ d->setCurrentColor( c.rgb() );
+}
+
+
+
+
+/*!
+ Sets the initial alpha channel value to \a a, and show the alpha channel
+ entry box.
+*/
+
+void OColorDialog::setSelectedAlpha( int a )
+{
+ d->showAlpha( TRUE );
+ d->setCurrentAlpha( a );
+}
+
+
+/*!
+ Returns the value selected for the alpha channel.
+*/
+
+int OColorDialog::selectedAlpha() const
+{
+ return d->currentAlpha();
+}
+
+#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 @@
+/****************************************************************************
+** $Id$
+**
+** Definition of OColorDialog class
+**
+** Created : 990222
+**
+** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
+**
+** This file is part of the dialogs module of the Qt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.QPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for QPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef OColorDialog_H
+#define OColorDialog_H
+
+#ifndef QT_H
+#include <qdialog.h>
+#endif // QT_H
+
+class OColorDialogPrivate;
+
+/*
+ * @class OColorDialog
+ * @brief The OColorDialog class is a copy of QColorDialog for use in Opie.
+ *
+ * OColorDialog is a copy of TrollTech's QColorDialog for use in Opie. The default
+ * build of QT/Embedded used by Opie does not include QColorDialog, so it is provided
+ * here. It is renamed to prevent conflicts in the event the QColorDialog is included
+ * at a later date in QP/E.
+ *
+ * See http://doc.trolltech.com/2.3/qcolordialog.html for complete documentation of
+ * QColorDialog.
+ */
+class Q_EXPORT OColorDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ static QColor getColor( const QColor&, QWidget *parent=0, const char* name=0 );
+ static QRgb getRgba( const QRgb&, bool* ok = 0,
+ QWidget *parent=0, const char* name=0 );
+
+private:
+ ~OColorDialog();
+
+ // FIXME add WFlags? -zecke
+ OColorDialog( QWidget* parent=0, const char* name=0, bool modal=FALSE );
+ void setColor( const QColor& );
+ QColor color() const;
+
+private:
+ void setSelectedAlpha( int );
+ int selectedAlpha() const;
+private:
+ OColorDialogPrivate *d;
+ friend class OColorDialogPrivate;
+
+private: // Disabled copy constructor and operator=
+#if defined(Q_DISABLE_COPY)
+ OColorDialog( const OColorDialog & );
+ OColorDialog& operator=( const OColorDialog & );
+#endif
+};
+
+#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 @@
+/*
+                This file is part of the Opie Project
+
+              Copyright (c) 2002 S. Prud'homme <prudhomme@laposte.net>
+              Dan Williams <williamsdr@acm.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include "colorpopupmenu.h"
+#include "colordialog.h"
+
+#include <qlayout.h>
+#include <qpainter.h>
+
+OColorPanelButton::OColorPanelButton( const QColor& color, QWidget* parent, const char* name )
+ : QFrame( parent, name )
+{
+ m_color = color;
+
+ setFixedSize( 16, 16 );
+ setActive( FALSE );
+}
+
+OColorPanelButton::~OColorPanelButton()
+{
+}
+
+void OColorPanelButton::setActive( bool active )
+{
+ m_active = active;
+
+ if ( m_active ) {
+ setFrameStyle( Panel | Sunken );
+ } else {
+ setFrameStyle( NoFrame );
+ }
+}
+
+void OColorPanelButton::enterEvent( QEvent* )
+{
+ if ( !m_active ) {
+ setFrameStyle( Panel | Sunken );
+ }
+}
+
+void OColorPanelButton::leaveEvent( QEvent* )
+{
+ if ( !m_active ) {
+ setFrameStyle( NoFrame );
+ }
+}
+
+void OColorPanelButton::paintEvent( QPaintEvent* e )
+{
+ QFrame::paintEvent( e );
+
+ QPainter painter;
+ painter.begin( this );
+ painter.fillRect( 2, 2, 12, 12, m_color );
+ painter.setPen( Qt::black );
+ painter.drawRect( 2, 2, 12, 12 );
+ painter.end();
+}
+
+void OColorPanelButton::mouseReleaseEvent( QMouseEvent* )
+{
+ emit selected( m_color );
+}
+
+OColorPopupMenu::OColorPopupMenu( const QColor& color, QWidget* parent, const char* name )
+ : QPopupMenu( parent, name )
+{
+ m_color = color;
+
+ colorPanel = new QWidget( this );
+
+ colorLayout = new QGridLayout(colorPanel, 5, 6);
+
+ addColor(QColor(255, 255, 255), 0, 1);
+ addColor(QColor(192, 192, 192), 0, 2);
+ addColor(QColor(128, 128, 128), 0, 3);
+ addColor(QColor(64, 64, 64), 0, 4);
+ addColor(QColor(0, 0, 0), 0, 5);
+
+ addColor(QColor(255, 0, 0), 1, 0);
+ addColor(QColor(255, 128, 0), 1, 1);
+ addColor(QColor(255, 255, 0), 1, 2);
+ addColor(QColor(128, 255, 0), 1, 3);
+ addColor(QColor(0, 255, 0), 1, 4);
+ addColor(QColor(0, 255, 128), 1, 5);
+
+ addColor(QColor(128, 0, 0), 2, 0);
+ addColor(QColor(128, 64, 0), 2, 1);
+ addColor(QColor(128, 128, 0), 2, 2);
+ addColor(QColor(64, 128, 0), 2, 3);
+ addColor(QColor(0, 128, 0), 2, 4);
+ addColor(QColor(0, 128, 64), 2, 5);
+
+ addColor(QColor(0, 255, 255), 3, 0);
+ addColor(QColor(0, 128, 255), 3, 1);
+ addColor(QColor(0, 0, 255), 3, 2);
+ addColor(QColor(128, 0, 255), 3, 3);
+ addColor(QColor(255, 0, 255), 3, 4);
+ addColor(QColor(255, 0, 128), 3, 5);
+
+ addColor(QColor(0, 128, 128), 4, 0);
+ addColor(QColor(0, 64, 128), 4, 1);
+ addColor(QColor(0, 0, 128), 4, 2);
+ addColor(QColor(64, 0, 128), 4, 3);
+ addColor(QColor(128, 0, 128), 4, 4);
+ addColor(QColor(128, 0, 64), 4, 5);
+
+ insertItem( colorPanel );
+ insertSeparator();
+ insertItem(tr("More"),this,SLOT( moreColorClicked()));
+ /*
+ QAction* chooseColorAction = new QAction( tr( "More" ), tr( "More..." ), 0, colorPanel, "More" );
+ connect( chooseColorAction, SIGNAL( activated() ), this, SLOT( moreColorClicked() ) );
+ chooseColorAction->addTo( this );
+ */
+ activateItemAt( 0 );
+}
+
+OColorPopupMenu::~OColorPopupMenu()
+{
+}
+
+void OColorPopupMenu::addColor( const QColor& color, int row, int col )
+{
+ OColorPanelButton* panelButton = new OColorPanelButton( color, colorPanel );
+ connect( panelButton, SIGNAL( selected(const QColor&) ), this, SLOT( buttonSelected(const QColor&) ) );
+ colorLayout->addWidget( panelButton, row, col );
+}
+
+void OColorPopupMenu::buttonSelected( const QColor& color )
+{
+ m_color = color;
+ emit colorSelected( color );
+ hide();
+}
+
+void OColorPopupMenu::moreColorClicked()
+{
+ QColor color = OColorDialog::getColor( m_color );
+ m_color = color;
+ emit colorSelected( color );
+ hide();
+}
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 @@
+/*
+                This file is part of the Opie Project
+
+              Copyright (c) 2002 S. Prud'homme <prudhomme@laposte.net>
+              Dan Williams <williamsdr@acm.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef COLORPOPUPMENU_H
+#define COLORPOPUPMENU_H
+
+#include <qframe.h>
+#include <qpopupmenu.h>
+
+class QWidget;
+class QGridLayout;
+
+/**
+ * @class OColorPanelButton
+ * @brief The OColorPanelButton class provides a button for color selection.
+ *
+ * @see OColorPopupMenu
+ *
+ * The OColorPanelButton class provides a button for color selection. The button
+ * is drawn with the desired color and no border. This class is used internally
+ * by the OColorPopupMenu class to displaying colors in its menu.
+ */
+class OColorPanelButton : public QFrame
+{
+ Q_OBJECT
+
+public:
+
+/**
+ * @fn OColorPanelButton( const QColor& color, QWidget* parent = 0, const char* name = 0 )
+ * @brief Object constructor.
+ *
+ * @param color Desired color.
+ * @param parent Pointer to parent of this control.
+ * @param name Name of control.
+ *
+ * Constructs a new ColorPanelButton control with parent, name and desired color.
+ */
+ OColorPanelButton(const QColor& color, QWidget* parent = 0, const char* name = 0);
+
+/**
+ * @fn ~OColorPanelButton()
+ * @brief Object destructor.
+ */
+ ~OColorPanelButton();
+
+/**
+ * @fn setActive( bool active )
+ * @brief Sets button selection state.
+ *
+ * @param active Boolean indicator of new button state.
+ *
+ * Changes button selection state. If button is selected, a highlighted border
+ * is drawn.
+ */
+ void setActive(bool active);
+
+/**
+ * @fn enterEvent( QEvent* e )
+ * @brief Reimplemented for internal reasons.
+ *
+ * @param e Event currently being processed.
+ *
+ * Reimplemented to ensure correct display of button based on whether it is
+ * active or not.
+ */
+ void enterEvent(QEvent* e);
+
+/**
+ * @fn leaveEvent( QEvent* e )
+ * @brief Reimplemented for internal reasons.
+ *
+ * @param e Event currently being processed.
+ *
+ * Reimplemented to ensure correct display of button based on whether it is
+ * active or not.
+ */
+ void leaveEvent(QEvent* e);
+
+/**
+ * @fn paintEvent( QPaintEvent* e )
+ * @brief Reimplemented for internal reasons.
+ *
+ * @param e Event currently being processed.
+ * @reimp
+ * Reimplemented to ensure correct display of button.
+ */
+ void paintEvent(QPaintEvent* e);
+
+/**
+ * @fn mouseReleaseEvent( QMouseEvent* e )
+ * @brief Slot executed when button is pressed.
+ *
+ * @param e Mouse event currently being processed.
+ *
+ * @see selected()
+ *
+ * This slot executes when the button has been pressed. It emits the selected
+ * signal as notification that it has been pressed.
+ */
+ void mouseReleaseEvent(QMouseEvent* e);
+
+signals:
+
+/**
+ * @fn selected( const QColor& color )
+ * @brief Signal to indicate button has been pressed.
+ *
+ * @param color Button color.
+ *
+ * This signal is emitted when the button is pressed. It provides the color
+ * associated to this button.
+ */
+ void selected(const QColor&);
+
+private:
+ QColor m_color;
+ bool m_active : 1;
+ class ColorPanelButtonPrivate;
+ ColorPanelButtonPrivate *d;
+};
+
+/**
+ * @class OColorPopupMenu
+ * @brief The OColorPopupMenu class provides a small color selection
+ * popup menu.
+ *
+ * OColorPopupMenu is a derivation of TrollTech's QPopupMenu and provides
+ * a small color selection popup menu which can be attached to another control
+ * such as a toolbar button of menu item.
+ *
+ * The popup menu displays 30 default colors available in a grid, and also
+ * includes an option at the bottom to display a color selection dialog box for
+ * finer color control.
+ */
+class OColorPopupMenu : public QPopupMenu
+{
+ Q_OBJECT
+
+public:
+
+/**
+ * @fn OColorPopupMenu( const QColor& color, QWidget* parent = 0, const char* name = 0 )
+ * @brief Object constructor.
+ *
+ * @param color Initial color selected in menu.
+ * @param parent Pointer to parent of this control.
+ * @param name Name of control.
+ *
+ * Constructs a new OColorPopupMenu control with parent, name and initial color selected.
+ */
+ // FIXME add Wflags? -zecke
+ OColorPopupMenu( const QColor& color, QWidget* parent = 0, const char* name = 0 );
+
+/**
+ * @fn ~OColorPopupMenu()
+ * @brief Object destructor.
+ */
+ ~OColorPopupMenu();
+
+private:
+ class ColorPopupMenuPrivate;
+ ColorPopupMenuPrivate *d;
+ QColor m_color;
+ QWidget* colorPanel;
+ QGridLayout* colorLayout;
+
+/**
+ * @fn addColor( const QColor& color, int row, int col )
+ * @brief Adds color selection option to popup menu.
+ *
+ * @param color Color to be displayed in menu.
+ * @param row Row where color is to appear in menu.
+ * @param col Column where color is to appear in menu.
+ *
+ * Adds a color selection option to popup menu. Used internally when
+ * initially constructing the menu control.
+ */
+ void addColor( const QColor& color, int row, int col );
+
+signals:
+
+/**
+ * @fn colorSelected( const QColor& color )
+ * @brief Signal to indicate color chosen from the menu.
+ *
+ * @param color Color selected from the menu.
+ *
+ * This signal is emitted when a color has been selected either directly from
+ * the menu, or chosen from the color selection dialog.
+ */
+ void colorSelected( const QColor& color );
+
+protected slots:
+
+/**
+ * @fn buttonSelected( const QColor& color )
+ * @brief Slot to process selected color.
+ *
+ * @param color Color selected from the menu.
+ *
+ * @see colorSelected()
+ *
+ * This slot executes when a color has been selected from the menu. It performs
+ * two functions:
+ * - Emit the colorSelected signal with the color selected.
+ * - Hide the menu.
+ */
+ void buttonSelected( const QColor& color );
+
+/**
+ * @fn moreColorClicked()
+ * @brief Slot to process display color selection dialog.
+ *
+ * @see colorSelected()
+ *
+ * This slot executes when the 'More...' option is selected at the bottom of the menu.
+ * It performs the following functions:
+ * - Constructs and executes a OColorDialog to allow finer color selection.
+ * - Emit the colorSelected signal with the color selected.
+ * - Hide the menu.
+ */
+ void moreColorClicked();
+};
+
+#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 @@
+ config LIBOPIE
+ boolean "libopie1 (compatibility only, use libopie2* for new applications)"
+ default "n"
+ 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 @@
+TEMPLATE = lib
+CONFIG += qte warn_on
+HEADERS = ofontmenu.h \
+ ocolorbutton.h \
+ ofiledialog.h ofileselector.h \
+ ofileselector_p.h \
+ ocheckitem.h \
+ xmltree.h \
+ colordialog.h colorpopupmenu.h \
+ oclickablelabel.h oprocctrl.h \
+ oprocess.h odevice.h odevicebutton.h \
+ otimepicker.h otabwidget.h \
+ otabbar.h otabinfo.h \
+ ofontselector.h \
+ pim/opimrecord.h \
+ pim/otodo.h \
+ pim/orecordlist.h \
+ pim/opimaccesstemplate.h \
+ pim/opimaccessbackend.h \
+ pim/otodoaccess.h \
+ pim/otodoaccessbackend.h \
+ pim/oconversion.h \
+ pim/ocontact.h \
+ pim/ocontactfields.h \
+ pim/ocontactaccess.h \
+ pim/ocontactaccessbackend.h \
+ pim/ocontactaccessbackend_xml.h \
+ pim/ocontactaccessbackend_vcard.h \
+ pim/obackendfactory.h \
+ pim/opimcache.h \
+ pim/otodoaccessvcal.h \
+ pim/orecur.h \
+ pim/opimstate.h \
+ pim/opimxrefpartner.h \
+ pim/opimxref.h \
+ pim/opimxrefmanager.h \
+ pim/opimmaintainer.h \
+ pim/opimnotify.h \
+ pim/opimnotifymanager.h \
+ pim/opimmainwindow.h \
+ pim/opimresolver.h \
+ pim/oevent.h \
+ pim/otimezone.h \
+ pim/odatebookaccess.h \
+ pim/odatebookaccessbackend.h \
+ pim/odatebookaccessbackend_xml.h \
+ orecurrancewidget.h \
+ oticker.h owait.h
+
+SOURCES = ofontmenu.cc \
+ ocolorbutton.cpp \
+ sharp_compat.cpp \
+ xmltree.cc \
+ ofiledialog.cc ofileselector.cpp \
+ ocheckitem.cpp \
+ colordialog.cpp \
+ colorpopupmenu.cpp oclickablelabel.cpp \
+ oprocctrl.cpp oprocess.cpp \
+ odevice.cpp odevicebutton.cpp otimepicker.cpp \
+ otabwidget.cpp otabbar.cpp \
+ ofontselector.cpp \
+ pim/otodo.cpp \
+ pim/opimrecord.cpp \
+ pim/otodoaccess.cpp \
+ pim/otodoaccessbackend.cpp \
+ pim/otodoaccessxml.cpp \
+ pim/oconversion.cpp \
+ pim/ocontact.cpp \
+ pim/ocontactfields.cpp \
+ pim/ocontactaccess.cpp \
+ pim/ocontactaccessbackend_vcard.cpp \
+ pim/ocontactaccessbackend_xml.cpp \
+ pim/otodoaccessvcal.cpp \
+ pim/orecur.cpp \
+ pim/opimstate.cpp \
+ pim/opimxrefpartner.cpp \
+ pim/opimxref.cpp \
+ pim/opimxrefmanager.cpp \
+ pim/opimmaintainer.cpp \
+ pim/opimnotify.cpp \
+ pim/opimnotifymanager.cpp \
+ pim/opimmainwindow.cpp \
+ pim/opimresolver.cpp \
+ pim/oevent.cpp \
+ pim/otimezone.cpp \
+ pim/odatebookaccess.cpp \
+ pim/odatebookaccessbackend.cpp \
+ pim/odatebookaccessbackend_xml.cpp \
+ orecurrancewidget.cpp \
+ oticker.cpp owait.cpp
+
+TARGET = opie
+INCLUDEPATH += $(OPIEDIR)/include
+DESTDIR = $(OPIEDIR)/lib$(PROJMAK)
+
+LIBS += -lqpe
+
+INTERFACES = otimepickerbase.ui orecurrancebase.ui
+TARGET = opie
+
+
+include ( $(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 @@
+Package: libopie1
+Files: lib/libopie.so.1.0.0 lib/libopie.so.1.0 lib/libopie.so.1
+Priority: optional
+Section: opie/system
+Maintainer: Opie Team <opie@handhelds.org>
+Architecture: arm
+Depends: libqte2 (>=$QTE_VERSION), libqpe1, opie-pics
+Provides: libopie
+Replaces: libopie
+Description: Opie library
+Version: $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 @@
+#!/bin/sh
+
+[ -x /sbin/ldconfig ] && /sbin/ldconfig
+exit 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 @@
+/*
+ This work is derived from:
+ ----
+ The Loki Library
+ Copyright (c) 2001 by Andrei Alexandrescu
+ This code accompanies the book:
+ Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+ Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+ Permission to use, copy, modify, distribute and sell this software for any
+ purpose is hereby granted without fee, provided that the above copyright
+ notice appear in all copies and that both that copyright notice and this
+ permission notice appear in supporting documentation.
+ The author or Addison-Welsey Longman make no representations about the
+ suitability of this software for any purpose. It is provided "as is"
+ without express or implied warranty.
+ ----
+
+ And KGenericFactor et all from Simon Hausmann <tronical@kde.org>
+
+*/
+
+#include <qstring.h>
+#include <qmetaobject.h>
+
+#include <qtopia/qcom.h>
+#include <qtopia/applicationinterface.h>
+
+namespace Opie {
+ struct NullType;
+
+ template <class T, class U>
+ struct Typelist
+ {
+ typedef T Head;
+ typedef U Tail;
+ };
+ template<
+ typename T1 = NullType, typename T2 = NullType, typename T3 = NullType,
+ typename T4 = NullType, typename T5 = NullType, typename T6 = NullType,
+ typename T7 = NullType, typename T8 = NullType, typename T9 = NullType,
+ typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
+ typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
+ typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
+ >
+ struct MakeTypelist{
+ private:
+ typedef typename MakeTypelist
+ <
+ T2 , T3 , T4 ,
+ T5 , T6 , T7 ,
+ T8 , T9 , T10,
+ T11, T12, T13,
+ T14, T15, T16,
+ T17, T18
+ >
+ ::Result TailResult;
+
+public:
+ typedef Typelist<T1, TailResult> Result;
+};
+
+template<>
+struct MakeTypelist<>
+{
+ typedef NullType Result;
+};
+
+}
+
+/**
+ * To allow your application to be quick launched some one needs
+ * to create the QWidget.
+ * This is this factory. Make surce your widget has static QString Widget::appName()
+ * as one of its functions.
+ *
+ * This template takes one QWidget and initialized it in the form of
+ * MyWidget::MyWidget( QWidget* parent, const char* name, WFlags f );
+ *
+ * To use it on your app do that:
+ * typedef OApplicationFactory<MyWidget> MyFactory;
+ * OPIE_EXPORT_APP( MyFactory )
+ *
+ */
+template <class Product>
+struct OApplicationFactory : public ApplicationInterface {
+ QRESULT queryInterface( const QUuid &uuid, QUnknownInterface **iface ) {
+ *iface = 0;
+ if ( uuid == IID_QUnknown ) *iface = this;
+ else if ( uuid == IID_QtopiaApplication ) *iface = this;
+ else return QS_FALSE;
+ (*iface)->addRef();
+ return QS_OK;
+ }
+
+ /*
+ *
+ */
+ virtual QWidget *createMainWindow( const QString& appName, QWidget* parent,
+ const char* name, Qt::WFlags f ) {
+ if (appName == Product::appName() )
+ return new Product(parent, name, f );
+ else
+ return 0l;
+ }
+
+ virtual QStringList applications()const {
+ QStringList list;
+ list << Product::appName() ;
+
+ return list;
+ }
+ Q_REFCOUNT
+
+};
+
+
+/* Internal */
+
+template< class Product >
+struct OPrivate {
+ inline static QWidget *multiFactory( const QString& appName, QWidget* parent,
+ const char* name, Qt::WFlags fl ) {
+ if ( appName == Product::appName() )
+ return new Product( parent, name, fl );
+ else
+ return 0;
+ }
+
+ inline static QStringList multiString( const QStringList& _list ) {
+ QStringList list = _list;
+ list << Product::appName();
+ return list;
+ }
+};
+
+template <>
+struct OPrivate<Opie::NullType > {
+ inline static QWidget* multiFactory ( const QString& , QWidget* ,
+ const char* , Qt::WFlags ) {
+ return 0l;
+ }
+ inline static QStringList multiString( const QStringList& _list ) {
+ return _list;
+ }
+};
+
+/*
+template <>
+struct OPrivate <Opie::NullType, Opie::NullType > {
+ inline static QWidget* multiFactory( const QString& , QWidget* ,
+ const char* , Qt::WFlags ) {
+ return 0l;
+ }
+
+ inline static QStringList multiString( const QStringList& _list ) {
+ return _list;
+ }
+};
+*/
+
+template <class Product, class ProductListTail>
+struct OPrivate< Opie::Typelist<Product, ProductListTail> > {
+ inline static QWidget* multiFactory( const QString& appName, QWidget* parent,
+ const char* name, Qt::WFlags fl) {
+ QWidget* wid = OPrivate<Product>::multiFactory( appName, parent, name, fl );
+
+ if (!wid )
+ wid = OPrivate<ProductListTail>::multiFactory( appName, parent, name, fl );
+
+ return wid;
+ }
+
+ inline static QStringList multiString( const QStringList& _list ) {
+ QStringList list = _list;
+
+ list = OPrivate<Product>::multiString( list );
+ list = OPrivate<ProductListTail>::multiString( list );
+
+ return list;
+ }
+};
+
+
+
+
+
+
+
+
+/* Internal END */
+
+/*
+ * If you want to export more than one Widget use that function
+ * Make sure all your Widgets provide the appName() static method
+ * otherwise you'll get a compiler error
+ *
+ * typedef Opie::MakeTypeList<MyWidget, MyDialog, MyMediaPlayer >::Result MyTypes;
+ * OPIE_EXPORT_APP( OApplicationFactory<MyTypes> )
+ */
+
+template<class Product, class ProductListTail>
+struct OApplicationFactory< Opie::Typelist<Product, ProductListTail > >
+ : ApplicationInterface {
+ QRESULT queryInterface( const QUuid &uuid, QUnknownInterface **iface ) {
+ *iface = 0;
+ if ( uuid == IID_QUnknown ) *iface = this;
+ else if ( uuid ==IID_QtopiaApplication ) *iface = this;
+ else return QS_FALSE;
+ (*iface)->addRef();
+ return QS_OK;
+ }
+
+ QWidget* createMainWindow ( const QString& appName, QWidget* parent,
+ const char* name, Qt::WFlags fl ) {
+ qWarning("StringList is %s", applications().join(":").latin1() );
+ return OPrivate< Opie::Typelist<Product, ProductListTail > >::multiFactory( appName, parent, name, fl );
+ }
+
+ QStringList applications()const {
+ QStringList _list;
+ return OPrivate< Opie::Typelist<Product, ProductListTail> >::multiString( _list );
+ }
+
+ Q_REFCOUNT
+};
+
+
+/* If the library version should be build */
+#ifdef OPIE_APP_INTERFACE
+#define OPIE_EXPORT_APP( factory ) Q_EXPORT_INTERFACE() { Q_CREATE_INSTANCE( factory ) }
+#else
+
+#include <qpe/qpeapplication.h>
+
+#define OPIE_EXPORT_APP( Factory ) \
+int main( int argc, char **argv ) { \
+ QPEApplication a(argc, argv ); \
+ QWidget *mw = 0;\
+\
+ /* method from TT */ \
+ QString executableName = QString::fromLatin1( argv[0] ); \
+ executableName = executableName.right(executableName.length() \
+ - executableName.findRev('/') - 1); \
+ \
+ Factory f; \
+ QStringList list = f.applications(); \
+ if (list.contains(executableName) ) \
+ mw = f.createMainWindow(executableName, 0, 0, 0 ); \
+ else \
+ mw = f.createMainWindow( list[0], 0, 0, 0 ); \
+\
+ if( mw ) { \
+ if ( mw->metaObject()->slotNames().contains("setDocument(const QString&)" ) ) \
+ a.showMainDocumentWidget( mw ); \
+ else \
+ a.showMainWidget( mw ); \
+\
+ int rv = a.exec(); \
+ delete mw; \
+ return rv; \
+ }else \
+ return -1; \
+}
+#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 @@
+/**********************************************************************
+** Copyright (C) 2002 Stefan Eilers (se, eilers.stefan@epost.de
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Library General Public License version 2 as published by the
+** Free Software Foundation and appearing in the file LICENSE.GPL
+** included in the packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**********************************************************************/
+
+
+#include "ocheckitem.h"
+
+/**
+ * Constructs an CheckItem with a QTable as parent
+ * and a sort key for.
+ * The sort key will be used by QTable to sort the table later
+ * @param t The parent QTable where the check item belongs
+ * @param key A sort key
+ */
+OCheckItem::OCheckItem( QTable *t, const QString &key )
+ : QTableItem( t, Never, "" ), m_checked( FALSE ), m_sortKey( key )
+{
+}
+
+/**
+ * reimplemted for internal reasons
+ * @return Returns the sort key of the Item
+ * @see QTableItem
+ */
+QString OCheckItem::key() const
+{
+ return m_sortKey;
+}
+
+/**
+ * This method can check or uncheck the item. It will
+ * call QTable to update the cell.
+ *
+ * @param b Whether to check or uncheck the item
+ */
+void OCheckItem::setChecked( bool b )
+{
+ m_checked = b;
+ table()->updateCell( row(), col() );
+}
+
+/**
+ * This will toggle the item. If it is checked it'll get
+ * unchecked by this method or vice versa.
+ */
+void OCheckItem::toggle()
+{
+ m_checked = !m_checked;
+}
+
+/**
+ * This will return the state of the item.
+ *
+ * @return Returns true if the item is checked
+ */
+bool OCheckItem::isChecked() const
+{
+ return m_checked;
+}
+
+/**
+ * @internal
+ * This paints the item
+ */
+void OCheckItem::paint( QPainter *p, const QColorGroup &cg, const QRect &cr,
+ bool )
+{
+ p->fillRect( 0, 0, cr.width(), cr.height(), cg.brush( QColorGroup::Base ) );
+
+ int marg = ( cr.width() - BoxSize ) / 2;
+ int x = 0;
+ int y = ( cr.height() - BoxSize ) / 2;
+ p->setPen( QPen( cg.text() ) );
+ p->drawRect( x + marg, y, BoxSize, BoxSize );
+ p->drawRect( x + marg+1, y+1, BoxSize-2, BoxSize-2 );
+ p->setPen( darkGreen );
+ x += 1;
+ y += 1;
+ if ( m_checked ) {
+ QPointArray a( 7*2 );
+ int i, xx, yy;
+ xx = x+1+marg;
+ yy = y+2;
+ for ( i=0; i<3; i++ ) {
+ a.setPoint( 2*i, xx, yy );
+ a.setPoint( 2*i+1, xx, yy+2 );
+ xx++; yy++;
+ }
+ yy -= 2;
+ for ( i=3; i<7; i++ ) {
+ a.setPoint( 2*i, xx, yy );
+ a.setPoint( 2*i+1, xx, yy+2 );
+ xx++; yy--;
+ }
+ p->drawLineSegments( a );
+ }
+}
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 @@
+/**********************************************************************
+** Copyright (C) 2002 Stefan Eilers (se, eilers.stefan@epost.de)
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Library General Public License version 2 as published by the
+** Free Software Foundation and appearing in the file LICENSE.GPL
+** included in the packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**********************************************************************/
+#include <qtable.h>
+
+#ifndef CHECKITEM_H__
+#define CHECKITEM_H__
+
+/**
+ * This class represents a checkable QTableItem. This can
+ * be added to any QTable.
+ *
+ *
+ * @see QTable
+ * @see QTableItem
+ * @short An checkable QTableItem
+ * @version 1.0
+ * @author Stefan Eilers ( eilers@handhelds.org )
+ */
+
+class OCheckItem : public QTableItem
+{
+public:
+ /** The size of a box currently unused */
+ enum Size { BoxSize = 10 };
+ OCheckItem( QTable *t, const QString &sortkey );
+
+ virtual void setChecked( bool b );
+ virtual void toggle();
+ bool isChecked() const;
+ /**
+ * @short Set the sort key
+ * @reimp
+ */
+ void setKey( const QString &key ) { m_sortKey = key; }
+ virtual QString key() const;
+
+ /**
+ * foo
+ * @internal
+ */
+ void paint( QPainter *p, const QColorGroup &cg, const QRect &cr, bool selected );
+
+ //static const int BoxSize = 10;
+
+private:
+ class OCheckItemPrivate;
+ OCheckItemPrivate *d;
+ bool m_checked: 1;
+ QString m_sortKey;
+
+};
+
+#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 @@
+#include "oclickablelabel.h"
+#include <stdio.h>
+
+/**
+ * This constructs the clickable ButtonLabel
+ *
+ * @param parent The parent of this label
+ * @param name A name of this label @see QObject
+ * @param fl The windowing flags
+ */
+OClickableLabel::OClickableLabel(QWidget* parent,
+ const char* name,
+ WFlags fl) :
+ QLabel(parent,name,fl)
+{
+ textInverted=false;
+ isToggle=false;
+ isDown=false;
+ showState(false);
+ setFrameShadow(Sunken);
+}
+
+/**
+ * This method makes the label behave as a toggle button
+ *
+ * @param t Whether or not to behave like a toggle button
+ */
+void OClickableLabel::setToggleButton(bool t) {
+ isToggle=t;
+}
+
+/**
+ * @internal
+ */
+void OClickableLabel::mousePressEvent( QMouseEvent * /*e*/ ) {
+ if (isToggle && isDown) {
+ showState(false);
+ } else {
+ showState(true);
+ }
+}
+
+/**
+ * @internal
+ */
+void OClickableLabel::mouseReleaseEvent( QMouseEvent *e ) {
+ if (rect().contains(e->pos()) && isToggle) isDown=!isDown;
+
+ if (isToggle && isDown) {
+ showState(true);
+ } else {
+ showState(false);
+ }
+
+ if (rect().contains(e->pos())) {
+ if (isToggle) {
+ emit toggled(isDown);
+ }
+ emit clicked();
+ }
+}
+
+/**
+ * @internal
+ */
+void OClickableLabel::mouseMoveEvent( QMouseEvent *e ) {
+ if (rect().contains(e->pos())) {
+ if (isToggle && isDown) {
+ showState(false);
+ } else {
+ showState(true);
+ }
+ } else {
+ if (isToggle && isDown) {
+ showState(true);
+ } else {
+ showState(false);
+ }
+ }
+}
+
+/**
+ * this toggles the label and inverts the color of
+ * the label
+ * @param on
+ */
+void OClickableLabel::showState(bool on) {
+ if (on) {
+ //setFrameShape(Panel);
+ setInverted(true);
+ setBackgroundMode(PaletteHighlight);
+ } else {
+ //setFrameShape(NoFrame);
+ setInverted(false);
+ setBackgroundMode(PaletteBackground);
+ }
+ repaint();
+}
+
+void OClickableLabel::setInverted(bool on) {
+ if ( (!textInverted && on) || (textInverted && !on) ) {
+ QPalette pal=palette();
+ QColor col=pal.color(QPalette::Normal, QColorGroup::Foreground);
+ col.setRgb(255-col.red(),255-col.green(),255-col.blue());
+ pal.setColor(QPalette::Normal, QColorGroup::Foreground, col);
+ setPalette(pal);
+ textInverted=!textInverted;
+ }
+}
+
+/**
+ * @param on if the Label is down or up
+ */
+void OClickableLabel::setOn(bool on) {
+ isDown=on;
+ showState(isDown);
+}
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 @@
+#ifndef CLICKABLELABEL
+#define CLICKABLELABEL
+
+#include <qlabel.h>
+
+/**
+ * This class is a special QLabel which can behave
+ * as a QPushButton or QToggleButton.
+ * The reason to use a clickable is if you want to save space
+ * or you want to skip the border of a normal button
+ *
+ * <pre>
+ * QLabel* lbl = new OClickableLabel( parent, "PushLabel" );
+ * lbl->setPixmap( "config" );
+ * QWhatsThis::add( lbl, tr("Click here to do something") );
+ * </pre>
+ *
+ * @short A Label behaving as button
+ * @author Hakan Ardo, Maximillian Reiß ( harlekin@handhelds.org )
+ * @see QLabel
+ * @see QPushButton
+ * @see QToggleButton
+ * @version 1.0
+ */
+
+class OClickableLabel: public QLabel
+{
+ Q_OBJECT
+public:
+ OClickableLabel(QWidget* parent = 0, const char* name = 0,
+ WFlags fl = 0);
+ void setToggleButton(bool t);
+
+ protected:
+ /** @internal */
+ void mousePressEvent( QMouseEvent *e );
+ /** @internal */
+ void mouseReleaseEvent( QMouseEvent *e );
+ /** @internal */
+ void mouseMoveEvent( QMouseEvent *e );
+
+ public slots:
+ void setOn(bool on);
+ signals:
+ /**
+ * emitted when the labels gets clicked
+ */
+ void clicked();
+
+ /**
+ * emitted when the labels gets toggled
+ * @param on the new new state of the label
+ */
+ void toggled(bool on);
+ private:
+ bool isToggle : 1;
+ bool isDown : 1;
+ bool textInverted : 1;
+
+ void showState(bool on);
+ void setInverted(bool on);
+
+ private:
+ class Private;
+ Private *d; // private d pointer
+};
+
+#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 @@
+/*
+               =. This file is part of the OPIE Project
+             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
+           .>+-=
+ _;:,     .>    :=|. This library is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This library is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include <opie/colorpopupmenu.h>
+#include <opie/ocolorbutton.h>
+
+#include <qpe/resource.h>
+
+struct OColorButtonPrivate {
+ QPopupMenu *m_menu;
+ QColor m_color;
+};
+
+
+/**
+ * This concstructs a Color Button with @param color as the start color
+ * It'll use a OColorPopupMenu internally
+ *
+ * @param parent The parent of the Color Button
+ * @param color The color from where to start on
+ * @param name @see QObject
+ */
+OColorButton::OColorButton ( QWidget *parent, const QColor &color, const char *name )
+ : QPushButton ( parent, name )
+{
+ d = new OColorButtonPrivate;
+
+ d-> m_menu = new OColorPopupMenu ( color, 0, 0 );
+ setPopup ( d-> m_menu );
+// setPopupDelay ( 0 );
+ connect ( d-> m_menu, SIGNAL( colorSelected(const QColor&)), this, SLOT( updateColor(const QColor&)));
+
+ updateColor ( color );
+
+ QSize s = sizeHint ( ) + QSize ( 12, 0 );
+ setMinimumSize ( s );
+ setMaximumSize ( s. width ( ) * 2, s. height ( ));
+}
+
+/**
+ * This destructs the object
+ */
+OColorButton::~OColorButton ( )
+{
+ delete d;
+}
+
+/**
+ * @return Returns the current color of the button
+ */
+QColor OColorButton::color ( ) const
+{
+ return d-> m_color;
+}
+
+/**
+ * This method sets the color of the button
+ * @param c The color to be set.
+ */
+void OColorButton::setColor ( const QColor &c )
+{
+ updateColor ( c );
+}
+
+/**
+ * @internal
+ */
+void OColorButton::updateColor ( const QColor &c )
+{
+ d-> m_color = c;
+
+ QImage img ( 16, 16, 32 );
+ img. fill ( 0 );
+
+ int r, g, b;
+ c. rgb ( &r, &g, &b );
+
+ int w = img. width ( );
+ int h = img. height ( );
+
+ int dx = w * 20 / 100; // 15%
+ int dy = h * 20 / 100;
+
+ for ( int y = 0; y < h; y++ ) {
+ for ( int x = 0; x < w; x++ ) {
+ double alpha = 1.0;
+
+ if ( x < dx )
+ alpha *= ( double ( x + 1 ) / dx );
+ else if ( x >= w - dx )
+ alpha *= ( double ( w - x ) / dx );
+ if ( y < dy )
+ alpha *= ( double ( y + 1 ) / dy );
+ else if ( y >= h - dy )
+ alpha *= ( double ( h - y ) / dy );
+
+ int a = int ( alpha * 255.0 );
+ if ( a < 0 )
+ a = 0;
+ if ( a > 255 )
+ a = 255;
+
+ img. setPixel ( x, y, qRgba ( r, g, b, a ));
+ }
+ }
+ img. setAlphaBuffer ( true );
+
+ QPixmap pix;
+ pix. convertFromImage ( img );
+ setPixmap ( pix );
+
+ emit colorSelected ( c );
+}
+
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 @@
+/*
+               =. This file is part of the OPIE Project
+             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
+           .>+-=
+ _;:,     .>    :=|. This library is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This library is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef __OPIE_OCOLORBUTTON_H__
+#define __OPIE_OCOLORBUTTON_H__
+
+#include <qpushbutton.h>
+
+class OColorButtonPrivate;
+class QColor;
+
+/**
+ *
+ * @short A Button which will show a OColorPopupMenu
+ * @author Robert Griebl ( sandman@handhelds.org )
+ * @version 1.0
+ * @see QPushButton
+ */
+class OColorButton : public QPushButton {
+ Q_OBJECT
+public:
+ // FIXME Wflags? -zecke
+ OColorButton ( QWidget *parent = 0, const QColor & = black, const char *name = 0 );
+ virtual ~OColorButton ( );
+
+ QColor color ( ) const;
+
+signals:
+ /**
+ * emitted when a color gets selected
+ */
+ void colorSelected ( const QColor & );
+
+public slots:
+ virtual void setColor ( const QColor & );
+
+protected slots:
+ /**
+ * @internal
+ */
+ virtual void updateColor ( const QColor & );
+
+private:
+ OColorButtonPrivate *d;
+};
+
+#endif
+
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 @@
+/* This file is part of the OPIE libraries
+ Copyright (C) 2002 Robert Griebl (sandman@handhelds.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <sys/time.h>
+#ifndef QT_NO_SOUND
+#include <linux/soundcard.h>
+#endif
+#include <math.h>
+
+
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qpe/sound.h>
+#include <qpe/resource.h>
+#include <qpe/config.h>
+#include <qpe/qcopenvelope_qws.h>
+
+#include "odevice.h"
+
+#include <qwindowsystem_qws.h>
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+// _IO and friends are only defined in kernel headers ...
+
+#define OD_IOC(dir,type,number,size) (( dir << 30 ) | ( type << 8 ) | ( number ) | ( size << 16 ))
+
+#define OD_IO(type,number) OD_IOC(0,type,number,0)
+#define OD_IOW(type,number,size) OD_IOC(1,type,number,sizeof(size))
+#define OD_IOR(type,number,size) OD_IOC(2,type,number,sizeof(size))
+#define OD_IORW(type,number,size) OD_IOC(3,type,number,sizeof(size))
+
+using namespace Opie;
+
+class ODeviceData {
+public:
+ QString m_vendorstr;
+ OVendor m_vendor;
+
+ QString m_modelstr;
+ OModel m_model;
+
+ QString m_systemstr;
+ OSystem m_system;
+
+ QString m_sysverstr;
+
+ Transformation m_rotation;
+ ODirection m_direction;
+
+ QValueList <ODeviceButton> *m_buttons;
+ uint m_holdtime;
+ QStrList *m_cpu_frequencies;
+
+};
+
+class iPAQ : public ODevice, public QWSServer::KeyboardFilter {
+protected:
+ virtual void init ( );
+ virtual void initButtons ( );
+
+public:
+ virtual bool setSoftSuspend ( bool soft );
+
+ virtual bool setDisplayBrightness ( int b );
+ virtual int displayBrightnessResolution ( ) const;
+
+ virtual void alarmSound ( );
+
+ virtual QValueList <OLed> ledList ( ) const;
+ virtual QValueList <OLedState> ledStateList ( OLed led ) const;
+ virtual OLedState ledState ( OLed led ) const;
+ virtual bool setLedState ( OLed led, OLedState st );
+
+ virtual bool hasLightSensor ( ) const;
+ virtual int readLightSensor ( );
+ virtual int lightSensorResolution ( ) const;
+
+protected:
+ virtual bool filter ( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat );
+ virtual void timerEvent ( QTimerEvent *te );
+
+ int m_power_timer;
+
+ OLedState m_leds [2];
+};
+
+class Jornada : public ODevice {
+protected:
+ virtual void init ( );
+ //virtual void initButtons ( );
+public:
+ virtual bool setSoftSuspend ( bool soft );
+ virtual bool setDisplayBrightness ( int b );
+ virtual int displayBrightnessResolution ( ) const;
+ static bool isJornada();
+
+};
+
+class Zaurus : public ODevice {
+protected:
+ virtual void init ( );
+ virtual void initButtons ( );
+
+public:
+ virtual bool setSoftSuspend ( bool soft );
+
+ virtual bool setDisplayBrightness ( int b );
+ virtual int displayBrightnessResolution ( ) const;
+
+ virtual void alarmSound ( );
+ virtual void keySound ( );
+ virtual void touchSound ( );
+
+ virtual QValueList <OLed> ledList ( ) const;
+ virtual QValueList <OLedState> ledStateList ( OLed led ) const;
+ virtual OLedState ledState ( OLed led ) const;
+ virtual bool setLedState ( OLed led, OLedState st );
+
+ bool hasHingeSensor() const;
+ OHingeStatus readHingeSensor();
+
+ static bool isZaurus();
+
+ // Does this break BC?
+ virtual bool suspend ( );
+ Transformation rotation ( ) const;
+ ODirection direction ( ) const;
+
+protected:
+ virtual void buzzer ( int snd );
+
+ OLedState m_leds [1];
+ bool m_embedix;
+ void virtual_hook( int id, void *data );
+};
+
+class SIMpad : public ODevice, public QWSServer::KeyboardFilter {
+protected:
+ virtual void init ( );
+ virtual void initButtons ( );
+
+public:
+ virtual bool setSoftSuspend ( bool soft );
+ virtual bool suspend();
+
+ virtual bool setDisplayStatus( bool on );
+ virtual bool setDisplayBrightness ( int b );
+ virtual int displayBrightnessResolution ( ) const;
+
+ virtual void alarmSound ( );
+
+ virtual QValueList <OLed> ledList ( ) const;
+ virtual QValueList <OLedState> ledStateList ( OLed led ) const;
+ virtual OLedState ledState ( OLed led ) const;
+ virtual bool setLedState ( OLed led, OLedState st );
+
+protected:
+ virtual bool filter ( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat );
+ virtual void timerEvent ( QTimerEvent *te );
+
+ int m_power_timer;
+
+ OLedState m_leds [1]; //FIXME check if really only one
+};
+
+class Ramses : public ODevice, public QWSServer::KeyboardFilter {
+protected:
+ virtual void init ( );
+
+public:
+ virtual bool setSoftSuspend ( bool soft );
+ virtual bool suspend ( );
+
+ virtual bool setDisplayStatus( bool on );
+ virtual bool setDisplayBrightness ( int b );
+ virtual int displayBrightnessResolution ( ) const;
+ virtual bool setDisplayContrast ( int b );
+ virtual int displayContrastResolution ( ) const;
+
+protected:
+ virtual bool filter ( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat );
+ virtual void timerEvent ( QTimerEvent *te );
+
+ int m_power_timer;
+};
+
+struct i_button {
+ uint model;
+ Qt::Key code;
+ char *utext;
+ char *pix;
+ char *fpressedservice;
+ char *fpressedaction;
+ char *fheldservice;
+ char *fheldaction;
+} ipaq_buttons [] = {
+ { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
+ Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
+ "devicebuttons/ipaq_calendar",
+ "datebook", "nextView()",
+ "today", "raise()" },
+ { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
+ Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
+ "devicebuttons/ipaq_contact",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+ { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx,
+ Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
+ "devicebuttons/ipaq_menu",
+ "QPE/TaskBar", "toggleMenu()",
+ "QPE/TaskBar", "toggleStartMenu()" },
+ { Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
+ Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
+ "devicebuttons/ipaq_mail",
+ "mail", "raise()",
+ "mail", "newMail()" },
+ { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
+ Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
+ "devicebuttons/ipaq_home",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
+ Qt::Key_F24, QT_TRANSLATE_NOOP("Button", "Record Button"),
+ "devicebuttons/ipaq_record",
+ "QPE/VMemo", "toggleRecord()",
+ "sound", "raise()" },
+};
+
+struct z_button {
+ Qt::Key code;
+ char *utext;
+ char *pix;
+ char *fpressedservice;
+ char *fpressedaction;
+ char *fheldservice;
+ char *fheldaction;
+} z_buttons [] = {
+ { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
+ "devicebuttons/z_calendar",
+ "datebook", "nextView()",
+ "today", "raise()" },
+ { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
+ "devicebuttons/z_contact",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+ { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
+ "devicebuttons/z_home",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
+ "devicebuttons/z_menu",
+ "QPE/TaskBar", "toggleMenu()",
+ "QPE/TaskBar", "toggleStartMenu()" },
+ { Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"),
+ "devicebuttons/z_mail",
+ "mail", "raise()",
+ "mail", "newMail()" },
+};
+
+struct z_button z_buttons_c700 [] = {
+ { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"),
+ "devicebuttons/z_calendar",
+ "datebook", "nextView()",
+ "today", "raise()" },
+ { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"),
+ "devicebuttons/z_contact",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+ { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"),
+ "devicebuttons/z_home",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"),
+ "devicebuttons/z_menu",
+ "QPE/TaskBar", "toggleMenu()",
+ "QPE/TaskBar", "toggleStartMenu()" },
+ { Qt::Key_F14, QT_TRANSLATE_NOOP("Button", "Display Rotate"),
+ "devicebuttons/z_hinge",
+ "QPE/Rotation", "rotateDefault()",
+ "QPE/Dummy", "doNothing()" },
+};
+
+struct s_button {
+ uint model;
+ Qt::Key code;
+ char *utext;
+ char *pix;
+ char *fpressedservice;
+ char *fpressedaction;
+ char *fheldservice;
+ char *fheldaction;
+} simpad_buttons [] = {
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Lower+Up"),
+ "devicebuttons/simpad_lower_up",
+ "datebook", "nextView()",
+ "today", "raise()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Lower+Down"),
+ "devicebuttons/simpad_lower_down",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Lower+Right"),
+ "devicebuttons/simpad_lower_right",
+ "QPE/TaskBar", "toggleMenu()",
+ "QPE/TaskBar", "toggleStartMenu()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Lower+Left"),
+ "devicebuttons/simpad_lower_left",
+ "mail", "raise()",
+ "mail", "newMail()" },
+
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F5, QT_TRANSLATE_NOOP("Button", "Upper+Up"),
+ "devicebuttons/simpad_upper_up",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F6, QT_TRANSLATE_NOOP("Button", "Upper+Down"),
+ "devicebuttons/simpad_upper_down",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F7, QT_TRANSLATE_NOOP("Button", "Upper+Right"),
+ "devicebuttons/simpad_upper_right",
+ "QPE/TaskBar", "toggleMenu()",
+ "QPE/TaskBar", "toggleStartMenu()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Upper+Left"),
+ "devicebuttons/simpad_upper_left",
+ "QPE/Rotation", "flip()",
+ "QPE/Rotation", "flip()" },
+ /*
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Lower+Upper"),
+ "devicebuttons/simpad_lower_upper",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus,
+ Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Lower+Upper"),
+ "devicebuttons/simpad_upper_lower",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+ */
+};
+
+class Yopy : public ODevice {
+protected:
+ virtual void init ( );
+ virtual void initButtons ( );
+
+public:
+ virtual bool suspend ( );
+
+ virtual bool setDisplayBrightness ( int b );
+ virtual int displayBrightnessResolution ( ) const;
+
+ static bool isYopy ( );
+};
+
+struct yopy_button {
+ Qt::Key code;
+ char *utext;
+ char *pix;
+ char *fpressedservice;
+ char *fpressedaction;
+ char *fheldservice;
+ char *fheldaction;
+} yopy_buttons [] = {
+ { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Action Button"),
+ "devicebuttons/yopy_action",
+ "datebook", "nextView()",
+ "today", "raise()" },
+ { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "OK Button"),
+ "devicebuttons/yopy_ok",
+ "addressbook", "raise()",
+ "addressbook", "beamBusinessCard()" },
+ { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "End Button"),
+ "devicebuttons/yopy_end",
+ "QPE/Launcher", "home()",
+ "buttonsettings", "raise()" },
+};
+
+static QCString makeChannel ( const char *str )
+{
+ if ( str && !::strchr ( str, '/' ))
+ return QCString ( "QPE/Application/" ) + str;
+ else
+ return str;
+}
+
+static inline bool isQWS()
+{
+ return qApp ? ( qApp-> type ( ) == QApplication::GuiServer ) : false;
+}
+
+ODevice *ODevice::inst ( )
+{
+ static ODevice *dev = 0;
+
+ if ( !dev ) {
+ if ( QFile::exists ( "/proc/hal/model" ))
+ dev = new iPAQ ( );
+ else if ( Zaurus::isZaurus() )
+ dev = new Zaurus ( );
+ else if ( QFile::exists ( "/proc/ucb1x00" ) && QFile::exists ( "/proc/cs3" ))
+ dev = new SIMpad ( );
+ else if ( Yopy::isYopy() )
+ dev = new Yopy ( );
+ else if ( Jornada::isJornada() )
+ dev = new Jornada ( );
+ else if ( QFile::exists ( "/proc/sys/board/sys_name" ))
+ dev = new Ramses ( );
+ else
+ dev = new ODevice ( );
+ dev-> init ( );
+ }
+ return dev;
+}
+
+
+/**************************************************
+ *
+ * common
+ *
+ **************************************************/
+
+
+ODevice::ODevice ( )
+{
+ d = new ODeviceData;
+
+ d-> m_modelstr = "Unknown";
+ d-> m_model = Model_Unknown;
+ d-> m_vendorstr = "Unknown";
+ d-> m_vendor = Vendor_Unknown;
+ d-> m_systemstr = "Unknown";
+ d-> m_system = System_Unknown;
+ d-> m_sysverstr = "0.0";
+ d-> m_rotation = Rot0;
+ d-> m_direction = CW;
+
+ d-> m_holdtime = 1000; // 1000ms
+ d-> m_buttons = 0;
+ d-> m_cpu_frequencies = new QStrList;
+}
+
+void ODevice::systemMessage ( const QCString &msg, const QByteArray & )
+{
+ if ( msg == "deviceButtonMappingChanged()" ) {
+ reloadButtonMapping ( );
+ }
+}
+
+void ODevice::init ( )
+{
+}
+
+/**
+ * This method initialises the button mapping
+ */
+void ODevice::initButtons ( )
+{
+ if ( d-> m_buttons )
+ return;
+
+ // Simulation uses iPAQ 3660 device buttons
+
+ qDebug ( "init Buttons" );
+ d-> m_buttons = new QValueList <ODeviceButton>;
+
+ for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) {
+ i_button *ib = ipaq_buttons + i;
+ ODeviceButton b;
+
+ if (( ib-> model & Model_iPAQ_H36xx ) == Model_iPAQ_H36xx ) {
+ b. setKeycode ( ib-> code );
+ b. setUserText ( QObject::tr ( "Button", ib-> utext ));
+ b. setPixmap ( Resource::loadPixmap ( ib-> pix ));
+ b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib-> fpressedservice ), ib-> fpressedaction ));
+ b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib-> fheldservice ), ib-> fheldaction ));
+ d-> m_buttons-> append ( b );
+ }
+ }
+ reloadButtonMapping ( );
+
+ QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
+ connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( systemMessage(const QCString&,const QByteArray&)));
+}
+
+ODevice::~ODevice ( )
+{
+// we leak m_devicebuttons and m_cpu_frequency
+// but it's a singleton and it is not so importantant
+// -zecke
+ delete d;
+}
+
+bool ODevice::setSoftSuspend ( bool /*soft*/ )
+{
+ return false;
+}
+
+//#include <linux/apm_bios.h>
+
+#define APM_IOC_SUSPEND OD_IO( 'A', 2 )
+
+/**
+ * This method will try to suspend the device
+ * It only works if the user is the QWS Server and the apm application
+ * is installed.
+ * It tries to suspend and then waits some time cause some distributions
+ * do have asynchronus apm implementations.
+ * This method will either fail and return false or it'll suspend the
+ * device and return once the device got woken up
+ *
+ * @return if the device got suspended
+ */
+bool ODevice::suspend ( )
+{
+ qDebug("ODevice::suspend");
+ if ( !isQWS( ) ) // only qwsserver is allowed to suspend
+ return false;
+
+ if ( d-> m_model == Model_Unknown ) // better don't suspend in qvfb / on unkown devices
+ return false;
+
+ bool res = false;
+
+ struct timeval tvs, tvn;
+ ::gettimeofday ( &tvs, 0 );
+
+ ::sync ( ); // flush fs caches
+ res = ( ::system ( "apm --suspend" ) == 0 );
+
+ // This is needed because the iPAQ apm implementation is asynchronous and we
+ // can not be sure when exactly the device is really suspended
+ // This can be deleted as soon as a stable familiar with a synchronous apm implementation exists.
+
+ if ( res ) {
+ do { // wait at most 1.5 sec: either suspend didn't work or the device resumed
+ ::usleep ( 200 * 1000 );
+ ::gettimeofday ( &tvn, 0 );
+ } while ((( tvn. tv_sec - tvs. tv_sec ) * 1000 + ( tvn. tv_usec - tvs. tv_usec ) / 1000 ) < 1500 );
+ }
+
+ return res;
+}
+
+//#include <linux/fb.h> better not rely on kernel headers in userspace ...
+
+#define FBIOBLANK OD_IO( 'F', 0x11 ) // 0x4611
+
+/* VESA Blanking Levels */
+#define VESA_NO_BLANKING 0
+#define VESA_VSYNC_SUSPEND 1
+#define VESA_HSYNC_SUSPEND 2
+#define VESA_POWERDOWN 3
+
+/**
+ * This sets the display on or off
+ */
+bool ODevice::setDisplayStatus ( bool on )
+{
+ qDebug("ODevice::setDisplayStatus(%d)", on);
+
+ if ( d-> m_model == Model_Unknown )
+ return false;
+
+ bool res = false;
+ int fd;
+
+#ifdef QT_QWS_DEVFS
+ if (( fd = ::open ( "/dev/fb/0", O_RDWR )) >= 0 ) {
+#else
+ if (( fd = ::open ( "/dev/fb0", O_RDWR )) >= 0 ) {
+#endif
+ res = ( ::ioctl ( fd, FBIOBLANK, on ? VESA_NO_BLANKING : VESA_POWERDOWN ) == 0 );
+ ::close ( fd );
+ }
+ return res;
+}
+
+/**
+ * This sets the display brightness
+ *
+ * @param p The brightness to be set on a scale from 0 to 255
+ * @return success or failure
+ */
+bool ODevice::setDisplayBrightness ( int p)
+{
+ Q_UNUSED( p )
+ return false;
+}
+
+/**
+ * @return returns the number of steppings on the brightness slider
+ * in the Light-'n-Power settings.
+ */
+int ODevice::displayBrightnessResolution ( ) const
+{
+ return 16;
+}
+
+/**
+ * This sets the display contrast
+ * @param p The contrast to be set on a scale from 0 to 255
+ * @return success or failure
+ */
+bool ODevice::setDisplayContrast ( int p)
+{
+ Q_UNUSED( p )
+ return false;
+}
+
+/**
+ * @return return the max value for the brightness settings slider
+ * or 0 if the device doesn't support setting of a contrast
+ */
+int ODevice::displayContrastResolution ( ) const
+{
+ return 0;
+}
+
+/**
+ * This returns the vendor as string
+ * @return Vendor as QString
+ */
+QString ODevice::vendorString ( ) const
+{
+ return d-> m_vendorstr;
+}
+
+/**
+ * This returns the vendor as one of the values of OVendor
+ * @return OVendor
+ */
+OVendor ODevice::vendor ( ) const
+{
+ return d-> m_vendor;
+}
+
+/**
+ * This returns the model as a string
+ * @return A string representing the model
+ */
+QString ODevice::modelString ( ) const
+{
+ return d-> m_modelstr;
+}
+
+/**
+ * This does return the OModel used
+ */
+OModel ODevice::model ( ) const
+{
+ return d-> m_model;
+}
+
+/**
+ * This does return the systen name
+ */
+QString ODevice::systemString ( ) const
+{
+ return d-> m_systemstr;
+}
+
+/**
+ * Return System as OSystem value
+ */
+OSystem ODevice::system ( ) const
+{
+ return d-> m_system;
+}
+
+/**
+ * @return the version string of the base system
+ */
+QString ODevice::systemVersionString ( ) const
+{
+ return d-> m_sysverstr;
+}
+
+/**
+ * @return the current Transformation
+ */
+Transformation ODevice::rotation ( ) const
+{
+ VirtRotation rot;
+ ODevice* that =(ODevice* )this;
+ that->virtual_hook( VIRTUAL_ROTATION, &rot );
+ return rot.trans;
+}
+
+/**
+ * @return the current rotation direction
+ */
+ODirection ODevice::direction ( ) const
+{
+ VirtDirection dir;
+ ODevice* that =(ODevice* )this;
+ that->virtual_hook( VIRTUAL_DIRECTION, &dir );
+ return dir.direct;
+}
+
+/**
+ * This plays an alarmSound
+ */
+void ODevice::alarmSound ( )
+{
+#ifndef QT_NO_SOUND
+ static Sound snd ( "alarm" );
+
+ if ( snd. isFinished ( ))
+ snd. play ( );
+#endif
+}
+
+/**
+ * This plays a key sound
+ */
+void ODevice::keySound ( )
+{
+#ifndef QT_NO_SOUND
+ static Sound snd ( "keysound" );
+
+ if ( snd. isFinished ( ))
+ snd. play ( );
+#endif
+}
+
+/**
+ * This plays a touch sound
+ */
+void ODevice::touchSound ( )
+{
+#ifndef QT_NO_SOUND
+ static Sound snd ( "touchsound" );
+
+ if ( snd. isFinished ( ))
+ snd. play ( );
+#endif
+}
+
+/**
+ * This method will return a list of leds
+ * available on this device
+ * @return a list of LEDs.
+ */
+QValueList <OLed> ODevice::ledList ( ) const
+{
+ return QValueList <OLed> ( );
+}
+
+/**
+ * This does return the state of the LEDs
+ */
+QValueList <OLedState> ODevice::ledStateList ( OLed /*which*/ ) const
+{
+ return QValueList <OLedState> ( );
+}
+
+/**
+ * @return the state for a given OLed
+ */
+OLedState ODevice::ledState ( OLed /*which*/ ) const
+{
+ return Led_Off;
+}
+
+/**
+ * Set the state for a LED
+ * @param which Which OLed to use
+ * @param st The state to set
+ * @return success or failure
+ */
+bool ODevice::setLedState ( OLed which, OLedState st )
+{
+ Q_UNUSED( which )
+ Q_UNUSED( st )
+ return false;
+}
+
+/**
+ * @return if the device has a light sensor
+ */
+bool ODevice::hasLightSensor ( ) const
+{
+ return false;
+}
+
+/**
+ * @return a value from the light sensor
+ */
+int ODevice::readLightSensor ( )
+{
+ return -1;
+}
+
+/**
+ * @return the light sensor resolution
+ */
+int ODevice::lightSensorResolution ( ) const
+{
+ return 0;
+}
+
+/**
+ * @return if the device has a hinge sensor
+ */
+bool ODevice::hasHingeSensor ( ) const
+{
+ VirtHasHinge hing;
+ ODevice* that =(ODevice* )this;
+ that->virtual_hook( VIRTUAL_HAS_HINGE, &hing );
+ return hing.hasHinge;
+}
+
+/**
+ * @return a value from the hinge sensor
+ */
+OHingeStatus ODevice::readHingeSensor ( )
+{
+ VirtHingeStatus hing;
+ virtual_hook( VIRTUAL_HINGE, &hing );
+ return hing.hingeStat;
+}
+
+/**
+ * @return a list with CPU frequencies supported by the hardware
+ */
+const QStrList &ODevice::allowedCpuFrequencies ( ) const
+{
+ return *d->m_cpu_frequencies;
+}
+
+
+/**
+ * Set desired CPU frequency
+ *
+ * @param index index into d->m_cpu_frequencies of the frequency to be set
+ */
+bool ODevice::setCurrentCpuFrequency(uint index)
+{
+ if (index >= d->m_cpu_frequencies->count())
+ return false;
+
+ char *freq = d->m_cpu_frequencies->at(index);
+ qWarning("set freq to %s", freq);
+
+ int fd;
+
+ if ((fd = ::open("/proc/sys/cpu/0/speed", O_WRONLY)) >= 0) {
+ char writeCommand[50];
+ const int count = sprintf(writeCommand, "%s\n", freq);
+ int res = (::write(fd, writeCommand, count) != -1);
+ ::close(fd);
+ return res;
+ }
+
+ return false;
+}
+
+
+/**
+ * @return a list of hardware buttons
+ */
+const QValueList <ODeviceButton> &ODevice::buttons ( )
+{
+ initButtons ( );
+
+ return *d-> m_buttons;
+}
+
+/**
+ * @return The amount of time that would count as a hold
+ */
+uint ODevice::buttonHoldTime ( ) const
+{
+ return d-> m_holdtime;
+}
+
+/**
+ * This method return a ODeviceButton for a key code
+ * or 0 if no special hardware button is available for the device
+ *
+ * @return The devicebutton or 0l
+ * @see ODeviceButton
+ */
+const ODeviceButton *ODevice::buttonForKeycode ( ushort code )
+{
+ initButtons ( );
+
+ for ( QValueListConstIterator<ODeviceButton> it = d-> m_buttons-> begin ( ); it != d-> m_buttons-> end ( ); ++it ) {
+ if ( (*it). keycode ( ) == code )
+ return &(*it);
+ }
+ return 0;
+}
+
+void ODevice::reloadButtonMapping ( )
+{
+ initButtons ( );
+
+ Config cfg ( "ButtonSettings" );
+
+ for ( uint i = 0; i < d-> m_buttons-> count ( ); i++ ) {
+ ODeviceButton &b = ( *d-> m_buttons ) [i];
+ QString group = "Button" + QString::number ( i );
+
+ QCString pch, hch;
+ QCString pm, hm;
+ QByteArray pdata, hdata;
+
+ if ( cfg. hasGroup ( group )) {
+ cfg. setGroup ( group );
+ pch = cfg. readEntry ( "PressedActionChannel" ). latin1 ( );
+ pm = cfg. readEntry ( "PressedActionMessage" ). latin1 ( );
+ // pdata = decodeBase64 ( buttonFile. readEntry ( "PressedActionArgs" ));
+
+ hch = cfg. readEntry ( "HeldActionChannel" ). latin1 ( );
+ hm = cfg. readEntry ( "HeldActionMessage" ). latin1 ( );
+ // hdata = decodeBase64 ( buttonFile. readEntry ( "HeldActionArgs" ));
+ }
+
+ b. setPressedAction ( OQCopMessage ( pch, pm, pdata ));
+
+ b. setHeldAction ( OQCopMessage ( hch, hm, hdata ));
+ }
+}
+
+void ODevice::remapPressedAction ( int button, const OQCopMessage &action )
+{
+ initButtons ( );
+
+ QString mb_chan;
+
+ if ( button >= (int) d-> m_buttons-> count ( ))
+ return;
+
+ ODeviceButton &b = ( *d-> m_buttons ) [button];
+ b. setPressedAction ( action );
+
+ mb_chan=b. pressedAction ( ). channel ( );
+
+ Config buttonFile ( "ButtonSettings" );
+ buttonFile. setGroup ( "Button" + QString::number ( button ));
+ buttonFile. writeEntry ( "PressedActionChannel", (const char*) mb_chan);
+ buttonFile. writeEntry ( "PressedActionMessage", (const char*) b. pressedAction ( ). message ( ));
+
+// buttonFile. writeEntry ( "PressedActionArgs", encodeBase64 ( b. pressedAction ( ). data ( )));
+
+ QCopEnvelope ( "QPE/System", "deviceButtonMappingChanged()" );
+}
+
+void ODevice::remapHeldAction ( int button, const OQCopMessage &action )
+{
+ initButtons ( );
+
+ if ( button >= (int) d-> m_buttons-> count ( ))
+ return;
+
+ ODeviceButton &b = ( *d-> m_buttons ) [button];
+ b. setHeldAction ( action );
+
+ Config buttonFile ( "ButtonSettings" );
+ buttonFile. setGroup ( "Button" + QString::number ( button ));
+ buttonFile. writeEntry ( "HeldActionChannel", (const char *) b. heldAction ( ). channel ( ));
+ buttonFile. writeEntry ( "HeldActionMessage", (const char *) b. heldAction ( ). message ( ));
+
+// buttonFile. writeEntry ( "HeldActionArgs", decodeBase64 ( b. heldAction ( ). data ( )));
+
+ QCopEnvelope ( "QPE/System", "deviceButtonMappingChanged()" );
+}
+void ODevice::virtual_hook(int id, void* data){
+ switch( id ) {
+ case VIRTUAL_ROTATION:{
+ VirtRotation* rot = reinterpret_cast<VirtRotation*>( data );
+ rot->trans = d->m_rotation;
+ break;
+ }
+ case VIRTUAL_DIRECTION:{
+ VirtDirection *dir = reinterpret_cast<VirtDirection*>( data );
+ dir->direct = d->m_direction;
+ break;
+ }
+ case VIRTUAL_HAS_HINGE:{
+ VirtHasHinge *hin = reinterpret_cast<VirtHasHinge*>( data );
+ hin->hasHinge = false;
+ break;
+ }
+ case VIRTUAL_HINGE:{
+ VirtHingeStatus *hin = reinterpret_cast<VirtHingeStatus*>( data );
+ hin->hingeStat = CASE_UNKNOWN;
+ break;
+ }
+ }
+}
+
+/**************************************************
+ *
+ * Yopy 3500/3700
+ *
+ **************************************************/
+
+bool Yopy::isYopy ( )
+{
+ QFile f( "/proc/cpuinfo" );
+ if ( f. open ( IO_ReadOnly ) ) {
+ QTextStream ts ( &f );
+ QString line;
+ while( line = ts. readLine ( ) ) {
+ if ( line. left ( 8 ) == "Hardware" ) {
+ int loc = line. find ( ":" );
+ if ( loc != -1 ) {
+ QString model =
+ line. mid ( loc + 2 ). simplifyWhiteSpace( );
+ return ( model == "Yopy" );
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void Yopy::init ( )
+{
+ d-> m_vendorstr = "G.Mate";
+ d-> m_vendor = Vendor_GMate;
+ d-> m_modelstr = "Yopy3700";
+ d-> m_model = Model_Yopy_3700;
+ d-> m_rotation = Rot0;
+
+ d-> m_systemstr = "Linupy";
+ d-> m_system = System_Linupy;
+
+ QFile f ( "/etc/issue" );
+ if ( f. open ( IO_ReadOnly )) {
+ QTextStream ts ( &f );
+ ts.readLine();
+ d-> m_sysverstr = ts. readLine ( );
+ f. close ( );
+ }
+}
+
+void Yopy::initButtons ( )
+{
+ if ( d-> m_buttons )
+ return;
+
+ d-> m_buttons = new QValueList <ODeviceButton>;
+
+ for (uint i = 0; i < ( sizeof( yopy_buttons ) / sizeof(yopy_button)); i++) {
+
+ yopy_button *ib = yopy_buttons + i;
+
+ ODeviceButton b;
+
+ b. setKeycode ( ib-> code );
+ b. setUserText ( QObject::tr ( "Button", ib-> utext ));
+ b. setPixmap ( Resource::loadPixmap ( ib-> pix ));
+ b. setFactoryPresetPressedAction
+ (OQCopMessage(makeChannel(ib->fpressedservice), ib->fpressedaction));
+ b. setFactoryPresetHeldAction
+ (OQCopMessage(makeChannel(ib->fheldservice), ib->fheldaction));
+
+ d-> m_buttons-> append ( b );
+ }
+ reloadButtonMapping ( );
+
+ QCopChannel *sysch = new QCopChannel("QPE/System", this);
+ connect(sysch, SIGNAL(received(const QCString&,const QByteArray&)),
+ this, SLOT(systemMessage(const QCString&,const QByteArray&)));
+}
+
+bool Yopy::suspend()
+{
+ /* Opie for Yopy does not implement its own power management at the
+ moment. The public version runs parallel to X, and relies on the
+ existing power management features. */
+ return false;
+}
+
+bool Yopy::setDisplayBrightness(int /*bright*/)
+{
+ /* The code here works, but is disabled as the current version runs
+ parallel to X, and relies on the existing backlight demon. */
+#if 0
+ if ( QFile::exists("/proc/sys/pm/light") ) {
+ int fd = ::open("/proc/sys/pm/light", O_WRONLY);
+ if (fd >= 0 ) {
+ if (bright)
+ ::write(fd, "1\n", 2);
+ else
+ ::write(fd, "0\n", 2);
+ ::close(fd);
+ return true;
+ }
+ }
+#endif
+ return false;
+}
+
+int Yopy::displayBrightnessResolution() const
+{
+ return 2;
+}
+
+/**************************************************
+ *
+ * iPAQ
+ *
+ **************************************************/
+
+void iPAQ::init ( )
+{
+ d-> m_vendorstr = "HP";
+ d-> m_vendor = Vendor_HP;
+
+ QFile f ( "/proc/hal/model" );
+
+ if ( f. open ( IO_ReadOnly )) {
+ QTextStream ts ( &f );
+
+ d-> m_modelstr = "H" + ts. readLine ( );
+
+ if ( d-> m_modelstr == "H3100" )
+ d-> m_model = Model_iPAQ_H31xx;
+ else if ( d-> m_modelstr == "H3600" )
+ d-> m_model = Model_iPAQ_H36xx;
+ else if ( d-> m_modelstr == "H3700" )
+ d-> m_model = Model_iPAQ_H37xx;
+ else if ( d-> m_modelstr == "H3800" )
+ d-> m_model = Model_iPAQ_H38xx;
+ else if ( d-> m_modelstr == "H3900" )
+ d-> m_model = Model_iPAQ_H39xx;
+ else if ( d-> m_modelstr == "H5400" )
+ d-> m_model = Model_iPAQ_H5xxx;
+ else
+ d-> m_model = Model_Unknown;
+
+ f. close ( );
+ }
+
+ switch ( d-> m_model ) {
+ case Model_iPAQ_H31xx:
+ case Model_iPAQ_H38xx:
+ d-> m_rotation = Rot90;
+ break;
+ case Model_iPAQ_H36xx:
+ case Model_iPAQ_H37xx:
+ case Model_iPAQ_H39xx:
+
+ default:
+ d-> m_rotation = Rot270;
+ break;
+ case Model_iPAQ_H5xxx:
+ d-> m_rotation = Rot0;
+ }
+
+ f. setName ( "/etc/familiar-version" );
+ if ( f. open ( IO_ReadOnly )) {
+ d-> m_systemstr = "Familiar";
+ d-> m_system = System_Familiar;
+
+ QTextStream ts ( &f );
+ d-> m_sysverstr = ts. readLine ( ). mid ( 10 );
+
+ f. close ( );
+ } else {
+ f. setName ( "/etc/oz_version" );
+
+ if ( f. open ( IO_ReadOnly )) {
+ d-> m_systemstr = "OpenEmbedded/iPaq";
+ d-> m_system = System_Familiar;
+
+ QTextStream ts ( &f );
+ ts.setDevice ( &f );
+ d-> m_sysverstr = ts. readLine ( );
+ f. close ( );
+ }
+ }
+
+
+
+
+
+ m_leds [0] = m_leds [1] = Led_Off;
+
+ m_power_timer = 0;
+
+}
+
+void iPAQ::initButtons ( )
+{
+ if ( d-> m_buttons )
+ return;
+
+ if ( isQWS( ) )
+ QWSServer::setKeyboardFilter ( this );
+
+ d-> m_buttons = new QValueList <ODeviceButton>;
+
+ for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) {
+ i_button *ib = ipaq_buttons + i;
+ ODeviceButton b;
+
+ if (( ib-> model & d-> m_model ) == d-> m_model ) {
+ b. setKeycode ( ib-> code );
+ b. setUserText ( QObject::tr ( "Button", ib-> utext ));
+ b. setPixmap ( Resource::loadPixmap ( ib-> pix ));
+ b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib-> fpressedservice ), ib-> fpressedaction ));
+ b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib-> fheldservice ), ib-> fheldaction ));
+
+ d-> m_buttons-> append ( b );
+ }
+ }
+ reloadButtonMapping ( );
+
+ QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
+ connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( systemMessage(const QCString&,const QByteArray&)));
+}
+
+
+//#include <linux/h3600_ts.h> // including kernel headers is evil ...
+
+typedef struct {
+ unsigned char OffOnBlink; /* 0=off 1=on 2=Blink */
+ unsigned char TotalTime; /* Units of 5 seconds */
+ unsigned char OnTime; /* units of 100m/s */
+ unsigned char OffTime; /* units of 100m/s */
+} LED_IN;
+
+typedef struct {
+ unsigned char mode;
+ unsigned char pwr;
+ unsigned char brightness;
+} FLITE_IN;
+
+#define LED_ON OD_IOW( 'f', 5, LED_IN )
+#define FLITE_ON OD_IOW( 'f', 7, FLITE_IN )
+
+
+QValueList <OLed> iPAQ::ledList ( ) const
+{
+ QValueList <OLed> vl;
+ vl << Led_Power;
+
+ if ( d-> m_model == Model_iPAQ_H38xx )
+ vl << Led_BlueTooth;
+ return vl;
+}
+
+QValueList <OLedState> iPAQ::ledStateList ( OLed l ) const
+{
+ QValueList <OLedState> vl;
+
+ if ( l == Led_Power )
+ vl << Led_Off << Led_On << Led_BlinkSlow << Led_BlinkFast;
+ else if ( l == Led_BlueTooth && d-> m_model == Model_iPAQ_H38xx )
+ vl << Led_Off; // << Led_On << ???
+
+ return vl;
+}
+
+OLedState iPAQ::ledState ( OLed l ) const
+{
+ switch ( l ) {
+ case Led_Power:
+ return m_leds [0];
+ case Led_BlueTooth:
+ return m_leds [1];
+ default:
+ return Led_Off;
+ }
+}
+
+bool iPAQ::setLedState ( OLed l, OLedState st )
+{
+ static int fd = ::open ( "/dev/touchscreen/0", O_RDWR | O_NONBLOCK );
+
+ if ( l == Led_Power ) {
+ if ( fd >= 0 ) {
+ LED_IN leds;
+ ::memset ( &leds, 0, sizeof( leds ));
+ leds. TotalTime = 0;
+ leds. OnTime = 0;
+ leds. OffTime = 1;
+ leds. OffOnBlink = 2;
+
+ switch ( st ) {
+ case Led_Off : leds. OffOnBlink = 0; break;
+ case Led_On : leds. OffOnBlink = 1; break;
+ case Led_BlinkSlow: leds. OnTime = 10; leds. OffTime = 10; break;
+ case Led_BlinkFast: leds. OnTime = 5; leds. OffTime = 5; break;
+ }
+
+ if ( ::ioctl ( fd, LED_ON, &leds ) >= 0 ) {
+ m_leds [0] = st;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+bool iPAQ::filter ( int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat )
+{
+ int newkeycode = keycode;
+
+ switch ( keycode ) {
+ // H38xx/H39xx have no "Q" key anymore - this is now the Mail key
+ case HardKey_Menu: {
+ if (( d-> m_model == Model_iPAQ_H38xx ) ||
+ ( d-> m_model == Model_iPAQ_H39xx ) ||
+ ( d-> m_model == Model_iPAQ_H5xxx)) {
+ newkeycode = HardKey_Mail;
+ }
+ break;
+ }
+
+ // Rotate cursor keys 180° or 270°
+ case Key_Left :
+ case Key_Right:
+ case Key_Up :
+ case Key_Down : {
+
+ if (( d-> m_model == Model_iPAQ_H31xx ) ||
+ ( d-> m_model == Model_iPAQ_H38xx )) {
+ newkeycode = Key_Left + ( keycode - Key_Left + 2 ) % 4;
+ }
+ // Rotate the cursor keys by 270°
+ // keycode - Key_Left = position of the button starting from left clockwise
+ // add the rotation to it and modolo. No we've the original offset
+ // add the offset to the Key_Left key
+ if ( d-> m_model == Model_iPAQ_H5xxx )
+ newkeycode = Key_Left + ( keycode - Key_Left + 3 ) % 4;
+ break;
+ }
+
+ // map Power Button short/long press to F34/F35
+ case Key_SysReq: {
+ if ( isPress ) {
+ if ( m_power_timer )
+ killTimer ( m_power_timer );
+ m_power_timer = startTimer ( 500 );
+ }
+ else if ( m_power_timer ) {
+ killTimer ( m_power_timer );
+ m_power_timer = 0;
+ QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, true, false );
+ QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, false, false );
+ }
+ newkeycode = Key_unknown;
+ break;
+ }
+ }
+
+ if ( newkeycode != keycode ) {
+ if ( newkeycode != Key_unknown )
+ QWSServer::sendKeyEvent ( -1, newkeycode, modifiers, isPress, autoRepeat );
+ return true;
+ }
+ else
+ return false;
+}
+
+void iPAQ::timerEvent ( QTimerEvent * )
+{
+ killTimer ( m_power_timer );
+ m_power_timer = 0;
+ QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, true, false );
+ QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, false, false );
+}
+
+
+void iPAQ::alarmSound ( )
+{
+#ifndef QT_NO_SOUND
+ static Sound snd ( "alarm" );
+ int fd;
+ int vol;
+ bool vol_reset = false;
+
+ if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) {
+ if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) {
+ Config cfg ( "qpe" );
+ cfg. setGroup ( "Volume" );
+
+ int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 );
+ if ( volalarm < 0 )
+ volalarm = 0;
+ else if ( volalarm > 100 )
+ volalarm = 100;
+ volalarm |= ( volalarm << 8 );
+
+ if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 )
+ vol_reset = true;
+ }
+ }
+
+ snd. play ( );
+ while ( !snd. isFinished ( ))
+ qApp-> processEvents ( );
+
+ if ( fd >= 0 ) {
+ if ( vol_reset )
+ ::ioctl ( fd, MIXER_WRITE( 0 ), &vol );
+ ::close ( fd );
+ }
+#endif
+}
+
+
+bool iPAQ::setSoftSuspend ( bool soft )
+{
+ bool res = false;
+ int fd;
+
+ if (( fd = ::open ( "/proc/sys/ts/suspend_button_mode", O_WRONLY )) >= 0 ) {
+ if ( ::write ( fd, soft ? "1" : "0", 1 ) == 1 )
+ res = true;
+ else
+ ::perror ( "write to /proc/sys/ts/suspend_button_mode" );
+
+ ::close ( fd );
+ }
+ else
+ ::perror ( "/proc/sys/ts/suspend_button_mode" );
+
+ return res;
+}
+
+
+bool iPAQ::setDisplayBrightness ( int bright )
+{
+ bool res = false;
+ int fd;
+
+ if ( bright > 255 )
+ bright = 255;
+ if ( bright < 0 )
+ bright = 0;
+
+ if (( fd = ::open ( "/dev/touchscreen/0", O_WRONLY )) >= 0 ) {
+ FLITE_IN bl;
+ bl. mode = 1;
+ bl. pwr = bright ? 1 : 0;
+ bl. brightness = ( bright * ( displayBrightnessResolution ( ) - 1 ) + 127 ) / 255;
+ res = ( ::ioctl ( fd, FLITE_ON, &bl ) == 0 );
+ ::close ( fd );
+ }
+ return res;
+}
+
+int iPAQ::displayBrightnessResolution ( ) const
+{
+ switch ( model ( )) {
+ case Model_iPAQ_H31xx:
+ case Model_iPAQ_H36xx:
+ case Model_iPAQ_H37xx:
+ return 128; // really 256, but >128 could damage the LCD
+
+ case Model_iPAQ_H38xx:
+ case Model_iPAQ_H39xx:
+ return 64;
+ case Model_iPAQ_H5xxx:
+ return 255;
+
+ default:
+ return 2;
+ }
+}
+
+
+bool iPAQ::hasLightSensor ( ) const
+{
+ return true;
+}
+
+int iPAQ::readLightSensor ( )
+{
+ int fd;
+ int val = -1;
+
+ if (( fd = ::open ( "/proc/hal/light_sensor", O_RDONLY )) >= 0 ) {
+ char buffer [8];
+
+ if ( ::read ( fd, buffer, 5 ) == 5 ) {
+ char *endptr;
+
+ buffer [4] = 0;
+ val = ::strtol ( buffer + 2, &endptr, 16 );
+
+ if ( *endptr != 0 )
+ val = -1;
+ }
+ ::close ( fd );
+ }
+
+ return val;
+}
+
+int iPAQ::lightSensorResolution ( ) const
+{
+ return 256;
+}
+
+/**************************************************
+ *
+ * Zaurus
+ *
+ **************************************************/
+
+// Check whether this device is the sharp zaurus..
+// FIXME This gets unnecessary complicated. We should think about splitting the Zaurus
+// class up into individual classes. We need three classes
+//
+// Zaurus-Collie (SA-model w/ 320x240 lcd, for SL5500 and SL5000)
+// Zaurus-Poodle (PXA-model w/ 320x240 lcd, for SL5600)
+// Zaurus-Corgi (PXA-model w/ 640x480 lcd, for C700, C750, C760, and C860)
+//
+// Only question right now is: Do we really need to do it? Because as soon
+// as the OpenZaurus kernel is ready, there will be a unified interface for all
+// Zaurus models (concerning apm, backlight, buttons, etc.)
+//
+// Comments? - mickeyl.
+
+bool Zaurus::isZaurus()
+{
+
+ // If the special devices by embedix exist, it is quite simple: it is a Zaurus !
+ if ( QFile::exists ( "/dev/sharp_buz" ) || QFile::exists ( "/dev/sharp_led" ) ){
+ return true;
+ }
+
+ // On non-embedix kernels, we have to look closer.
+ bool is_zaurus = false;
+ QFile f ( "/proc/cpuinfo" );
+ if ( f. open ( IO_ReadOnly ) ) {
+ QString model;
+ QFile f ( "/proc/cpuinfo" );
+
+ QTextStream ts ( &f );
+ QString line;
+ while( line = ts. readLine ( ) ) {
+ if ( line. left ( 8 ) == "Hardware" )
+ break;
+ }
+ int loc = line. find ( ":" );
+ if ( loc != -1 )
+ model = line. mid ( loc + 2 ). simplifyWhiteSpace( );
+
+ if ( model == "Sharp-Collie"
+ || model == "Collie"
+ || model == "SHARP Corgi"
+ || model == "SHARP Shepherd"
+ || model == "SHARP Poodle"
+ || model == "SHARP Husky"
+ )
+ is_zaurus = true;
+
+ }
+ return is_zaurus;
+}
+
+
+void Zaurus::init ( )
+{
+ d-> m_vendorstr = "Sharp";
+ d-> m_vendor = Vendor_Sharp;
+ m_embedix = true; // Not openzaurus means: It has an embedix kernel !
+
+ // QFile f ( "/proc/filesystems" );
+ QString model;
+
+ // It isn't a good idea to check the system configuration to
+ // detect the distribution !
+ // Otherwise it may happen that any other distribution is detected as openzaurus, just
+ // because it uses a jffs2 filesystem..
+ // (eilers)
+ // if ( f. open ( IO_ReadOnly ) && ( QTextStream ( &f ). read ( ). find ( "\tjffs2\n" ) >= 0 )) {
+ QFile f ("/etc/oz_version");
+ if ( f.exists() ){
+ d-> m_vendorstr = "OpenZaurus Team";
+ d-> m_systemstr = "OpenZaurus";
+ d-> m_system = System_OpenZaurus;
+
+ if ( f. open ( IO_ReadOnly )) {
+ QTextStream ts ( &f );
+ d-> m_sysverstr = ts. readLine ( );//. mid ( 10 );
+ f. close ( );
+ }
+
+ // Openzaurus sometimes uses the embedix kernel!
+ // => Check whether this is an embedix kernel
+ FILE *uname = popen("uname -r", "r");
+ QString line;
+ if ( f.open(IO_ReadOnly, uname) ) {
+ QTextStream ts ( &f );
+ line = ts. readLine ( );
+ int loc = line. find ( "embedix" );
+ if ( loc != -1 )
+ m_embedix = true;
+ else
+ m_embedix = false;
+ f. close ( );
+ }
+ pclose(uname);
+ }
+ else {
+ d-> m_systemstr = "Zaurus";
+ d-> m_system = System_Zaurus;
+ }
+
+ f. setName ( "/proc/cpuinfo" );
+ if ( f. open ( IO_ReadOnly ) ) {
+ QTextStream ts ( &f );
+ QString line;
+ while( line = ts. readLine ( ) ) {
+ if ( line. left ( 8 ) == "Hardware" )
+ break;
+ }
+ int loc = line. find ( ":" );
+ if ( loc != -1 )
+ model = line. mid ( loc + 2 ). simplifyWhiteSpace( );
+ }
+
+ if ( model == "SHARP Corgi" ) {
+ d-> m_model = Model_Zaurus_SLC7x0;
+ d-> m_modelstr = "Zaurus SL-C700";
+ } else if ( model == "SHARP Shepherd" ) {
+ d-> m_model = Model_Zaurus_SLC7x0;
+ d-> m_modelstr = "Zaurus SL-C750";
+ } else if ( model == "SHARP Husky" ) {
+ d-> m_model = Model_Zaurus_SLC7x0;
+ d-> m_modelstr = "Zaurus SL-C760";
+ } else if ( model == "SHARP Poodle" ) {
+ d-> m_model = Model_Zaurus_SLB600;
+ d-> m_modelstr = "Zaurus SL-B500 or SL-5600";
+ } else if ( model == "Sharp-Collie" || model == "Collie" ) {
+ d-> m_model = Model_Zaurus_SL5500;
+ d-> m_modelstr = "Zaurus SL-5500 or SL-5000d";
+ } else {
+ d-> m_model = Model_Zaurus_SL5500;
+ d-> m_modelstr = "Zaurus (Model unknown)";
+ }
+
+ switch ( d-> m_model ) {
+ case Model_Zaurus_SLA300:
+ d-> m_rotation = Rot0;
+ break;
+ case Model_Zaurus_SLC7x0:
+ d-> m_rotation = rotation();
+ d-> m_direction = direction();
+ break;
+ case Model_Zaurus_SLB600:
+ case Model_Zaurus_SL5500:
+ case Model_Zaurus_SL5000:
+ default:
+ d-> m_rotation = Rot270;
+ break;
+ }
+ m_leds [0] = Led_Off;
+}
+
+void Zaurus::initButtons ( )
+{
+ if ( d-> m_buttons )
+ return;
+
+ d-> m_buttons = new QValueList <ODeviceButton>;
+
+ struct z_button * pz_buttons;
+ int buttoncount;
+ switch ( d-> m_model ) {
+ case Model_Zaurus_SLC7x0:
+ pz_buttons = z_buttons_c700;
+ buttoncount = ARRAY_SIZE(z_buttons_c700);
+ break;
+ default:
+ pz_buttons = z_buttons;
+ buttoncount = ARRAY_SIZE(z_buttons);
+ break;
+ }
+
+ for ( int i = 0; i < buttoncount; i++ ) {
+ struct z_button *zb = pz_buttons + i;
+ ODeviceButton b;
+
+ b. setKeycode ( zb-> code );
+ b. setUserText ( QObject::tr ( "Button", zb-> utext ));
+ b. setPixmap ( Resource::loadPixmap ( zb-> pix ));
+ b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( zb-> fpressedservice ),
+ zb-> fpressedaction ));
+ b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( zb-> fheldservice ),
+ zb-> fheldaction ));
+
+ d-> m_buttons-> append ( b );
+ }
+
+ reloadButtonMapping ( );
+
+ QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
+ connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)),
+ this, SLOT( systemMessage(const QCString&,const QByteArray&)));
+}
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+//#include <asm/sharp_char.h> // including kernel headers is evil ...
+
+#define SHARP_DEV_IOCTL_COMMAND_START 0x5680
+
+#define SHARP_BUZZER_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START)
+#define SHARP_BUZZER_MAKESOUND (SHARP_BUZZER_IOCTL_START)
+
+#define SHARP_BUZ_TOUCHSOUND 1 /* touch panel sound */
+#define SHARP_BUZ_KEYSOUND 2 /* key sound */
+#define SHARP_BUZ_SCHEDULE_ALARM 11 /* schedule alarm */
+
+/* --- for SHARP_BUZZER device --- */
+
+//#define SHARP_BUZZER_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START)
+//#define SHARP_BUZZER_MAKESOUND (SHARP_BUZZER_IOCTL_START)
+
+#define SHARP_BUZZER_SETVOLUME (SHARP_BUZZER_IOCTL_START+1)
+#define SHARP_BUZZER_GETVOLUME (SHARP_BUZZER_IOCTL_START+2)
+#define SHARP_BUZZER_ISSUPPORTED (SHARP_BUZZER_IOCTL_START+3)
+#define SHARP_BUZZER_SETMUTE (SHARP_BUZZER_IOCTL_START+4)
+#define SHARP_BUZZER_STOPSOUND (SHARP_BUZZER_IOCTL_START+5)
+
+//#define SHARP_BUZ_TOUCHSOUND 1 /* touch panel sound */
+//#define SHARP_BUZ_KEYSOUND 2 /* key sound */
+
+//#define SHARP_PDA_ILLCLICKSOUND 3 /* illegal click */
+//#define SHARP_PDA_WARNSOUND 4 /* warning occurred */
+//#define SHARP_PDA_ERRORSOUND 5 /* error occurred */
+//#define SHARP_PDA_CRITICALSOUND 6 /* critical error occurred */
+//#define SHARP_PDA_SYSSTARTSOUND 7 /* system start */
+//#define SHARP_PDA_SYSTEMENDSOUND 8 /* system shutdown */
+//#define SHARP_PDA_APPSTART 9 /* application start */
+//#define SHARP_PDA_APPQUIT 10 /* application ends */
+
+//#define SHARP_BUZ_SCHEDULE_ALARM 11 /* schedule alarm */
+//#define SHARP_BUZ_DAILY_ALARM 12 /* daily alarm */
+//#define SHARP_BUZ_GOT_PHONE_CALL 13 /* phone call sound */
+//#define SHARP_BUZ_GOT_MAIL 14 /* mail sound */
+//
+
+#define SHARP_LED_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START)
+#define SHARP_LED_SETSTATUS (SHARP_LED_IOCTL_START+1)
+
+#define SHARP_IOCTL_GET_ROTATION 0x413c
+
+typedef struct sharp_led_status {
+ int which; /* select which LED status is wanted. */
+ int status; /* set new led status if you call SHARP_LED_SETSTATUS */
+} sharp_led_status;
+
+#define SHARP_LED_MAIL_EXISTS 9 /* mail status (exists or not) */
+
+#define LED_MAIL_NO_UNREAD_MAIL 0 /* for SHARP_LED_MAIL_EXISTS */
+#define LED_MAIL_NEWMAIL_EXISTS 1 /* for SHARP_LED_MAIL_EXISTS */
+#define LED_MAIL_UNREAD_MAIL_EX 2 /* for SHARP_LED_MAIL_EXISTS */
+
+// #include <asm/sharp_apm.h> // including kernel headers is evil ...
+
+#define APM_IOCGEVTSRC OD_IOR( 'A', 203, int )
+#define APM_IOCSEVTSRC OD_IORW( 'A', 204, int )
+#define APM_EVT_POWER_BUTTON (1 << 0)
+
+#define FL_IOCTL_STEP_CONTRAST 100
+
+
+void Zaurus::buzzer ( int sound )
+{
+#ifndef QT_NO_SOUND
+ QString soundname;
+
+ // Not all devices have real sound
+ if ( d->m_model == Model_Zaurus_SLC7x0
+ || d->m_model == Model_Zaurus_SLB600 ){
+
+ switch ( sound ){
+ case SHARP_BUZ_SCHEDULE_ALARM:
+ soundname = "alarm";
+ break;
+ case SHARP_BUZ_TOUCHSOUND:
+ soundname = "touchsound";
+ break;
+ case SHARP_BUZ_KEYSOUND:
+ soundname = "keysound";
+ break;
+ default:
+ soundname = "alarm";
+
+ }
+ }
+
+ // If a soundname is defined, we expect that this device has
+ // sound capabilities.. Otherwise we expect to have the buzzer
+ // device..
+ if ( !soundname.isEmpty() ){
+ int fd;
+ int vol;
+ bool vol_reset = false;
+
+ Sound snd ( soundname );
+
+ if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) {
+ if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) {
+ Config cfg ( "qpe" );
+ cfg. setGroup ( "Volume" );
+
+ int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 );
+ if ( volalarm < 0 )
+ volalarm = 0;
+ else if ( volalarm > 100 )
+ volalarm = 100;
+ volalarm |= ( volalarm << 8 );
+
+ if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 )
+ vol_reset = true;
+ }
+ }
+
+ snd. play ( );
+ while ( !snd. isFinished ( ))
+ qApp-> processEvents ( );
+
+ if ( fd >= 0 ) {
+ if ( vol_reset )
+ ::ioctl ( fd, MIXER_WRITE( 0 ), &vol );
+ ::close ( fd );
+ }
+ } else {
+ int fd = ::open ( "/dev/sharp_buz", O_WRONLY|O_NONBLOCK );
+
+ if ( fd >= 0 ) {
+ ::ioctl ( fd, SHARP_BUZZER_MAKESOUND, sound );
+ ::close ( fd );
+ }
+
+ }
+#endif
+}
+
+
+void Zaurus::alarmSound ( )
+{
+ buzzer ( SHARP_BUZ_SCHEDULE_ALARM );
+}
+
+void Zaurus::touchSound ( )
+{
+ buzzer ( SHARP_BUZ_TOUCHSOUND );
+}
+
+void Zaurus::keySound ( )
+{
+ buzzer ( SHARP_BUZ_KEYSOUND );
+}
+
+
+QValueList <OLed> Zaurus::ledList ( ) const
+{
+ QValueList <OLed> vl;
+ vl << Led_Mail;
+ return vl;
+}
+
+QValueList <OLedState> Zaurus::ledStateList ( OLed l ) const
+{
+ QValueList <OLedState> vl;
+
+ if ( l == Led_Mail )
+ vl << Led_Off << Led_On << Led_BlinkSlow;
+ return vl;
+}
+
+OLedState Zaurus::ledState ( OLed which ) const
+{
+ if ( which == Led_Mail )
+ return m_leds [0];
+ else
+ return Led_Off;
+}
+
+bool Zaurus::setLedState ( OLed which, OLedState st )
+{
+ if (!m_embedix) // Currently not supported on non_embedix kernels
+ return false;
+
+ static int fd = ::open ( "/dev/sharp_led", O_RDWR|O_NONBLOCK );
+
+ if ( which == Led_Mail ) {
+ if ( fd >= 0 ) {
+ struct sharp_led_status leds;
+ ::memset ( &leds, 0, sizeof( leds ));
+ leds. which = SHARP_LED_MAIL_EXISTS;
+ bool ok = true;
+
+ switch ( st ) {
+ case Led_Off : leds. status = LED_MAIL_NO_UNREAD_MAIL; break;
+ case Led_On : leds. status = LED_MAIL_NEWMAIL_EXISTS; break;
+ case Led_BlinkSlow: leds. status = LED_MAIL_UNREAD_MAIL_EX; break;
+ default : ok = false;
+ }
+
+ if ( ok && ( ::ioctl ( fd, SHARP_LED_SETSTATUS, &leds ) >= 0 )) {
+ m_leds [0] = st;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool Zaurus::setSoftSuspend ( bool soft )
+{
+ if (!m_embedix) {
+ /* non-Embedix kernels dont have kernel autosuspend */
+ return ODevice::setSoftSuspend( soft );
+ }
+
+ bool res = false;
+ int fd;
+
+ if ((( fd = ::open ( "/dev/apm_bios", O_RDWR )) >= 0 ) ||
+ (( fd = ::open ( "/dev/misc/apm_bios",O_RDWR )) >= 0 )) {
+
+ int sources = ::ioctl ( fd, APM_IOCGEVTSRC, 0 ); // get current event sources
+
+ if ( sources >= 0 ) {
+ if ( soft )
+ sources &= ~APM_EVT_POWER_BUTTON;
+ else
+ sources |= APM_EVT_POWER_BUTTON;
+
+ if ( ::ioctl ( fd, APM_IOCSEVTSRC, sources ) >= 0 ) // set new event sources
+ res = true;
+ else
+ perror ( "APM_IOCGEVTSRC" );
+ }
+ else
+ perror ( "APM_IOCGEVTSRC" );
+
+ ::close ( fd );
+ }
+ else
+ perror ( "/dev/apm_bios or /dev/misc/apm_bios" );
+
+ return res;
+}
+
+
+bool Zaurus::setDisplayBrightness ( int bright )
+{
+ //qDebug( "Zaurus::setDisplayBrightness( %d )", bright );
+ bool res = false;
+ int fd;
+
+ if ( bright > 255 ) bright = 255;
+ if ( bright < 0 ) bright = 0;
+
+ if ( m_embedix )
+ {
+ if ( d->m_model == Model_Zaurus_SLC7x0 )
+ {
+ //qDebug( "using special treatment for devices with the corgi backlight interface" );
+ // special treatment for devices with the corgi backlight interface
+ if (( fd = ::open ( "/proc/driver/fl/corgi-bl", O_WRONLY )) >= 0 )
+ {
+ int value = ( bright == 1 ) ? 1 : bright * ( 17.0 / 255.0 );
+ char writeCommand[100];
+ const int count = sprintf( writeCommand, "0x%x\n", value );
+ res = ( ::write ( fd, writeCommand, count ) != -1 );
+ ::close ( fd );
+ }
+ return res;
+ }
+ else
+ {
+ // standard treatment for devices with the dumb embedix frontlight interface
+ if (( fd = ::open ( "/dev/fl", O_WRONLY )) >= 0 ) {
+ int bl = ( bright * 4 + 127 ) / 255; // only 4 steps on zaurus
+ if ( bright && !bl )
+ bl = 1;
+ res = ( ::ioctl ( fd, FL_IOCTL_STEP_CONTRAST, bl ) == 0 );
+ ::close ( fd );
+ }
+ }
+ }
+ else
+ {
+ // special treatment for the OpenZaurus unified interface
+ #define FB_BACKLIGHT_SET_BRIGHTNESS _IOW('F', 1, u_int) /* set brightness */
+ if (( fd = ::open ( "/dev/fb0", O_WRONLY )) >= 0 ) {
+ res = ( ::ioctl ( fd , FB_BACKLIGHT_SET_BRIGHTNESS, bright ) == 0 );
+ ::close ( fd );
+ }
+ }
+ return res;
+}
+
+bool Zaurus::suspend ( )
+{
+ qDebug("ODevice::suspend");
+ if ( !isQWS( ) ) // only qwsserver is allowed to suspend
+ return false;
+
+ if ( d-> m_model == Model_Unknown ) // better don't suspend in qvfb / on unkown devices
+ return false;
+
+ bool res = false;
+
+ struct timeval tvs, tvn;
+ ::gettimeofday ( &tvs, 0 );
+
+ ::sync ( ); // flush fs caches
+ res = ( ::system ( "apm --suspend" ) == 0 );
+
+ // This is needed because the iPAQ apm implementation is asynchronous and we
+ // can not be sure when exactly the device is really suspended
+ // This can be deleted as soon as a stable familiar with a synchronous apm implementation exists.
+
+ if ( res ) {
+ do { // Yes, wait 15 seconds. This APM bug sucks big time.
+ ::usleep ( 200 * 1000 );
+ ::gettimeofday ( &tvn, 0 );
+ } while ((( tvn. tv_sec - tvs. tv_sec ) * 1000 + ( tvn. tv_usec - tvs. tv_usec ) / 1000 ) < 15000 );
+ }
+
+ QCopEnvelope ( "QPE/Rotation", "rotateDefault()" );
+ return res;
+}
+
+
+Transformation Zaurus::rotation ( ) const
+{
+ Transformation rot;
+ int handle = 0;
+ int retval = 0;
+
+ switch ( d-> m_model ) {
+ case Model_Zaurus_SLC7x0:
+ handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK);
+ if (handle == -1) {
+ return Rot270;
+ } else {
+ retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION);
+ ::close (handle);
+
+ if (retval == 2 )
+ rot = Rot0;
+ else
+ rot = Rot270;
+ }
+ break;
+ case Model_Zaurus_SLA300:
+ case Model_Zaurus_SLB600:
+ case Model_Zaurus_SL5500:
+ case Model_Zaurus_SL5000:
+ default:
+ rot = d-> m_rotation;
+ break;
+ }
+
+ return rot;
+}
+ODirection Zaurus::direction ( ) const
+{
+ ODirection dir;
+ int handle = 0;
+ int retval = 0;
+ switch ( d-> m_model ) {
+ case Model_Zaurus_SLC7x0:
+ handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK);
+ if (handle == -1) {
+ dir = CW;
+ } else {
+ retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION);
+ ::close (handle);
+ if (retval == 2 )
+ dir = CCW;
+ else
+ dir = CW;
+ }
+ break;
+ case Model_Zaurus_SLA300:
+ case Model_Zaurus_SLB600:
+ case Model_Zaurus_SL5500:
+ case Model_Zaurus_SL5000:
+ default:
+ dir = d-> m_direction;
+ break;
+ }
+ return dir;
+
+}
+
+int Zaurus::displayBrightnessResolution ( ) const
+{
+ if (m_embedix)
+ return d->m_model == Model_Zaurus_SLC7x0 ? 18 : 5;
+ else
+ return 256;
+}
+
+bool Zaurus::hasHingeSensor() const
+{
+ return d->m_model == Model_Zaurus_SLC7x0;
+}
+
+OHingeStatus Zaurus::readHingeSensor()
+{
+ int handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK);
+ if (handle == -1)
+ {
+ qWarning("Zaurus::readHingeSensor() - failed (%s)", "unknown reason" ); //FIXME: use strerror
+ return CASE_UNKNOWN;
+ }
+ else
+ {
+ int retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION);
+ ::close (handle);
+ if ( retval == CASE_CLOSED || retval == CASE_PORTRAIT || retval == CASE_LANDSCAPE )
+ {
+ qDebug( "Zaurus::readHingeSensor() - result = %d", retval );
+ return static_cast<OHingeStatus>( retval );
+ }
+ else
+ {
+ qWarning("Zaurus::readHingeSensor() - couldn't compute hinge status!" );
+ return CASE_UNKNOWN;
+ }
+ }
+}
+
+
+void Zaurus::virtual_hook( int id, void *data ) {
+ switch( id ) {
+ case VIRTUAL_ROTATION:{
+ VirtRotation* rot = reinterpret_cast<VirtRotation*>( data );
+ rot->trans = rotation();
+ break;
+ }
+ case VIRTUAL_DIRECTION:{
+ VirtDirection *dir = reinterpret_cast<VirtDirection*>( data );
+ dir->direct = direction();
+ break;
+ }
+ case VIRTUAL_HAS_HINGE:{
+ VirtHasHinge *hin = reinterpret_cast<VirtHasHinge*>( data );
+ hin->hasHinge = hasHingeSensor();
+ break;
+ }
+ case VIRTUAL_HINGE:{
+ VirtHingeStatus *hin = reinterpret_cast<VirtHingeStatus*>( data );
+ hin->hingeStat = readHingeSensor();
+ break;
+ }
+ default:
+ ODevice::virtual_hook( id, data );
+ break;
+ }
+}
+
+/**************************************************
+ *
+ * SIMpad
+ *
+ **************************************************/
+
+void SIMpad::init ( )
+{
+ d-> m_vendorstr = "SIEMENS";
+ d-> m_vendor = Vendor_SIEMENS;
+
+ QFile f ( "/proc/hal/model" );
+
+ //TODO Implement model checking
+ //FIXME For now we assume an SL4
+
+ d-> m_modelstr = "SL4";
+ d-> m_model = Model_SIMpad_SL4;
+
+ switch ( d-> m_model ) {
+ default:
+ d-> m_rotation = Rot0;
+ d-> m_direction = CCW;
+ d-> m_holdtime = 1000; // 1000ms
+
+ break;
+ }
+
+ f. setName ( "/etc/familiar-version" );
+ if ( f. open ( IO_ReadOnly )) {
+ d-> m_systemstr = "Familiar";
+ d-> m_system = System_Familiar;
+
+ QTextStream ts ( &f );
+ d-> m_sysverstr = ts. readLine ( ). mid ( 10 );
+
+ f. close ( );
+ } else {
+ f. setName ( "/etc/oz_version" );
+
+ if ( f. open ( IO_ReadOnly )) {
+ d-> m_systemstr = "OpenEmbedded/SIMpad";
+ d-> m_system = System_OpenZaurus;
+
+ QTextStream ts ( &f );
+ ts.setDevice ( &f );
+ d-> m_sysverstr = ts. readLine ( );
+ f. close ( );
+ }
+ }
+
+ m_leds [0] = m_leds [1] = Led_Off;
+
+ m_power_timer = 0;
+
+}
+
+void SIMpad::initButtons ( )
+{
+ if ( d-> m_buttons )
+ return;
+
+ if ( isQWS( ) )
+ QWSServer::setKeyboardFilter ( this );
+
+ d-> m_buttons = new QValueList <ODeviceButton>;
+
+ for ( uint i = 0; i < ( sizeof( simpad_buttons ) / sizeof( s_button )); i++ ) {
+ s_button *sb = simpad_buttons + i;
+ ODeviceButton b;
+
+ if (( sb-> model & d-> m_model ) == d-> m_model ) {
+ b. setKeycode ( sb-> code );
+ b. setUserText ( QObject::tr ( "Button", sb-> utext ));
+ b. setPixmap ( Resource::loadPixmap ( sb-> pix ));
+ b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( sb-> fpressedservice ), sb-> fpressedaction ));
+ b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( sb-> fheldservice ), sb-> fheldaction ));
+
+ d-> m_buttons-> append ( b );
+ }
+ }
+ reloadButtonMapping ( );
+
+ QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
+ connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( systemMessage(const QCString&,const QByteArray&)));
+}
+
+// SIMpad boardcontrol register CS3
+#define SIMPAD_BOARDCONTROL "/proc/cs3"
+#define SIMPAD_VCC_5V_EN 0x0001 // For 5V PCMCIA
+#define SIMPAD_VCC_3V_EN 0x0002 // FOR 3.3V PCMCIA
+#define SIMPAD_EN1 0x0004 // This is only for EPROM's
+#define SIMPAD_EN0 0x0008 // Both should be enable for 3.3V or 5V
+#define SIMPAD_DISPLAY_ON 0x0010
+#define SIMPAD_PCMCIA_BUFF_DIS 0x0020
+#define SIMPAD_MQ_RESET 0x0040
+#define SIMPAD_PCMCIA_RESET 0x0080
+#define SIMPAD_DECT_POWER_ON 0x0100
+#define SIMPAD_IRDA_SD 0x0200 // Shutdown for powersave
+#define SIMPAD_RS232_ON 0x0400
+#define SIMPAD_SD_MEDIAQ 0x0800 // Shutdown for powersave
+#define SIMPAD_LED2_ON 0x1000
+#define SIMPAD_IRDA_MODE 0x2000 // Fast/Slow IrDA mode
+#define SIMPAD_ENABLE_5V 0x4000 // Enable 5V circuit
+#define SIMPAD_RESET_SIMCARD 0x8000
+
+//SIMpad touchscreen backlight strength control
+#define SIMPAD_BACKLIGHT_CONTROL "/proc/driver/mq200/registers/PWM_CONTROL"
+#define SIMPAD_BACKLIGHT_MASK 0x00a10044
+
+QValueList <OLed> SIMpad::ledList ( ) const
+{
+ QValueList <OLed> vl;
+ vl << Led_Power; //FIXME which LED is LED2 ? The green one or the amber one?
+ //vl << Led_Mail; //TODO find out if LED1 is accessible anyway
+ return vl;
+}
+
+QValueList <OLedState> SIMpad::ledStateList ( OLed l ) const
+{
+ QValueList <OLedState> vl;
+
+ if ( l == Led_Power ) //FIXME which LED is LED2 ? The green one or the amber one?
+ vl << Led_Off << Led_On;
+ //else if ( l == Led_Mail ) //TODO find out if LED1 is accessible anyway
+ //vl << Led_Off;
+ return vl;
+}
+
+OLedState SIMpad::ledState ( OLed l ) const
+{
+ switch ( l ) {
+ case Led_Power:
+ return m_leds [0];
+ //case Led_Mail:
+ // return m_leds [1];
+ default:
+ return Led_Off;
+ }
+}
+
+bool SIMpad::setLedState ( OLed l, OLedState st )
+{
+ static int fd = ::open ( SIMPAD_BOARDCONTROL, O_RDWR | O_NONBLOCK );
+
+ if ( l == Led_Power ) {
+ if ( fd >= 0 ) {
+ LED_IN leds;
+ ::memset ( &leds, 0, sizeof( leds ));
+ leds. TotalTime = 0;
+ leds. OnTime = 0;
+ leds. OffTime = 1;
+ leds. OffOnBlink = 2;
+
+ switch ( st ) {
+ case Led_Off : leds. OffOnBlink = 0; break;
+ case Led_On : leds. OffOnBlink = 1; break;
+ case Led_BlinkSlow: leds. OnTime = 10; leds. OffTime = 10; break;
+ case Led_BlinkFast: leds. OnTime = 5; leds. OffTime = 5; break;
+ }
+
+ {
+ /*TODO Implement this like that:
+ read from cs3
+ && with SIMPAD_LED2_ON
+ write to cs3 */
+ m_leds [0] = st;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+bool SIMpad::filter ( int /*unicode*/, int /*keycode*/, int /*modifiers*/, bool /*isPress*/, bool /*autoRepeat*/ )
+{
+ //TODO
+ return false;
+}
+
+void SIMpad::timerEvent ( QTimerEvent * )
+{
+ killTimer ( m_power_timer );
+ m_power_timer = 0;
+ QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, true, false );
+ QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, false, false );
+}
+
+
+void SIMpad::alarmSound ( )
+{
+#ifndef QT_NO_SOUND
+ static Sound snd ( "alarm" );
+ int fd;
+ int vol;
+ bool vol_reset = false;
+
+ if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) {
+ if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) {
+ Config cfg ( "qpe" );
+ cfg. setGroup ( "Volume" );
+
+ int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 );
+ if ( volalarm < 0 )
+ volalarm = 0;
+ else if ( volalarm > 100 )
+ volalarm = 100;
+ volalarm |= ( volalarm << 8 );
+
+ if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 )
+ vol_reset = true;
+ }
+ }
+
+ snd. play ( );
+ while ( !snd. isFinished ( ))
+ qApp-> processEvents ( );
+
+ if ( fd >= 0 ) {
+ if ( vol_reset )
+ ::ioctl ( fd, MIXER_WRITE( 0 ), &vol );
+ ::close ( fd );
+ }
+#endif
+}
+
+
+bool SIMpad::suspend ( ) // Must override because SIMpad does NOT have apm
+{
+ qDebug( "ODevice for SIMpad: suspend()" );
+ if ( !isQWS( ) ) // only qwsserver is allowed to suspend
+ return false;
+
+ bool res = false;
+
+ struct timeval tvs;
+ ::gettimeofday ( &tvs, 0 );
+
+ ::sync ( ); // flush fs caches
+ res = ( ::system ( "cat /dev/fb/0 >/tmp/.buffer; echo > /proc/sys/pm/suspend; cat /tmp/.buffer >/dev/fb/0" ) == 0 ); //TODO make better :)
+
+ return res;
+}
+
+
+bool SIMpad::setSoftSuspend ( bool soft )
+{
+ qDebug( "ODevice for SIMpad: UNHANDLED setSoftSuspend(%s)", soft? "on" : "off" );
+ return false;
+}
+
+
+bool SIMpad::setDisplayStatus ( bool on )
+{
+ qDebug( "ODevice for SIMpad: setDisplayStatus(%s)", on? "on" : "off" );
+
+ bool res = false;
+
+ QString cmdline = QString().sprintf( "echo %s > /proc/cs3", on ? "0xd41a" : "0xd40a" ); //TODO make better :)
+
+ res = ( ::system( (const char*) cmdline ) == 0 );
+
+ return res;
+}
+
+
+bool SIMpad::setDisplayBrightness ( int bright )
+{
+ qDebug( "ODevice for SIMpad: setDisplayBrightness( %d )", bright );
+ bool res = false;
+ int fd;
+
+ if ( bright > 255 )
+ bright = 255;
+ if ( bright < 1 )
+ bright = 0;
+
+ if (( fd = ::open ( SIMPAD_BACKLIGHT_CONTROL, O_WRONLY )) >= 0 ) {
+ int value = 255 - bright;
+ const int mask = SIMPAD_BACKLIGHT_MASK;
+ value = value << 8;
+ value += mask;
+ char writeCommand[100];
+ const int count = sprintf( writeCommand, "0x%x\n", value );
+ res = ( ::write ( fd, writeCommand, count ) != -1 );
+ ::close ( fd );
+ }
+ return res;
+}
+
+
+int SIMpad::displayBrightnessResolution ( ) const
+{
+ return 255; // All SIMpad models share the same display
+}
+
+/**************************************************
+ *
+ * Ramses
+ *
+ **************************************************/
+
+void Ramses::init()
+{
+ d->m_vendorstr = "M und N";
+ d->m_vendor = Vendor_MundN;
+
+ QFile f("/proc/sys/board/ramses");
+
+ d->m_modelstr = "Ramses";
+ d->m_model = Model_Ramses_MNCI;
+
+ d->m_rotation = Rot90;
+ d->m_holdtime = 1000;
+
+ f.setName("/etc/oz_version");
+
+ if (f.open(IO_ReadOnly)) {
+ d->m_systemstr = "OpenEmbedded/Ramses";
+ d->m_system = System_OpenZaurus;
+
+ QTextStream ts(&f);
+ ts.setDevice(&f);
+ d->m_sysverstr = ts.readLine();
+ f.close();
+ }
+
+ m_power_timer = 0;
+
+#ifdef QT_QWS_ALLOW_OVERCLOCK
+#warning *** Overclocking enabled - this may fry your hardware - you have been warned ***
+#define OC(x...) x
+#else
+#define OC(x...)
+#endif
+
+
+ // This table is true for a Intel XScale PXA 255
+
+ d->m_cpu_frequencies->append("99000"); // mem= 99, run= 99, turbo= 99, PXbus= 50
+OC( d->m_cpu_frequencies->append("118000"); ) // mem=118, run=118, turbo=118, PXbus= 59 OC'd mem
+ d->m_cpu_frequencies->append("199100"); // mem= 99, run=199, turbo=199, PXbus= 99
+OC( d->m_cpu_frequencies->append("236000"); ) // mem=118, run=236, turbo=236, PXbus=118 OC'd mem
+ d->m_cpu_frequencies->append("298600"); // mem= 99, run=199, turbo=298, PXbus= 99
+OC( d->m_cpu_frequencies->append("354000"); ) // mem=118, run=236, turbo=354, PXbus=118 OC'd mem
+ d->m_cpu_frequencies->append("398099"); // mem= 99, run=199, turbo=398, PXbus= 99
+ d->m_cpu_frequencies->append("398100"); // mem= 99, run=398, turbo=398, PXbus=196
+OC( d->m_cpu_frequencies->append("471000"); ) // mem=118, run=471, turbo=471, PXbus=236 OC'd mem/core/bus
+
+}
+
+bool Ramses::filter(int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat)
+{
+ Q_UNUSED( keycode );
+ Q_UNUSED( modifiers );
+ Q_UNUSED( isPress );
+ Q_UNUSED( autoRepeat );
+ return false;
+}
+
+void Ramses::timerEvent(QTimerEvent *)
+{
+ killTimer(m_power_timer);
+ m_power_timer = 0;
+ QWSServer::sendKeyEvent(-1, HardKey_Backlight, 0, true, false);
+ QWSServer::sendKeyEvent(-1, HardKey_Backlight, 0, false, false);
+}
+
+
+bool Ramses::setSoftSuspend(bool soft)
+{
+ qDebug("Ramses::setSoftSuspend(%d)", soft);
+#if 0
+ bool res = false;
+ int fd;
+
+ if (((fd = ::open("/dev/apm_bios", O_RDWR)) >= 0) ||
+ ((fd = ::open("/dev/misc/apm_bios",O_RDWR)) >= 0)) {
+
+ int sources = ::ioctl(fd, APM_IOCGEVTSRC, 0); // get current event sources
+
+ if (sources >= 0) {
+ if (soft)
+ sources &= ~APM_EVT_POWER_BUTTON;
+ else
+ sources |= APM_EVT_POWER_BUTTON;
+
+ if (::ioctl(fd, APM_IOCSEVTSRC, sources) >= 0) // set new event sources
+ res = true;
+ else
+ perror("APM_IOCGEVTSRC");
+ }
+ else
+ perror("APM_IOCGEVTSRC");
+
+ ::close(fd);
+ }
+ else
+ perror("/dev/apm_bios or /dev/misc/apm_bios");
+
+ return res;
+#else
+ return true;
+#endif
+}
+
+bool Ramses::suspend ( )
+{
+ qDebug("Ramses::suspend");
+ return false;
+}
+
+/**
+ * This sets the display on or off
+ */
+bool Ramses::setDisplayStatus(bool on)
+{
+ qDebug("Ramses::setDisplayStatus(%d)", on);
+#if 0
+ bool res = false;
+ int fd;
+
+ if ((fd = ::open ("/dev/fb/0", O_RDWR)) >= 0) {
+ res = (::ioctl(fd, FBIOBLANK, on ? VESA_NO_BLANKING : VESA_POWERDOWN) == 0);
+ ::close(fd);
+ }
+ return res;
+#else
+ return true;
+#endif
+}
+
+
+/*
+ * We get something between 0..255 into us
+*/
+bool Ramses::setDisplayBrightness(int bright)
+{
+ qDebug("Ramses::setDisplayBrightness(%d)", bright);
+ bool res = false;
+ int fd;
+
+ // pwm1 brighness: 20 steps 500..0 (dunkel->hell)
+
+ if (bright > 255 )
+ bright = 255;
+ if (bright < 0)
+ bright = 0;
+
+ // Turn backlight completely off
+ if ((fd = ::open("/proc/sys/board/lcd_backlight", O_WRONLY)) >= 0) {
+ char writeCommand[10];
+ const int count = sprintf(writeCommand, "%d\n", bright ? 1 : 0);
+ res = (::write(fd, writeCommand, count) != -1);
+ ::close(fd);
+ }
+
+ // scale backlight brightness to hardware
+ bright = 500-(bright * 500 / 255);
+ if ((fd = ::open("/proc/sys/board/pwm1", O_WRONLY)) >= 0) {
+ qDebug(" %d -> pwm1", bright);
+ char writeCommand[100];
+ const int count = sprintf(writeCommand, "%d\n", bright);
+ res = (::write(fd, writeCommand, count) != -1);
+ ::close(fd);
+ }
+ return res;
+}
+
+
+int Ramses::displayBrightnessResolution() const
+{
+ return 32;
+}
+
+bool Ramses::setDisplayContrast(int contr)
+{
+ qDebug("Ramses::setDisplayContrast(%d)", contr);
+ bool res = false;
+ int fd;
+
+ // pwm0 contrast: 20 steps 79..90 (dunkel->hell)
+
+ if (contr > 255 )
+ contr = 255;
+ if (contr < 0)
+ contr = 0;
+ contr = 90 - (contr * 20 / 255);
+
+ if ((fd = ::open("/proc/sys/board/pwm0", O_WRONLY)) >= 0) {
+ qDebug(" %d -> pwm0", contr);
+ char writeCommand[100];
+ const int count = sprintf(writeCommand, "%d\n", contr);
+ res = (::write(fd, writeCommand, count) != -1);
+ res = true;
+ ::close(fd);
+ }
+ return res;
+}
+
+
+int Ramses::displayContrastResolution() const
+{
+ return 20;
+}
+
+
+/**************************************************
+ * *
+ * Jornada *
+ * *
+ **************************************************/
+
+
+bool Jornada::isJornada ( )
+{
+ QFile f( "/proc/cpuinfo" );
+ if ( f. open ( IO_ReadOnly ) ) {
+ QTextStream ts ( &f );
+ QString line;
+ while( line = ts. readLine ( ) ) {
+ if ( line. left ( 8 ) == "Hardware" ) {
+ int loc = line. find ( ":" );
+ if ( loc != -1 ) {
+ QString model =
+ line. mid ( loc + 2 ). simplifyWhiteSpace( );
+ return ( model == "HP Jornada 56x" );
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void Jornada::init ( )
+{
+ d-> m_vendorstr = "HP";
+ d-> m_vendor = Vendor_HP;
+ d-> m_modelstr = "Jornada 56x";
+ d-> m_model = Model_Jornada_56x;
+ d-> m_systemstr = "Familiar";
+ d-> m_system = System_Familiar;
+ d-> m_rotation = Rot0;
+
+ QFile f ( "/etc/familiar-version" );
+ f. setName ( "/etc/familiar-version" );
+ if ( f. open ( IO_ReadOnly )) {
+
+ QTextStream ts ( &f );
+ d-> m_sysverstr = ts. readLine ( ). mid ( 10 );
+
+ f. close ( );
+ }
+}
+
+#if 0
+void Jornada::initButtons ( )
+{
+ if ( d-> m_buttons )
+ return;
+
+ // Simulation uses iPAQ 3660 device buttons
+
+ qDebug ( "init Buttons" );
+ d-> m_buttons = new QValueList <ODeviceButton>;
+
+ for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) {
+ i_button *ib = ipaq_buttons + i;
+ ODeviceButton b;
+
+ if (( ib-> model & Model_iPAQ_H36xx ) == Model_iPAQ_H36xx ) {
+ b. setKeycode ( ib-> code );
+ b. setUserText ( QObject::tr ( "Button", ib-> utext ));
+ b. setPixmap ( Resource::loadPixmap ( ib-> pix ));
+ b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib-> fpressedservice ), ib-> fpressedaction ));
+ b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib-> fheldservice ), ib-> fheldaction ));
+ d-> m_buttons-> append ( b );
+ }
+ }
+ reloadButtonMapping ( );
+
+ QCopChannel *sysch = new QCopChannel ( "QPE/System", this );
+ connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( systemMessage(const QCString&,const QByteArray&)));
+}
+#endif
+int Jornada::displayBrightnessResolution ( ) const
+{
+ return 255;
+}
+
+bool Jornada::setDisplayBrightness ( int bright )
+{
+ bool res = false;
+ int fd;
+
+ if ( bright > 255 )
+ bright = 255;
+ if ( bright < 0 )
+ bright = 0;
+
+ if (( fd = ::open ( "/dev/touchscreen/0", O_WRONLY )) >= 0 ) {
+ FLITE_IN bl;
+ bl. mode = 1;
+ bl. pwr = bright ? 1 : 0;
+ bl. brightness = ( bright * ( displayBrightnessResolution ( ) - 1 ) + 127 ) / 255;
+ res = ( ::ioctl ( fd, FLITE_ON, &bl ) == 0 );
+ ::close ( fd );
+ }
+ return res;
+}
+
+bool Jornada::setSoftSuspend ( bool soft )
+{
+ bool res = false;
+ int fd;
+
+ if (( fd = ::open ( "/proc/sys/ts/suspend_button_mode", O_WRONLY )) >= 0 ) {
+ if ( ::write ( fd, soft ? "1" : "0", 1 ) == 1 )
+ res = true;
+ else
+ ::perror ( "write to /proc/sys/ts/suspend_button_mode" );
+
+ ::close ( fd );
+ }
+ else
+ ::perror ( "/proc/sys/ts/suspend_button_mode" );
+
+ return res;
+}
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 @@
+/* This file is part of the OPIE libraries
+ Copyright (C) 2002 Robert Griebl (sandman@handhelds.org)
+ Copyright (C) 2003 Holger 'zecke' Freyther (zecke@handhelds.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _LIBOPIE_ODEVICE_H_
+#define _LIBOPIE_ODEVICE_H_
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qnamespace.h>
+#include <qstrlist.h>
+
+#include <opie/odevicebutton.h>
+
+#include <qpe/qpeapplication.h> /* for Transformation enum.. */
+
+class ODeviceData;
+
+namespace Opie {
+
+/**
+ * The available devices
+ */
+enum OModel {
+ Model_Unknown, // = 0
+
+ Model_Series_Mask = 0xff000000,
+
+ Model_iPAQ = ( 1 << 24 ),
+
+ Model_iPAQ_All = ( Model_iPAQ | 0xffffff ),
+ Model_iPAQ_H31xx = ( Model_iPAQ | 0x000001 ),
+ Model_iPAQ_H36xx = ( Model_iPAQ | 0x000002 ),
+ Model_iPAQ_H37xx = ( Model_iPAQ | 0x000004 ),
+ Model_iPAQ_H38xx = ( Model_iPAQ | 0x000008 ),
+ Model_iPAQ_H39xx = ( Model_iPAQ | 0x000010 ),
+ Model_iPAQ_H5xxx = ( Model_iPAQ | 0x000011 ),
+
+ Model_Jornada = ( 6 << 24 ),
+ Model_Jornada_56x = ( Model_Jornada | 0x000001 ),
+
+ Model_Zaurus = ( 2 << 24 ),
+
+ Model_Zaurus_SL5000 = ( Model_Zaurus | 0x000001 ),
+ Model_Zaurus_SL5500 = ( Model_Zaurus | 0x000002 ),
+ Model_Zaurus_SLA300 = ( Model_Zaurus | 0x000003 ),
+ Model_Zaurus_SLB600 = ( Model_Zaurus | 0x000004 ),
+ Model_Zaurus_SLC7x0 = ( Model_Zaurus | 0x000005 ),
+
+ Model_SIMpad = ( 3 << 24 ),
+
+ Model_SIMpad_All = ( Model_SIMpad | 0xffffff ),
+ Model_SIMpad_CL4 = ( Model_SIMpad | 0x000001 ),
+ Model_SIMpad_SL4 = ( Model_SIMpad | 0x000002 ),
+ Model_SIMpad_SLC = ( Model_SIMpad | 0x000004 ),
+ Model_SIMpad_TSinus = ( Model_SIMpad | 0x000008 ),
+
+ Model_Ramses = ( 4 << 24 ),
+
+ Model_Ramses_All = ( Model_Ramses | 0xffffff ),
+ Model_Ramses_MNCI = ( Model_Ramses | 0x000001 ),
+
+ Model_Yopy = ( 5 << 24 ),
+
+ Model_Yopy_All = ( Model_Yopy | 0xffffff ),
+ Model_Yopy_3000 = ( Model_Yopy | 0x000001 ),
+ Model_Yopy_3500 = ( Model_Yopy | 0x000002 ),
+ Model_Yopy_3700 = ( Model_Yopy | 0x000003 ),
+
+};
+
+/**
+ * The vendor of the device
+ */
+enum OVendor {
+ Vendor_Unknown,
+
+ Vendor_HP,
+ Vendor_Sharp,
+ Vendor_SIEMENS,
+ Vendor_MundN,
+ Vendor_GMate,
+};
+
+/**
+ * The System used
+ */
+enum OSystem {
+ System_Unknown,
+
+ System_Familiar,
+ System_Zaurus,
+ System_OpenZaurus,
+ System_Linupy,
+};
+
+enum OLedState {
+ Led_Off,
+ Led_On,
+ Led_BlinkSlow,
+ Led_BlinkFast
+};
+
+enum OLed {
+ Led_Mail,
+ Led_Power,
+ Led_BlueTooth
+};
+
+enum OHardKey {
+ HardKey_Datebook = Qt::Key_F9,
+ HardKey_Contacts = Qt::Key_F10,
+ HardKey_Menu = Qt::Key_F11,
+ HardKey_Home = Qt::Key_F12,
+ HardKey_Mail = Qt::Key_F13,
+ HardKey_Record = Qt::Key_F24,
+ HardKey_Suspend = Qt::Key_F34,
+ HardKey_Backlight = Qt::Key_F35,
+ HardKey_Action = Qt::Key_F10,
+ HardKey_OK = Qt::Key_F11,
+ HardKey_End = Qt::Key_F12,
+};
+
+enum ODirection {
+ CW = 0,
+ CCW = 1,
+ Flip = 2,
+};
+
+enum OHingeStatus {
+ CASE_CLOSED = 3,
+ CASE_PORTRAIT = 2,
+ CASE_LANDSCAPE = 0,
+ CASE_UNKNOWN = 1,
+};
+
+/**
+ * A singleton which gives informations about device specefic option
+ * like the Hardware used, LEDs, the Base Distribution and
+ * hardware key mappings.
+ *
+ * @short A small class for device specefic options
+ * @see QObject
+ * @author Robert Griebl
+ * @version 1.0
+ */
+class ODevice : public QObject {
+ Q_OBJECT
+
+private:
+ /* disable copy */
+ ODevice ( const ODevice & );
+
+protected:
+ ODevice ( );
+ virtual void init ( );
+ virtual void initButtons ( );
+
+ ODeviceData *d;
+
+public:
+ // sandman do we want to allow destructions? -zecke?
+ virtual ~ODevice ( );
+
+ static ODevice *inst ( );
+
+ // information
+
+ QString modelString ( ) const;
+ OModel model ( ) const;
+ inline OModel series ( ) const { return (OModel) ( model ( ) & Model_Series_Mask ); }
+
+ QString vendorString ( ) const;
+ OVendor vendor ( ) const;
+
+ QString systemString ( ) const;
+ OSystem system ( ) const;
+
+ QString systemVersionString ( ) const;
+
+ /*virtual*/ Transformation rotation ( ) const;
+ /*virtual*/ ODirection direction ( ) const;
+
+// system
+
+ virtual bool setSoftSuspend ( bool on );
+ virtual bool suspend ( );
+
+ virtual bool setDisplayStatus ( bool on );
+ virtual bool setDisplayBrightness ( int brightness );
+ virtual int displayBrightnessResolution ( ) const;
+ virtual bool setDisplayContrast ( int contrast );
+ virtual int displayContrastResolution ( ) const;
+
+ // don't add new virtual methods, use this:
+ // /*virtual */ void boo(int i ) { return virtual_hook(1,&i); };
+ // and in your subclass do do overwrite
+ // protected virtual int virtual_hook(int, void *)
+ // which is defined below
+
+ // input / output
+ //FIXME playAlarmSound and al might be better -zecke
+ virtual void alarmSound ( );
+ virtual void keySound ( );
+ virtual void touchSound ( );
+
+ virtual QValueList <OLed> ledList ( ) const;
+ virtual QValueList <OLedState> ledStateList ( OLed led ) const;
+ virtual OLedState ledState ( OLed led ) const;
+ virtual bool setLedState ( OLed led, OLedState st );
+
+ virtual bool hasLightSensor ( ) const;
+ virtual int readLightSensor ( );
+ virtual int lightSensorResolution ( ) const;
+
+ /*virtual*/ bool hasHingeSensor ( ) const;
+ /*virtual*/ OHingeStatus readHingeSensor ( );
+
+ const QStrList &allowedCpuFrequencies() const;
+ bool setCurrentCpuFrequency(uint index);
+
+ /**
+ * Returns the available buttons on this device. The number and location
+ * of buttons will vary depending on the device. Button numbers will be assigned
+ * by the device manufacturer and will be from most preferred button to least preffered
+ * button. Note that this list only contains "user mappable" buttons.
+ *
+ * @todo ### make const
+ */
+ const QValueList<ODeviceButton> &buttons ( ) /** /todo ### make const */;
+
+ /**
+ * Returns the DeviceButton for the \a keyCode. If \a keyCode is not found, it
+ * returns 0L
+ */
+ const ODeviceButton *buttonForKeycode ( ushort keyCode );
+
+ /**
+ * Reassigns the pressed action for \a button. To return to the factory
+ * default pass an empty string as \a qcopMessage.
+ */
+ void remapPressedAction ( int button, const OQCopMessage &qcopMessage );
+
+ /**
+ * Reassigns the held action for \a button. To return to the factory
+ * default pass an empty string as \a qcopMessage.
+ */
+ void remapHeldAction ( int button, const OQCopMessage &qcopMessage );
+
+ /**
+ * How long (in ms) you have to press a button for a "hold" action
+ */
+ uint buttonHoldTime ( ) const;
+
+signals:
+ void buttonMappingChanged ( );
+
+private slots:
+ void systemMessage ( const QCString &, const QByteArray & );
+
+protected:
+ void reloadButtonMapping ( );
+ /* ugly virtual hook */
+ virtual void virtual_hook( int id, void* data );
+
+protected:
+ enum { VIRTUAL_ROTATION = 0x200, VIRTUAL_DIRECTION,
+ VIRTUAL_HAS_HINGE, VIRTUAL_HINGE };
+ struct VirtRotation {
+ Transformation trans;
+ };
+ struct VirtDirection {
+ ODirection direct;
+ };
+ struct VirtHasHinge {
+ bool hasHinge;
+ };
+ struct VirtHingeStatus {
+ OHingeStatus hingeStat;
+ };
+};
+
+}
+
+#endif
+
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 @@
+/**********************************************************************
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+#include <qpe/qcopenvelope_qws.h>
+#include <opie/odevicebutton.h>
+
+using namespace Opie;
+
+
+class OQCopMessageData {
+public:
+ QCString m_channel;
+ QCString m_message;
+ QByteArray m_data;
+};
+
+
+OQCopMessage::OQCopMessage ( )
+ : d ( 0 )
+{
+ init ( QCString ( ), QCString ( ), QByteArray ( ));
+}
+
+OQCopMessage::OQCopMessage ( const OQCopMessage &copy )
+ : d ( 0 )
+{
+ init ( copy. channel ( ), copy. message ( ), copy. data ( ));
+}
+
+OQCopMessage &OQCopMessage::operator = ( const OQCopMessage &assign )
+{
+ init ( assign. channel ( ), assign. message ( ), assign. data ( ));
+ return *this;
+}
+
+OQCopMessage::OQCopMessage ( const QCString &ch, const QCString &m, const QByteArray &arg )
+ : d ( 0 )
+{
+ init ( ch, m, arg );
+}
+
+void OQCopMessage::init ( const QCString &ch, const QCString &m, const QByteArray &arg )
+{
+ if ( !d )
+ d = new OQCopMessageData ( );
+ d-> m_channel = ch;
+ d-> m_message = m;
+ d-> m_data = arg;
+}
+
+bool OQCopMessage::send ( )
+{
+ if ( d-> m_channel. isEmpty ( ) || d-> m_message. isEmpty ( ) )
+ return false;
+
+ QCopEnvelope e ( d-> m_channel, d-> m_message );
+
+ if ( d-> m_data. size ( ))
+ e. writeRawBytes ( d-> m_data. data ( ), d-> m_data. size ( ));
+
+ return true;
+}
+
+QCString OQCopMessage::channel ( ) const
+{
+ return d-> m_channel;
+}
+
+QCString OQCopMessage::message ( ) const
+{
+ return d-> m_message;
+}
+
+QByteArray OQCopMessage::data ( ) const
+{
+ return d-> m_data;
+}
+
+bool OQCopMessage::isNull() const
+{
+ return d-> m_message.isNull() || d-> m_channel.isNull();
+}
+void OQCopMessage::setChannel ( const QCString &ch )
+{
+ d-> m_channel = ch;
+}
+
+void OQCopMessage::setMessage ( const QCString &m )
+{
+ d-> m_message = m;
+}
+
+void OQCopMessage::setData ( const QByteArray &data )
+{
+ d-> m_data = data;
+}
+
+/*! \class Opie::ODeviceButton
+ \brief The Opie::ODeviceButton class represents a physical user mappable button on a Qtopia device.
+
+ This class represents a physical button on a Qtopia device. A
+ device may have "user programmable" buttons.
+ The location and number of buttons will vary from device to
+ device. userText() and pixmap() may be used to describe this button
+ to the user in help documentation.
+
+ \ingroup qtopiaemb
+ \internal
+*/
+
+ODeviceButton::ODeviceButton()
+{
+}
+
+ODeviceButton::~ODeviceButton()
+{
+}
+
+/*!
+ Returns the button's keycode.
+ */
+ushort ODeviceButton::keycode() const
+{
+ return m_Keycode;
+}
+
+
+/*!
+ This function returns a human readable, translated description of the button.
+ */
+QString ODeviceButton::userText() const
+{
+ return m_UserText;
+}
+
+/*!
+ This function returns the pixmap for this button. If there isn't one
+ it will return an empty (null) pixmap.
+ */
+QPixmap ODeviceButton::pixmap() const
+{
+ return m_Pixmap;
+}
+
+/*!
+ This function returns the factory preset (default) action for when this button
+ is pressed. The return value is a legal QCop message.
+ */
+OQCopMessage ODeviceButton::factoryPresetPressedAction() const
+{
+ return m_FactoryPresetPressedAction;
+}
+
+/*!
+ This function returns the user assigned action for when this button is pressed.
+ If no action is assigned, factoryPresetAction() is returned.
+ */
+OQCopMessage ODeviceButton::pressedAction() const
+{
+ if (m_PressedAction.channel().isEmpty())
+ return factoryPresetPressedAction();
+ return m_PressedAction;
+}
+
+/*!
+ This function returns the factory preset (default) action for when this button
+ is pressed and held. The return value is a legal QCop message.
+ */
+OQCopMessage ODeviceButton::factoryPresetHeldAction() const
+{
+ return m_FactoryPresetHeldAction;
+}
+
+/*!
+ This function returns the user assigned action for when this button is pressed
+ and held. If no action is assigned, factoryPresetAction() is returned.
+ */
+OQCopMessage ODeviceButton::heldAction() const
+{
+ if (m_HeldAction.channel().isEmpty())
+ return factoryPresetHeldAction();
+ return m_HeldAction;
+}
+
+void ODeviceButton::setKeycode(ushort keycode)
+{
+ m_Keycode = keycode;
+}
+
+void ODeviceButton::setUserText(const QString& text)
+{
+ m_UserText = text;
+}
+
+void ODeviceButton::setPixmap(const QPixmap& picture)
+{
+ m_Pixmap = picture;
+}
+
+void ODeviceButton::setFactoryPresetPressedAction(const OQCopMessage& action)
+{
+ m_FactoryPresetPressedAction = action;
+}
+
+
+void ODeviceButton::setPressedAction(const OQCopMessage& action)
+{
+ m_PressedAction = action;
+}
+
+void ODeviceButton::setFactoryPresetHeldAction(const OQCopMessage& action)
+{
+ m_FactoryPresetHeldAction = action;
+}
+
+void ODeviceButton::setHeldAction(const OQCopMessage& action)
+{
+ m_HeldAction = action;
+}
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 @@
+/**********************************************************************
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef DEVICE_BUTTON_H
+#define DEVICE_BUTTON_H
+
+#include <qpixmap.h>
+#include <qstring.h>
+
+class OQCopMessageData;
+
+namespace Opie
+{
+
+class OQCopMessage {
+public:
+ OQCopMessage ( );
+ OQCopMessage ( const OQCopMessage &copy );
+ OQCopMessage ( const QCString &m_channel, const QCString &message, const QByteArray &args = QByteArray ( ));
+
+ OQCopMessage &operator = ( const OQCopMessage &assign );
+
+ void setChannel ( const QCString &channel );
+ void setMessage ( const QCString &message );
+ void setData ( const QByteArray &ba );
+
+ QCString channel ( ) const;
+ QCString message ( ) const;
+ QByteArray data ( ) const;
+
+ bool isNull()const;
+
+ bool send ( );
+
+private:
+ void init ( const QCString &m_channel, const QCString &message, const QByteArray &args );
+
+ OQCopMessageData *d;
+ class Private;
+ Private* m_data;
+};
+
+
+/**
+ * This class represents a physical button on a Qtopia device. A device may
+ * have n "user programmable" buttons, which are number 1..n. The location
+ * and number of buttons will vary from device to device. userText() and pixmap()
+ * may be used to describe this button to the user in help documentation.
+ *
+ * @version 1.0
+ * @author Trolltech
+ * @short A representation of buttons
+ */
+
+class ODeviceButton
+{
+public:
+ ODeviceButton();
+ virtual ~ODeviceButton();
+
+ ushort keycode ( ) const;
+ QString userText ( ) const;
+ QPixmap pixmap ( ) const;
+ OQCopMessage factoryPresetPressedAction ( ) const;
+ OQCopMessage pressedAction ( ) const;
+ OQCopMessage factoryPresetHeldAction ( ) const;
+ OQCopMessage heldAction ( ) const;
+
+ void setKeycode ( ushort keycode );
+ void setUserText ( const QString& text );
+ void setPixmap ( const QPixmap& picture );
+ void setFactoryPresetPressedAction ( const OQCopMessage& qcopMessage );
+ void setPressedAction ( const OQCopMessage& qcopMessage );
+ void setFactoryPresetHeldAction ( const OQCopMessage& qcopMessage );
+ void setHeldAction ( const OQCopMessage& qcopMessage );
+
+private:
+ ushort m_Keycode;
+ QString m_UserText;
+ QPixmap m_Pixmap;
+ OQCopMessage m_FactoryPresetPressedAction;
+ OQCopMessage m_PressedAction;
+ OQCopMessage m_FactoryPresetHeldAction;
+ OQCopMessage m_HeldAction;
+ class Private;
+ Private *d;
+};
+
+}
+
+#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 @@
+/*
+               =. This file is part of the OPIE Project
+             .=l. Copyright (c) 2002,2003 <zecke@handhelds.org>
+           .>+-=
+ _;:,     .>    :=|. This library is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This library is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include <qpe/config.h>
+#include <qpe/qpeapplication.h>
+
+#include <qfileinfo.h>
+#include <qlayout.h>
+
+
+#include "ofiledialog.h"
+
+
+namespace {
+ /*
+ * helper functions to load the start dir
+ * and to save it
+ * helper to extract the dir out of a file name
+ */
+ /**
+ * This method will use Config( argv[0] );
+ * @param key The group key used
+ */
+ QString lastUsedDir( const QString& key ) {
+ if ( qApp->argc() < 1 )
+ return QString::null;
+
+ Config cfg( QFileInfo(qApp->argv()[0]).fileName() ); // appname
+ cfg.setGroup( key );
+ return cfg.readEntry("LastDir", QPEApplication::documentDir() );
+ }
+
+ void saveLastDir( const QString& key, const QString& file ) {
+ if ( qApp->argc() < 1 )
+ return;
+
+ Config cfg( QFileInfo(qApp->argv()[0]).fileName() );
+ cfg.setGroup( key );
+ QFileInfo inf( file );
+ cfg.writeEntry("LastDir", inf.dirPath( true ) );
+ }
+};
+
+/**
+ * This constructs a modal dialog
+ *
+ * @param caption The caption of the dialog
+ * @param wid The parent widget
+ * @param mode The mode of the OFileSelector @see OFileSelector
+ * @param selector The selector of the OFileSelector
+ * @param dirName the dir or resource to start from
+ * @param fileName a proposed or existing filename
+ * @param mimetypes The mimeTypes
+ */
+OFileDialog::OFileDialog(const QString &caption,
+ QWidget *wid, int mode, int selector,
+ const QString &dirName,
+ const QString &fileName,
+ const QMap<QString,QStringList>& mimetypes )
+ : QDialog( wid, "OFileDialog", true )
+{
+ // QVBoxLayout *lay = new QVBoxLayout(this);
+ //showMaximized();
+ QVBoxLayout *lay = new QVBoxLayout(this );
+ file = new OFileSelector(this , mode, selector,
+ dirName, fileName,
+ mimetypes );
+ lay->addWidget( file );
+
+ //lay->addWidget( file );
+ //showFullScreen();
+ setCaption( caption.isEmpty() ? tr("FileDialog") : caption );
+ connect(file, SIGNAL(fileSelected(const QString&) ),
+ this, SLOT(slotFileSelected(const QString&) ) );
+ connect(file, SIGNAL(ok() ),
+ this, SLOT(slotSelectorOk()) ) ;
+
+ connect(file, SIGNAL(dirSelected(const QString&) ), this, SLOT(slotDirSelected(const QString&) ) );
+
+#if 0
+ connect(file, SIGNAL(dirSelected(const QString &) ),
+ this, SLOT(slotDirSelected(const QString &) ) );
+#endif
+}
+/**
+ * @returns the mimetype of the selected
+ * currently it return QString::null
+ */
+QString OFileDialog::mimetype()const
+{
+ return QString::null;
+}
+
+/**
+ * @return the fileName
+ */
+QString OFileDialog::fileName()const
+{
+ return file->selectedName();
+}
+
+/**
+ * return a DocLnk to the current file
+ */
+DocLnk OFileDialog::selectedDocument()const
+{
+ return file->selectedDocument();
+}
+
+/**
+ * This opens up a filedialog in Open mode
+ *
+ * @param selector the Selector Mode
+ * @param startDir Where to start from
+ * @param file A proposed filename
+ * @param mimes A list of MimeTypes
+ * @param wid the parent
+ * @param caption of the dialog if QString::null tr("Open") will be used
+ * @return the fileName or QString::null
+ */
+QString OFileDialog::getOpenFileName(int selector,
+ const QString &_startDir,
+ const QString &file,
+ const MimeTypes &mimes,
+ QWidget *wid,
+ const QString &caption )
+{
+ QString ret;
+ QString startDir = _startDir;
+ if (startDir.isEmpty() )
+ startDir = lastUsedDir( "FileDialog-OPEN" );
+
+
+ OFileDialog dlg( caption.isEmpty() ? tr("Open") : caption,
+ wid, OFileSelector::Open, selector, startDir, file, mimes);
+ dlg.showMaximized();
+ if( dlg.exec() ) {
+ ret = dlg.fileName();
+ saveLastDir( "FileDialog-OPEN", ret );
+ }
+
+ return ret;
+}
+
+/**
+ * This opens up a file dialog in save mode
+ * @see getOpenFileName
+ */
+QString OFileDialog::getSaveFileName(int selector,
+ const QString &_startDir,
+ const QString &file,
+ const MimeTypes &mimes,
+ QWidget *wid,
+ const QString &caption )
+{
+ QString ret;
+ QString startDir = _startDir;
+ if (startDir.isEmpty() )
+ startDir = lastUsedDir( "FileDialog-SAVE" );
+
+ OFileDialog dlg( caption.isEmpty() ? tr("Save") : caption,
+ wid, OFileSelector::Save, selector, startDir, file, mimes);
+ dlg.showMaximized();
+ if( dlg.exec() ) {
+ ret = dlg.fileName();
+ saveLastDir( "FileDialog-SAVE", ret );
+ }
+
+ return ret;
+}
+
+void OFileDialog::slotFileSelected(const QString & )
+{
+ accept();
+}
+
+void OFileDialog::slotSelectorOk( )
+{
+ accept();
+}
+
+void OFileDialog::slotDirSelected(const QString &dir )
+{
+ setCaption( dir );
+ // if mode
+ //accept();
+}
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 @@
+/*
+               =. This file is part of the OPIE Project
+             .=l. Copyright (c) 2002 zecke <zecke@handhelds.org>
+           .>+-=
+ _;:,     .>    :=|. This library is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This library is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+
+#ifndef OpieFileDialog_h
+#define OpieFileDialog_h
+
+#include <qdialog.h>
+
+#include <opie/ofileselector.h>
+
+/**
+ * This class places a OFileSelector inside a QDialog.
+ * It provides static method for letting a user chose
+ * a file for either opening or saving.
+ * Most of the time the c'tor will not be used instead using
+ * the static member functions is prefered.
+ *
+ * <pre>
+ * QMap<QString, QStringList> mimeTypes;
+ * QStringList types;
+ * types << "text@slash* ";
+ * mimeTypes.insert( tr("Text"), types );
+ * mimeTypes.insert( tr("All"), " *@slash* " ); // remove the spaces in the 2nd comment
+ * QString fileName= OFileDialog::getOpenFileName( OFileSelector::EXTENDED_ALL,
+ * "foo","bar", mimeTypes);
+ * </pre>
+ *
+ * @short A small QDialog swalloing a FileSelector
+ * @see QDialog
+ * @see OFileSelector
+ * @version 0.1-unfinished
+ * @author Holger Freyther ( zecke@handhelds.org )
+ */
+class OFileDialog : public QDialog {
+ Q_OBJECT
+ public:
+ OFileDialog(const QString &caption,
+ QWidget *, int mode, int selector,
+ const QString &dirName,
+ const QString &fileName = QString::null,
+ const MimeTypes &mimetypes = MimeTypes() );
+ QString mimetype() const;
+ QString fileName() const;
+ DocLnk selectedDocument()const;
+
+ // static methods
+ static QString getOpenFileName(int selector,
+ const QString& startDir = QString::null,
+ const QString &fileName = QString::null,
+ const MimeTypes& mime = MimeTypes(),
+ QWidget *wid = 0,
+ const QString &caption = QString::null );
+
+ static QString getSaveFileName(int selector,
+ const QString& startDir = QString::null,
+ const QString& fileName = QString::null,
+ const MimeTypes& mimefilter = MimeTypes(),
+ QWidget *wid = 0,
+ const QString &caption = QString::null );
+
+ //let's OFileSelector catch up first
+ //static QString getExistingDirectory(const QString& startDir = QString::null,
+ // QWidget *parent = 0,
+ // const QString& caption = QString::null );
+ private:
+ class OFileDialogPrivate;
+ OFileDialogPrivate *d;
+ OFileSelector *file;
+
+ private slots:
+ void slotFileSelected( const QString & );
+ void slotDirSelected(const QString & );
+ void slotSelectorOk();
+};
+#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 @@
+#include <qcombobox.h>
+#include <qdir.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qpopupmenu.h>
+#include <qwidgetstack.h>
+
+/* hacky but we need to get FileSelector::filter */
+#define private public
+#include <qpe/fileselector.h>
+#undef private
+
+#include <qpe/qpeapplication.h>
+#include <qpe/mimetype.h>
+#include <qpe/resource.h>
+#include <qpe/storage.h>
+
+#include "ofileselector_p.h"
+#include "ofileselector.h"
+
+
+
+OFileViewInterface::OFileViewInterface( OFileSelector* selector )
+ : m_selector( selector ) {
+}
+OFileViewInterface::~OFileViewInterface() {
+}
+QString OFileViewInterface::name()const{
+ return m_name;
+}
+void OFileViewInterface::setName( const QString& name ) {
+ m_name = name;
+}
+OFileSelector* OFileViewInterface::selector()const {
+ return m_selector;
+}
+DocLnk OFileViewInterface::selectedDocument()const {
+ return DocLnk( selectedName() );
+}
+bool OFileViewInterface::showNew()const {
+ return selector()->showNew();
+}
+bool OFileViewInterface::showClose()const {
+ return selector()->showClose();
+}
+MimeTypes OFileViewInterface::mimeTypes()const {
+ return selector()->mimeTypes();
+}
+QStringList OFileViewInterface::currentMimeType()const {
+ return selector()->currentMimeType();
+}
+void OFileViewInterface::activate( const QString& ) {
+ // not implemented here
+}
+void OFileViewInterface::ok() {
+ emit selector()->ok();
+}
+void OFileViewInterface::cancel() {
+ emit selector()->cancel();
+}
+void OFileViewInterface::closeMe() {
+ emit selector()->closeMe();
+}
+void OFileViewInterface::fileSelected( const QString& str) {
+ emit selector()->fileSelected( str);
+}
+void OFileViewInterface::fileSelected( const DocLnk& lnk) {
+ emit selector()->fileSelected( lnk );
+}
+void OFileViewInterface::setCurrentFileName( const QString& str ) {
+ selector()->m_lneEdit->setText( str );
+}
+QString OFileViewInterface::currentFileName()const{
+ return selector()->m_lneEdit->text();
+}
+QString OFileViewInterface::startDirectory()const{
+ return selector()->m_startDir;
+}
+
+
+ODocumentFileView::ODocumentFileView( OFileSelector* selector )
+ : OFileViewInterface( selector ) {
+ m_selector = 0;
+ setName( QObject::tr("Documents") );
+}
+ODocumentFileView::~ODocumentFileView() {
+
+}
+QString ODocumentFileView::selectedName()const {
+ if (!m_selector)
+ return QString::null;
+
+ return m_selector->selectedDocument().file();
+}
+QString ODocumentFileView::selectedPath()const {
+ return QPEApplication::documentDir();
+}
+QString ODocumentFileView::directory()const {
+ return selectedPath();
+}
+void ODocumentFileView::reread() {
+ if (!m_selector)
+ return;
+
+ m_selector->setNewVisible( showNew() );
+ m_selector->setCloseVisible( showClose() );
+ m_selector->filter = currentMimeType().join(";");
+ m_selector->reread();
+}
+int ODocumentFileView::fileCount()const {
+ if (!m_selector)
+ return -1;
+
+ return m_selector->fileCount();
+}
+DocLnk ODocumentFileView::selectedDocument()const {
+ if (!m_selector)
+ return DocLnk();
+
+ return m_selector->selectedDocument();
+}
+QWidget* ODocumentFileView::widget( QWidget* parent ) {
+ if (!m_selector ) {
+ m_selector = new FileSelector(currentMimeType().join(";"), parent, "fileselector", showNew(), showClose() );
+ QObject::connect(m_selector, SIGNAL(fileSelected(const DocLnk&) ),
+ selector(), SLOT(slotDocLnkBridge(const DocLnk&) ) );
+ QObject::connect(m_selector, SIGNAL(closeMe() ),
+ selector(), SIGNAL(closeMe() ) );
+ QObject::connect(m_selector, SIGNAL(newSelected(const DocLnk&) ),
+ selector(), SIGNAL(newSelected(const DocLnk&) ) );
+ }
+
+ return m_selector;
+}
+
+/*
+ * This is the file system view used
+ * we use a QListView + QListViewItems for it
+ */
+
+OFileSelectorItem::OFileSelectorItem( QListView* view, const QPixmap& pixmap,
+ const QString& path, const QString& date,
+ const QString& size, const QString& dir,
+ bool isLocked, bool isDir )
+ : QListViewItem( view )
+{
+ setPixmap(0, pixmap );
+ setText(1, path );
+ setText(2, size );
+ setText(3, date );
+ m_isDir = isDir;
+ m_dir = dir;
+ m_locked = isLocked;
+}
+OFileSelectorItem::~OFileSelectorItem() {
+
+}
+bool OFileSelectorItem::isLocked()const {
+ return m_locked;
+}
+QString OFileSelectorItem::directory()const {
+ return m_dir;
+}
+bool OFileSelectorItem::isDir()const {
+ return m_isDir;
+}
+QString OFileSelectorItem::path()const {
+ return text( 1 );
+}
+QString OFileSelectorItem::key( int id, bool )const {
+ QString ke;
+ if( id == 0 || id == 1 ){ // name
+ if( m_isDir ){
+ ke.append("0" );
+ ke.append( text(1) );
+ }else{
+ ke.append("1" );
+ ke.append( text(1) );
+ }
+ return ke;
+ }else
+ return text( id );
+
+}
+
+OFileViewFileListView::OFileViewFileListView( QWidget* parent, const QString& startDir,
+ OFileSelector* sel)
+ : QWidget( parent ), m_sel( sel ) {
+ m_all = false;
+ QVBoxLayout* lay = new QVBoxLayout( this );
+ m_currentDir = startDir;
+
+ /*
+ * now we add a special bar
+ * One Button For Up
+ * Home
+ * Doc
+ * And a dropdown menu with FileSystems
+ * FUTURE: one to change dir with lineedit
+ * Bookmarks
+ * Create Dir
+ */
+ QHBox* box = new QHBox(this );
+ box->setBackgroundMode( PaletteButton );
+ box->setSpacing( 0 );
+
+ QToolButton *btn = new QToolButton( box );
+ btn->setIconSet( Resource::loadIconSet("up") );
+ connect(btn, SIGNAL(clicked() ),
+ this, SLOT( cdUP() ) );
+
+ btn = new QToolButton( box );
+ btn->setIconSet( Resource::loadIconSet("home") );
+ connect(btn, SIGNAL(clicked() ),
+ this, SLOT( cdHome() ) );
+
+ btn = new QToolButton( box );
+ btn->setIconSet( Resource::loadIconSet("DocsIcon") );
+ connect(btn, SIGNAL(clicked() ),
+ this, SLOT(cdDoc() ) );
+
+ m_btnNew = new QToolButton( box );
+ m_btnNew->setIconSet( Resource::loadIconSet("new") );
+ connect(m_btnNew, SIGNAL(clicked() ),
+ this, SLOT(slotNew() ) );
+
+
+ m_btnClose = new QToolButton( box );
+ m_btnClose->setIconSet( Resource::loadIconSet("close") );
+ connect(m_btnClose, SIGNAL(clicked() ),
+ selector(), SIGNAL(closeMe() ) );
+
+ btn = new QToolButton( box );
+ btn->setIconSet( Resource::loadIconSet("cardmon/pcmcia") );
+
+ /* let's fill device parts */
+ QPopupMenu* pop = new QPopupMenu(this);
+ connect(pop, SIGNAL( activated(int) ),
+ this, SLOT(slotFSActivated(int) ) );
+
+ StorageInfo storage;
+ const QList<FileSystem> &fs = storage.fileSystems();
+ QListIterator<FileSystem> it(fs);
+ for ( ; it.current(); ++it ) {
+ const QString disk = (*it)->name();
+ const QString path = (*it)->path();
+ m_dev.insert( disk, path );
+ pop->insertItem( disk );
+ }
+ m_fsPop = pop;
+
+
+ btn->setPopup( pop );
+
+ lay->addWidget( box );
+
+ m_view = new QListView( this );
+
+ m_view->installEventFilter(this);
+
+ QPEApplication::setStylusOperation( m_view->viewport(),
+ QPEApplication::RightOnHold);
+ m_view->addColumn(" " );
+ m_view->addColumn(tr("Name"), 135 );
+ m_view->addColumn(tr("Size"), -1 );
+ m_view->addColumn(tr("Date"), 60 );
+ m_view->addColumn(tr("Mime Type"), -1 );
+
+
+ m_view->setSorting( 1 );
+ m_view->setAllColumnsShowFocus( TRUE );
+
+ lay->addWidget( m_view, 1000 );
+ connectSlots();
+}
+OFileViewFileListView::~OFileViewFileListView() {
+}
+void OFileViewFileListView::slotNew() {
+ DocLnk lnk;
+ emit selector()->newSelected( lnk );
+}
+OFileSelectorItem* OFileViewFileListView::currentItem()const{
+ QListViewItem* item = m_view->currentItem();
+ if (!item )
+ return 0l;
+
+ return static_cast<OFileSelectorItem*>(item);
+}
+void OFileViewFileListView::reread( bool all ) {
+ m_view->clear();
+
+ if (selector()->showClose() )
+ m_btnClose->show();
+ else
+ m_btnClose->hide();
+
+ if (selector()->showNew() )
+ m_btnNew->show();
+ else
+ m_btnNew->hide();
+
+ m_mimes = selector()->currentMimeType();
+ m_all = all;
+
+ QDir dir( m_currentDir );
+ if (!dir.exists() )
+ return;
+
+ dir.setSorting( QDir::Name | QDir::DirsFirst | QDir::Reversed );
+ int filter;
+ if (m_all )
+ filter = QDir::Files | QDir::Dirs | QDir::Hidden | QDir::All;
+ else
+ filter = QDir::Files | QDir::Dirs | QDir::All;
+ dir.setFilter( filter );
+
+ // now go through all files
+ const QFileInfoList *list = dir.entryInfoList();
+ if (!list) {
+ cdUP();
+ return;
+ }
+ QFileInfoListIterator it( *list );
+ QFileInfo *fi;
+ while( (fi=it.current() ) ){
+ if( fi->fileName() == QString::fromLatin1("..") || fi->fileName() == QString::fromLatin1(".") ){
+ ++it;
+ continue;
+ }
+
+ /*
+ * It is a symlink we try to resolve it now but don't let us attack by DOS
+ *
+ */
+ if( fi->isSymLink() ){
+ QString file = fi->dirPath( true ) + "/" + fi->readLink();
+ for( int i = 0; i<=4; i++) { // 5 tries to prevent dos
+ QFileInfo info( file );
+ if( !info.exists() ){
+ addSymlink( fi, TRUE );
+ break;
+ }else if( info.isDir() ){
+ addDir( fi, TRUE );
+ break;
+ }else if( info.isFile() ){
+ addFile( fi, TRUE );
+ break;
+ }else if( info.isSymLink() ){
+ file = info.dirPath(true ) + "/" + info.readLink() ;
+ break;
+ }else if( i == 4){ // couldn't resolve symlink add it as symlink
+ addSymlink( fi );
+ }
+ } // off for loop for symlink resolving
+ }else if( fi->isDir() )
+ addDir( fi );
+ else if( fi->isFile() )
+ addFile( fi );
+
+ ++it;
+ } // of while loop
+ m_view->sort();
+
+}
+int OFileViewFileListView::fileCount()const{
+ return m_view->childCount();
+}
+QString OFileViewFileListView::currentDir()const{
+ return m_currentDir;
+}
+OFileSelector* OFileViewFileListView::selector() {
+ return m_sel;
+}
+
+bool OFileViewFileListView::eventFilter (QObject *o, QEvent *e) {
+ if ( e->type() == QEvent::KeyPress ) {
+ QKeyEvent *k = (QKeyEvent *)e;
+ if ( (k->key()==Key_Enter) || (k->key()==Key_Return)) {
+ slotClicked( Qt::LeftButton,m_view->currentItem(),QPoint(0,0),0);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void OFileViewFileListView::connectSlots() {
+ connect(m_view, SIGNAL(clicked(QListViewItem*) ),
+ this, SLOT(slotCurrentChanged(QListViewItem*) ) );
+ connect(m_view, SIGNAL(mouseButtonClicked(int,QListViewItem*,const QPoint&,int) ),
+ this, SLOT(slotClicked(int,QListViewItem*,const QPoint&,int) ) );
+}
+void OFileViewFileListView::slotCurrentChanged( QListViewItem* item) {
+ if (!item)
+ return;
+#if 0
+
+ OFileSelectorItem *sel = static_cast<OFileSelectorItem*>(item);
+
+ if (!sel->isDir() ) {
+ selector()->m_lneEdit->setText( sel->text(1) );
+ // if in fileselector mode we will emit selected
+ if ( selector()->mode() == OFileSelector::FileSelector ) {
+ qWarning("slot Current Changed");
+ QStringList str = QStringList::split("->", sel->text(1) );
+ QString path = sel->directory() + "/" + str[0].stripWhiteSpace();
+ emit selector()->fileSelected( path );
+ DocLnk lnk( path );
+ emit selector()->fileSelected( lnk );
+ }
+ }
+#endif
+}
+void OFileViewFileListView::slotClicked(int button , QListViewItem* item, const QPoint&, int ) {
+ if (!item || ( button != Qt::LeftButton) )
+ return;
+
+ OFileSelectorItem *sel = static_cast<OFileSelectorItem*>(item);
+ if (!sel->isLocked() ) {
+ QStringList str = QStringList::split("->", sel->text(1) );
+ if (sel->isDir() ) {
+ m_currentDir = sel->directory() + "/" + str[0].stripWhiteSpace();
+ emit selector()->dirSelected( m_currentDir );
+ reread( m_all );
+ }else { // file
+ qWarning("slot Clicked");
+ selector()->m_lneEdit->setText( str[0].stripWhiteSpace() );
+ QString path = sel->directory() + "/" + str[0].stripWhiteSpace();
+ emit selector()->fileSelected( path );
+ DocLnk lnk( path );
+ emit selector()->fileSelected( lnk );
+ }
+ } // not locked
+}
+void OFileViewFileListView::addFile( QFileInfo* info, bool symlink ) {
+ MimeType type( info->absFilePath() );
+ if (!compliesMime( type.id() ) )
+ return;
+
+ QPixmap pix = type.pixmap();
+ QString dir, name; bool locked;
+ if ( pix.isNull() ) {
+ QWMatrix matrix;
+ QPixmap pixer(Resource::loadPixmap("UnknownDocument") );
+ matrix.scale( .4, .4 );
+ pix = pixer.xForm( matrix );
+ }
+ dir = info->dirPath( true );
+ locked = false;
+ if ( symlink )
+ name = info->fileName() + " -> " + info->dirPath() + "/" + info->readLink();
+ else{
+ name = info->fileName();
+ if ( ( (selector()->mode() == OFileSelector::Open)&& !info->isReadable() ) ||
+ ( (selector()->mode() == OFileSelector::Save)&& !info->isWritable() ) ) {
+ locked = true; pix = Resource::loadPixmap("locked");
+ }
+ }
+ (void)new OFileSelectorItem( m_view, pix, name,
+ info->lastModified().toString(), QString::number( info->size() ),
+ dir, locked );
+}
+void OFileViewFileListView::addDir( QFileInfo* info, bool symlink ) {
+ bool locked = false; QString name; QPixmap pix;
+
+ if ( ( ( selector()->mode() == OFileSelector::Open ) && !info->isReadable() ) ||
+ ( ( selector()->mode() == OFileSelector::Save ) && !info->isWritable() ) ) {
+ locked = true;
+ if ( symlink )
+ pix = Resource::loadPixmap( "opie/symlink" );
+ else
+ pix = Resource::loadPixmap( "lockedfolder" );
+ }else
+ pix = symlink ? Resource::loadPixmap( "opie/symlink") : Resource::loadPixmap("folder");
+
+ name = symlink ? info->fileName() + " -> " + info->dirPath(true) + "/" + info->readLink() :
+ info->fileName();
+
+ (void)new OFileSelectorItem( m_view, pix, name,
+ info->lastModified().toString(),
+ QString::number( info->size() ),
+ info->dirPath( true ), locked, true );
+
+
+}
+void OFileViewFileListView::addSymlink( QFileInfo* , bool ) {
+
+}
+void OFileViewFileListView::cdUP() {
+ QDir dir( m_currentDir );
+ dir.cdUp();
+
+ if (!dir.exists() )
+ m_currentDir = "/";
+ else
+ m_currentDir = dir.absPath();
+
+ emit selector()->dirSelected( m_currentDir );
+ reread( m_all );
+}
+void OFileViewFileListView::cdHome() {
+ m_currentDir = QDir::homeDirPath();
+ emit selector()->dirSelected( m_currentDir );
+ reread( m_all );
+}
+void OFileViewFileListView::cdDoc() {
+ m_currentDir = QPEApplication::documentDir();
+ emit selector()->dirSelected( m_currentDir );
+ reread( m_all );
+}
+void OFileViewFileListView::changeDir( const QString& dir ) {
+ m_currentDir = dir;
+ emit selector()->dirSelected( m_currentDir );
+ reread( m_all );
+}
+void OFileViewFileListView::slotFSActivated( int id ) {
+ changeDir ( m_dev[m_fsPop->text(id)] );
+}
+
+/* check if the mimetype in mime
+ * complies with the one which is current
+ */
+/*
+ * We've the mimetype of the file
+ * We need to get the stringlist of the current mimetype
+ *
+ * mime = image@slashjpeg
+ * QStringList = 'image@slash*'
+ * or QStringList = image/jpeg;image/png;application/x-ogg
+ * or QStringList = application/x-ogg;image@slash*;
+ * with all these mime filters it should get acceptes
+ * to do so we need to look if mime is contained inside
+ * the stringlist
+ * if it's contained return true
+ * if not ( I'm no RegExp expert at all ) we'll look if a '@slash*'
+ * is contained in the mimefilter and then we will
+ * look if both are equal until the '/'
+ */
+bool OFileViewFileListView::compliesMime( const QString& str) {
+ if (str.isEmpty() || m_mimes.isEmpty() || str.stripWhiteSpace().isEmpty() )
+ return true;
+
+ for (QStringList::Iterator it = m_mimes.begin(); it != m_mimes.end(); ++it ) {
+ QRegExp reg( (*it) );
+ reg.setWildcard( true );
+ if ( str.find( reg ) != -1 )
+ return true;
+
+ }
+ return false;
+}
+/*
+ * The listView giving access to the file system!
+ */
+class OFileViewFileSystem : public OFileViewInterface {
+public:
+ OFileViewFileSystem( OFileSelector* );
+ ~OFileViewFileSystem();
+
+ QString selectedName() const;
+ QString selectedPath() const;
+
+ QString directory()const;
+ void reread();
+ int fileCount()const;
+
+ QWidget* widget( QWidget* parent );
+ void activate( const QString& );
+private:
+ OFileViewFileListView* m_view;
+ bool m_all : 1;
+};
+OFileViewFileSystem::OFileViewFileSystem( OFileSelector* sel)
+ : OFileViewInterface( sel ) {
+ m_view = 0;
+ m_all = false;
+}
+OFileViewFileSystem::~OFileViewFileSystem() {
+}
+QString OFileViewFileSystem::selectedName()const{
+ if (!m_view )
+ return QString::null;
+
+ QString cFN=currentFileName();
+ if (cFN.startsWith("/")) return cFN;
+ return m_view->currentDir() + "/" + cFN;
+}
+QString OFileViewFileSystem::selectedPath()const{
+ return QString::null;
+}
+QString OFileViewFileSystem::directory()const{
+ if (!m_view)
+ return QString::null;
+
+ OFileSelectorItem* item = m_view->currentItem();
+ if (!item )
+ return QString::null;
+
+ return QDir(item->directory() ).absPath();
+}
+void OFileViewFileSystem::reread() {
+ if (!m_view)
+ return;
+
+ m_view->reread( m_all );
+}
+int OFileViewFileSystem::fileCount()const{
+ if (!m_view )
+ return -1;
+ return m_view->fileCount();
+}
+QWidget* OFileViewFileSystem::widget( QWidget* parent ) {
+ if (!m_view ) {
+ m_view = new OFileViewFileListView( parent, startDirectory(), selector() );
+ }
+ return m_view;
+}
+void OFileViewFileSystem::activate( const QString& str) {
+ m_all = (str != QObject::tr("Files") );
+
+
+}
+
+/* Selector */
+/**
+ * @short new and complete c'tor
+ *
+ * Create a OFileSelector to let the user select a file. It can
+ * either be used to open a file, select a save name in a dir or
+ * as a dropin for the FileSelector.
+ *
+ * <pre>
+ * QMap<QString, QStringList> mimeTypes;
+ * QStringList types;
+ * types << "text@slash* ";
+ * types << "audio@slash*";
+ * mimeTypes.insert( tr("Audio and Text"), types );
+ * mimeTypes.insert( tr("All"), "*@slash*);
+ *
+ * now you could create your fileselector
+ * </pre>
+ *
+ *
+ * @param parent the parent of this widget
+ * @param mode The mode from the enum Mode (Open,Save,FILESELECTOR)
+ * @param sel The selector to be used
+ * @param dirName The name of the dir to start int
+ * @param fileName The fileName placed in the fileselector lineedit
+ * @param mimetypes The MimeType map of used mimetypes
+ * @param showNew Show a New Button. Most likely to be used in the FileSelector view.
+ * @param showClose Show a Close Button. Most likely to be used in FileSelector view.
+ *
+ */
+OFileSelector::OFileSelector( QWidget* parent, int mode, int sel,
+ const QString& dirName, const QString& fileName,
+ const MimeTypes& mimetypes,
+ bool showNew, bool showClose)
+ : QWidget( parent, "OFileSelector" )
+{
+ m_current = 0;
+ m_shNew = showNew;
+ m_shClose = showClose;
+ m_mimeType = mimetypes;
+ m_startDir = dirName;
+
+ m_mode = mode;
+ m_selector = sel;
+
+ initUI();
+ m_lneEdit->setText( fileName );
+ initMime();
+ initViews();
+
+ QString str;
+ switch ( m_selector ) {
+ default:
+ case Normal:
+ str = QObject::tr("Documents");
+ m_cmbView->setCurrentItem( 0 );
+ break;
+ case Extended:
+ str = QObject::tr("Files");
+ m_cmbView->setCurrentItem( 1 );
+ break;
+ case ExtendedAll:
+ str = QObject::tr("All Files");
+ m_cmbView->setCurrentItem( 2 );
+ break;
+ }
+ slotViewChange( str );
+
+}
+
+/**
+ * This a convience c'tor to just substitute the use of FileSelector
+ */
+OFileSelector::OFileSelector( const QString& mimeFilter, QWidget* parent, const char* name,
+ bool showNew, bool showClose )
+ : QWidget( parent, name )
+{
+ m_current = 0;
+ m_shNew = showNew;
+ m_shClose = showClose;
+ m_startDir = QPEApplication::documentDir();
+
+ if (!mimeFilter.isEmpty() )
+ m_mimeType.insert(mimeFilter, QStringList::split(";", mimeFilter ) );
+
+ m_mode = OFileSelector::FileSelector;
+ m_selector = OFileSelector::Normal;
+
+ initUI();
+ initMime();
+ initViews();
+ m_cmbView->setCurrentItem( 0 );
+ slotViewChange( QObject::tr("Documents") );
+}
+/*
+ * INIT UI will set up the basic GUI
+ * Layout: Simple VBoxLayout
+ * On top a WidgetStack containing the Views...
+ * - List View
+ * - Document View
+ * Below we will have a Label + LineEdit
+ * Below we will have two ComoBoxes one for choosing the view one for
+ * choosing the mimetype
+ */
+void OFileSelector::initUI() {
+ QVBoxLayout* lay = new QVBoxLayout( this );
+
+ m_stack = new QWidgetStack( this );
+ lay->addWidget( m_stack, 1000 );
+
+ m_nameBox = new QHBox( this );
+ (void)new QLabel( tr("Name:"), m_nameBox );
+ m_lneEdit = new QLineEdit( m_nameBox );
+ m_lneEdit ->installEventFilter(this);
+ lay->addWidget( m_nameBox );
+
+ m_cmbBox = new QHBox( this );
+ m_cmbView = new QComboBox( m_cmbBox );
+ m_cmbMime = new QComboBox( m_cmbBox );
+ lay->addWidget( m_cmbBox );
+}
+
+/*
+ * This will make sure that the return key in the name edit causes dialogs to close
+ */
+
+bool OFileSelector::eventFilter (QObject *o, QEvent *e) {
+ if ( e->type() == QEvent::KeyPress ) {
+ QKeyEvent *k = (QKeyEvent *)e;
+ if ( (k->key()==Key_Enter) || (k->key()==Key_Return)) {
+ emit ok();
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ * This will insert the MimeTypes into the Combo Box
+ * And also connect the changed signal
+ *
+ * AutoMimeTyping is disabled for now. It used to reparse a dir and then set available mimetypes
+ */
+void OFileSelector::initMime() {
+ MimeTypes::Iterator it;
+ for ( it = m_mimeType.begin(); it != m_mimeType.end(); ++it ) {
+ m_cmbMime->insertItem( it.key() );
+ }
+ m_cmbMime->setCurrentItem( 0 );
+
+ connect( m_cmbMime, SIGNAL(activated(int) ),
+ this, SLOT(slotMimeTypeChanged() ) );
+
+}
+void OFileSelector::initViews() {
+ m_cmbView->insertItem( QObject::tr("Documents") );
+ m_cmbView->insertItem( QObject::tr("Files") );
+ m_cmbView->insertItem( QObject::tr("All Files") );
+ connect(m_cmbView, SIGNAL(activated(const QString&) ),
+ this, SLOT(slotViewChange(const QString&) ) );
+
+
+ m_views.insert( QObject::tr("Documents"), new ODocumentFileView(this) );
+
+ /* see above why add both */
+ OFileViewInterface* in = new OFileViewFileSystem( this );
+ m_views.insert( QObject::tr("Files"), in );
+ m_views.insert( QObject::tr("All Files"), in );
+}
+
+/**
+ * d'tor
+ */
+OFileSelector::~OFileSelector() {
+
+}
+
+/**
+ * Convience function for the fileselector
+ * make sure to delete the DocLnk
+ *
+ * @see DocLnk
+ * @todo remove in ODP
+ */
+const DocLnk* OFileSelector::selected() {
+ DocLnk* lnk = new DocLnk( currentView()->selectedDocument() );
+ return lnk;
+}
+
+/**
+ *
+ * @return the name of the selected file
+ */
+QString OFileSelector::selectedName()const{
+ return currentView()->selectedName();
+}
+
+/**
+ * @return the selected path
+ */
+QString OFileSelector::selectedPath()const {
+ return currentView()->selectedPath();
+}
+
+/**
+ * @return the directory name
+ */
+QString OFileSelector::directory()const {
+ return currentView()->directory();
+}
+
+/**
+ * @return a DocLnk for the selected document
+ */
+DocLnk OFileSelector::selectedDocument()const {
+ return currentView()->selectedDocument();
+}
+
+/**
+ * @return the number of items for the current view
+ */
+int OFileSelector::fileCount()const {
+ return currentView()->fileCount();
+}
+
+/**
+ * @return reparse the file content
+ */
+void OFileSelector::reread() {
+ return currentView()->reread();
+}
+OFileViewInterface* OFileSelector::currentView()const{
+ return m_current;
+}
+bool OFileSelector::showNew()const {
+ return m_shNew;
+}
+bool OFileSelector::showClose()const {
+ return m_shClose;
+}
+MimeTypes OFileSelector::mimeTypes()const {
+ return m_mimeType;
+}
+
+/**
+ * @return the Mode of the OFileSelector
+ */
+int OFileSelector::mode()const{
+ return m_mode;
+}
+
+/**
+ * @return the Selector of the OFileSelector
+ */
+int OFileSelector::selector()const{
+ return m_selector;
+}
+QStringList OFileSelector::currentMimeType()const {
+ return m_mimeType[m_cmbMime->currentText()];
+}
+void OFileSelector::slotMimeTypeChanged() {
+ reread();
+}
+void OFileSelector::slotDocLnkBridge( const DocLnk& lnk) {
+ m_lneEdit->setText( lnk.name() );
+ emit fileSelected( lnk );
+ emit fileSelected( lnk.name() );
+}
+void OFileSelector::slotFileBridge( const QString& str) {
+ DocLnk lnk( str );
+ emit fileSelected( lnk );
+}
+void OFileSelector::slotViewChange( const QString& view ) {
+ OFileViewInterface* interface = m_views[view];
+ if (!interface)
+ return;
+
+ interface->activate( view );
+ if (m_current)
+ m_stack->removeWidget( m_current->widget( m_stack ) );
+
+ static int id = 1;
+
+ m_stack->addWidget( interface->widget(m_stack), id );
+ m_stack->raiseWidget( id );
+
+ interface->reread();
+ m_current = interface;
+
+ id++;
+}
+void OFileSelector::setNewVisible( bool b ) {
+ m_shNew = b;
+ currentView()->reread();
+}
+void OFileSelector::setCloseVisible( bool b ) {
+ m_shClose = b;
+ currentView()->reread();
+}
+void OFileSelector::setNameVisible( bool b ) {
+ if ( b )
+ m_nameBox->show();
+ else
+ m_nameBox->hide();
+}
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 @@
+/*
+ This is based on code and ideas of
+ L. J. Potter ljp@llornkcor.com
+ Thanks a lot
+
+
+               =. This file is part of the OPIE Project
+             .=l. Copyright (c) 2002,2003 Holger Freyther <zecke@handhelds.org>
+           .>+-=
+ _;:,     .>    :=|. This library is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This library is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+
+#ifndef OPIE_OFILESELECTOR_FOO_H
+#define OPIE_OFILESELECTOR_FOO_H
+
+#include <qlist.h>
+#include <qwidget.h>
+#include <qmap.h>
+#include <qvaluelist.h>
+#include <qstringlist.h>
+
+#include <qpe/applnk.h>
+
+typedef QMap<QString, QStringList> MimeTypes;
+
+class OFileViewInterface;
+class OFileViewFileListView;
+class QLineEdit;
+class QComboBox;
+class QWidgetStack;
+class QHBox;
+
+
+/**
+ * @short a dropin replacement for the FileSelector
+ *
+ * This class is first used insert the OFileDialog.
+ * It supports multiple view and mimetype filtering for now.
+ *
+ * @see OFileDialog
+ * @see FileSelector
+ * @author zecke
+ * @version 0.1
+ */
+class OFileSelector : public QWidget {
+ Q_OBJECT
+ friend class OFileViewInterface;
+ friend class OFileViewFileListView;
+public:
+ /**
+ * The Mode of the Fileselector
+ * Open = Open A File
+ * Save = Save a File
+ * FILESELECTOR = As A GUI in a screen to select a file
+ */
+ enum Mode { Open=1, Save=2, FileSelector=4, OPEN=1, SAVE=2, FILESELECTOR=4 };
+// enum OldMode { OPEN=1, SAVE=2, FILESELECTOR = 4 };
+ /**
+ * Normal = The old FileSelector
+ * Extended = Dir View
+ * ExtendedAll = Dir View with all hidden files
+ * Default = What the vendor considers best
+ */
+ enum Selector { Normal = 0, Extended=1, ExtendedAll =2, Default=3, NORMAL=0,EXTENDED=1, EXTENDED_ALL =2, DEFAULT=3 };
+// enum OldSelector { NORMAL = 0, EXTENDED =1, EXTENDED_ALL = 2};
+
+
+ OFileSelector(QWidget* parent, int mode, int selector,
+ const QString& dirName,
+ const QString& fileName,
+ const MimeTypes& mimetypes = MimeTypes(),
+ bool newVisible = FALSE, bool closeVisible = FALSE );
+
+ OFileSelector(const QString& mimeFilter, QWidget* parent,
+ const char* name = 0, bool newVisible = TRUE, bool closeVisible = FALSE );
+ ~OFileSelector();
+
+ const DocLnk* selected();
+
+ QString selectedName()const;
+ QString selectedPath()const;
+ QString directory()const;
+
+ DocLnk selectedDocument()const;
+
+ int fileCount()const;
+ void reread();
+
+ int mode()const;
+ int selector()const;
+
+ /**
+ * Set the Icon visible
+ * @param b Show or Hide the New Button
+ */
+ void setNewVisible( bool b );
+
+ /**
+ * Set the Icon visible
+ */
+ void setCloseVisible( bool b );
+
+ /**
+ * Set the Name Line visible
+ */
+ void setNameVisible( bool b );
+
+signals:
+ /**
+ * dirSelected is emitted whenever changed into a different dir
+ */
+ void dirSelected( const QString& );
+
+ /**
+ * fileSelected is emitted when a file is selected
+ * it uses a DocLnk as parameter
+ */
+ void fileSelected( const DocLnk& );
+
+ /**
+ * fileSelected is emitted when a file is selected
+ * the complete path is a parameter
+ */
+ void fileSelected( const QString& );
+
+ /**
+ * Create a new File with a DocLnk
+ */
+ void newSelected( const DocLnk& );
+
+ void closeMe();
+
+ /**
+ * Ok is emitted on a Qt::Key_Return or Q::Key_Enter
+ * in the line edit
+ */
+ void ok();
+ void cancel();
+
+/* used by the ViewInterface */
+private:
+ bool showNew()const;
+ bool showClose()const;
+ MimeTypes mimeTypes()const;
+ QStringList currentMimeType()const;
+
+private:
+ /* inits the Widgets */
+ void initUI();
+ /* inits the MimeType ComboBox content + connects signals and slots */
+ void initMime();
+ /* init the Views :) */
+ void initViews();
+
+private:
+ QLineEdit* m_lneEdit; // the LineEdit for the Name
+ QComboBox *m_cmbView, *m_cmbMime; // two ComboBoxes to select the View and MimeType
+ QWidgetStack* m_stack; // our widget stack which will contain the views
+ OFileViewInterface* currentView()const; // returns the currentView
+ OFileViewInterface* m_current; // here is the view saved
+ bool m_shNew : 1; // should we show New?
+ bool m_shClose : 1; // should we show Close?
+ MimeTypes m_mimeType; // list of mimetypes
+
+ QMap<QString, OFileViewInterface*> m_views; // QString translated view name + ViewInterface Ptr
+ QHBox* m_nameBox; // the LineEdit + Label is hold here
+ QHBox* m_cmbBox; // this holds the two combo boxes
+
+ QString m_startDir;
+ int m_mode;
+ int m_selector;
+
+ struct Data; // used for future versions
+ Data *d;
+
+private slots:
+ void slotMimeTypeChanged();
+
+ /* will set the text of the lineedit and emit a fileChanged signal */
+ void slotDocLnkBridge( const DocLnk& );
+ void slotFileBridge( const QString& );
+ void slotViewChange( const QString& );
+
+ bool eventFilter (QObject *o, QEvent *e);
+
+};
+
+#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 @@
+#ifndef OPIE_OFILE_SELECTOR_PRIVATE_H
+#define OPIE_OFILE_SELECTOR_PRIVATE_H
+
+#include <qmap.h>
+#include <qstringlist.h>
+#include <qwidget.h>
+#include <qlistview.h>
+
+#include <qpe/applnk.h>
+#include <qpe/fileselector.h>
+
+
+/*
+ * How to avoid having really two different objects
+ * for Extended and ExtendedAll
+ * The only difference is the Lister...
+ * a) static object?
+ * b) leave some object inside the OFileSelector which can be used?
+ * c) when switching views tell which view we want o have.. internally we can switch then
+ *
+ * I'll take c) -zecke
+ */
+
+
+/* the View Interface */
+class OFileSelector;
+typedef QMap<QString, QStringList> MimeTypes;
+class QFileInfo;
+class QToolButton;
+class OFileViewInterface {
+public:
+ OFileViewInterface( OFileSelector* selector );
+ virtual ~OFileViewInterface();
+ virtual QString selectedName()const = 0;
+ virtual QString selectedPath()const = 0;
+ virtual QString directory()const = 0;
+ virtual void reread() = 0;
+ virtual int fileCount()const = 0;
+ virtual DocLnk selectedDocument()const;
+ virtual QWidget* widget( QWidget* parent) = 0;
+ virtual void activate( const QString& );
+ QString name()const;
+protected:
+ OFileSelector* selector()const;
+ void setName( const QString& );
+ bool showNew()const;
+ bool showClose()const;
+ MimeTypes mimeTypes()const;
+ QStringList currentMimeType()const;
+ QString startDirectory()const;
+protected:
+ void ok();
+ void cancel();
+ void closeMe();
+ void fileSelected( const QString& );
+ void fileSelected( const DocLnk& );
+ void setCurrentFileName( const QString& );
+ QString currentFileName()const;
+
+private:
+ QString m_name;
+ OFileSelector* m_selector;
+};
+
+
+/* THE Document View hosting a FileSelector*/
+class ODocumentFileView : public OFileViewInterface {
+public:
+ ODocumentFileView( OFileSelector* selector );
+ ~ODocumentFileView();
+
+ QString selectedName() const;
+ QString selectedPath() const;
+
+ QString directory() const;
+ void reread();
+ int fileCount()const;
+ DocLnk selectedDocument()const;
+
+ QWidget* widget( QWidget* parent );
+
+private:
+ mutable FileSelector* m_selector;
+
+};
+
+class OFileSelectorItem : public QListViewItem {
+public:
+ OFileSelectorItem( QListView* view, const QPixmap& pixmap,
+ const QString& path, const QString& date,
+ const QString& size, const QString& mDir,
+ bool isLocked = false, bool isDir = false );
+ ~OFileSelectorItem();
+ bool isLocked()const;
+ bool isDir()const;
+ QString directory()const;
+ QString path()const;
+ QString key(int id, bool )const;
+
+private:
+ bool m_locked : 1;
+ bool m_isDir : 1;
+ QString m_dir;
+};
+
+class OFileViewFileListView : public QWidget {
+ Q_OBJECT
+public:
+ OFileViewFileListView( QWidget* parent, const QString& dir, OFileSelector* selector );
+ ~OFileViewFileListView();
+
+ OFileSelectorItem* currentItem()const;
+ void reread( bool all = false );
+ int fileCount()const;
+ QString currentDir()const;
+protected:
+ bool eventFilter (QObject *o, QEvent *e);
+private slots:
+ void slotNew(); // will emit newSelected
+ void cdUP();
+ void cdHome();
+ void cdDoc();
+ void changeDir( const QString& );
+ void slotCurrentChanged( QListViewItem* );
+ void slotClicked(int, QListViewItem*, const QPoint&, int );
+ void slotFSActivated(int);
+
+protected:
+
+ OFileSelector* selector();
+
+private:
+ QMap<QString, QString> m_dev;
+ bool m_all : 1;
+ OFileSelector* m_sel;
+ QPopupMenu* m_fsPop;
+ bool compliesMime( const QString& );
+ QStringList m_mimes; // used in compy mime
+ QString m_currentDir;
+ QToolButton *m_btnNew, *m_btnClose;
+ void connectSlots();
+ void addFile( QFileInfo* info, bool symlink = FALSE );
+ void addDir ( QFileInfo* info, bool symlink = FALSE );
+ void addSymlink( QFileInfo* info, bool = FALSE );
+
+
+private:
+ QListView* m_view;
+};
+
+#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 @@
+/*
+               =. This file is part of the OPIE Project
+             .=l. Copyright (c) 2002 zecke <zecke@handhelds.org>
+           .>+-=
+ _;:,     .>    :=|. This library is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This library is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef ofileview_h
+#define ofileview_h
+
+#include <qobject.h>
+#include <qwidget.h>
+
+class QFileInfo;
+class QDir;
+class DocLnk;
+
+/**
+ * A OFileView is a specialised View for the
+ * OFileSelector
+ * With a View you can chage the user visible
+ * representation of a OFileLister
+ * OFileView is just a basic interface which helps you to
+ * write new views
+ */
+class OFileView {
+ Q_OBJECT
+ public:
+ OFileView(QWidget *widget,
+ const char *name );
+ virtual OFileView();
+ virtual ~OFileSelectorView() = 0;
+
+ virtual void addFile(const QString &mine,
+ QFileInfo *info,
+ bool isSymlink = FALSE ) = 0;
+
+ virtual void addDir (const QString &mine,
+ QFileInfo *info,
+ bool isSymlink = FALSE ) = 0;
+
+ virtual void addSymlink(const QString &mime,
+ QFileInfo *info,
+ bool isSymlink = FALSE ) = 0;
+
+ virtual void cd(const QString &path ) = 0;
+ signals:
+ void fileSelected(const QString &);
+ void fileSelected(const DocLnk & );
+ void contextMenu();
+ void changedDir(const QString &);
+ void changedDir(const QDir & );
+};
+
+class OFileViewFactory {
+ // Q_OBJECT
+ public:
+ OFileViewFactory() {} ;
+ virtual ~OFileViewFactory() = 0;
+
+ OFileSelectorView* newView(QWidget *parent, const char *name );
+ QString name()const;
+};
+
+
+#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 @@
+
+
+#include <qpe/config.h>
+#include "ofontmenu.h"
+
+
+/**
+ * Constructs the FontMenu.
+ *
+ * @param parent The parent widget
+ * @param name A name for this widget
+ * @param list The list of widgets to be controlled
+ */
+OFontMenu::OFontMenu(QWidget *parent, const char *name, const QList<QWidget> &list )
+ : QPopupMenu( parent, name )
+{
+ m_list = list;
+ m_wids.setAutoDelete( TRUE );
+
+ insertItem(tr("Large"), this, SLOT(slotLarge() ),
+ 0, 10);
+ insertItem(tr("Medium"), this, SLOT(slotMedium() ),
+ 0, 11 );
+ insertItem(tr("Small"), this, SLOT(slotSmall() ),
+ 0, 12 );
+ setCheckable( true );
+ m_size=10;
+}
+
+/**
+ * This method saves the font size
+ * into a Config object
+ * OFontMenu will be used as group and size as key
+ * @param cfg The Config object to be used
+ */
+void OFontMenu::save(Config *cfg )
+{
+ cfg->setGroup("OFontMenu" );
+ cfg->writeEntry("size", m_size );
+}
+
+/**
+ * This method restores the font size from a Config object
+ * it'll apply the sizes to the widgets and will also set the
+ * menu appropriate
+ */
+void OFontMenu::restore(Config *cfg )
+{
+ cfg->setGroup("OFontMeny" );
+ m_size = cfg->readNumEntry("size" );
+ setItemChecked(10, false );
+ setItemChecked(11, false );
+ setItemChecked(12, false );
+ switch( m_size ){
+ case 8:
+ setItemChecked(12, true );
+ break;
+ case 14:
+ setItemChecked(10, true );
+ break;
+ case 10:// fall through
+ default:
+ setItemChecked(11, true );
+ m_size = 10;
+ break;
+ }
+ setFontSize( m_size );
+}
+
+/**
+ * set the list of widgets
+ * @param list the widget list
+ */
+void OFontMenu::setWidgets(const QList<QWidget> &list )
+{
+ m_list = list;
+}
+
+/**
+ * add a widget to the list
+ * @param wid The widget to be added
+ */
+void OFontMenu::addWidget( QWidget *wid )
+{
+ m_list.append(wid );
+}
+
+/**
+ * removes the widget from the list of controlled objects
+ * @param wid the to be removed widget
+ */
+void OFontMenu::removeWidget( QWidget *wid )
+{
+ m_list.remove( wid );
+}
+
+/**
+ * The list of controlled widgets
+ */
+const QList<QWidget> &OFontMenu::widgets()const
+{
+ return m_list;
+}
+
+/**
+ * Forces a size on a widget
+ * @param wid The widget
+ * @param size The font size forced onto the widget
+ */
+void OFontMenu::forceSize(QWidget *wid, int size )
+{
+ WidSize *widz = new WidSize;
+ widz->wid = wid;
+ widz->size = size;
+ m_wids.append( widz );
+}
+void OFontMenu::slotSmall()
+{
+ setItemChecked(10, false );
+ setItemChecked(11, false );
+ setItemChecked(12, true );
+ setFontSize( 8 );
+}
+void OFontMenu::slotMedium()
+{
+ setItemChecked(10, false );
+ setItemChecked(11, true );
+ setItemChecked(12, false );
+ setFontSize(10 );
+}
+void OFontMenu::slotLarge()
+{
+ setItemChecked(10, true );
+ setItemChecked(11, false );
+ setItemChecked(12, false );
+ setFontSize(14 );
+}
+void OFontMenu::setFontSize(int size )
+{
+ m_size = size;
+ QWidget *wid;
+ for(wid = m_list.first(); wid !=0; wid = m_list.next() ){
+ QFont font = wid->font();
+ font.setPointSize( size );
+ wid->setFont( font );
+ }
+ if(!m_wids.isEmpty() ){
+ WidSize *wids;
+ for( wids = m_wids.first(); wids != 0; wids = m_wids.next() ){
+ QFont font = wids->wid->font();
+ font.setPointSize( wids->size );
+ wids->wid->setFont( font );
+ }
+ }
+ emit fontChanged(size );
+}
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 @@
+
+/*
+
+               =. This file is part of the OPIE Project
+             .=l. Copyright (c) 2002 zecke <zecke@handhelds.org>
+           .>+-=
+ _;:,     .>    :=|. This library is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This library is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+
+
+
+#ifndef ofontmenu_h
+#define ofontmenu_h
+
+#include <qpopupmenu.h>
+#include <qlist.h>
+
+/*
+ * @internal
+ */
+namespace {
+ struct WidSize {
+ QWidget *wid;
+ int size;
+ };
+
+};
+
+// forward declarations
+class Config;
+
+/**
+ * This class is a specialised QPopupMenu. It'll display three different
+ * font sizes. Small, Normal and large by adding widgets to the Menu
+ * you can control the font size of these widgets
+ * by using the save and restore method you can also apply font sizes
+ * over two different runtimes
+ *
+ * <pre>
+ * QTable* tbl = new QTable();
+ * QList<QWidget> wid;
+ * wid.append( tbl );
+ * OFontMenu* menu = new OFontMenu(this, "Popup Menu", wid );
+ * Config cfg("mycfg");
+ * menu->restore( cfg );
+ * </pre>
+ *
+ * @author Holger Freyther ( zecke@handhelds.org )
+ * @version 0.1
+ * @short PopupMenu which can control the size of Widgets
+ * @see QPopupMenu
+ */
+class OFontMenu : public QPopupMenu {
+ Q_OBJECT
+ public:
+ OFontMenu(QWidget *parent, const char* name, const QList<QWidget> &list );
+ void save(Config *cfg );
+ void restore(Config *cfg );
+ void setWidgets(const QList<QWidget> &list );
+ void addWidget(QWidget *wid );
+ void forceSize(QWidget *wid, int size );
+ void removeWidget(QWidget *wid );
+ const QList<QWidget> &widgets()const;
+
+ signals:
+ /**
+ * this signal gets emitted when the font size gets changed
+ * @param size The new size of font
+ */
+ void fontChanged(int size );
+
+ private:
+ QList<QWidget> m_list;
+ QList<WidSize> m_wids;
+ int m_size;
+ class OFontMenuPrivate;
+ OFontMenuPrivate *d;
+
+ private slots:
+ virtual void slotSmall();
+ virtual void slotMedium();
+ virtual void slotLarge();
+ void setFontSize(int size );
+};
+
+#endif
+
+
+
+
+
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 @@
+/*
+               =. This file is part of the OPIE Project
+             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
+           .>+-=
+ _;:,     .>    :=|. This library is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This library is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include <qlayout.h>
+#include <qlistbox.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qmultilineedit.h>
+
+#include <qpe/fontdatabase.h>
+
+#include "ofontselector.h"
+
+class OFontSelectorPrivate {
+public:
+ QListBox * m_font_family_list;
+ QComboBox * m_font_style_list;
+ QComboBox * m_font_size_list;
+ QMultiLineEdit *m_preview;
+
+ bool m_pointbug : 1;
+
+ FontDatabase m_fdb;
+};
+
+namespace {
+
+class FontListItem : public QListBoxText {
+public:
+ FontListItem ( const QString &t, const QStringList &styles, const QValueList<int> &sizes ) : QListBoxText ( )
+ {
+ m_name = t;
+ m_styles = styles;
+ m_sizes = sizes;
+
+ QString str = t;
+ str [0] = str [0]. upper ( );
+ setText ( str );
+ }
+
+ QString family ( ) const
+ {
+ return m_name;
+ }
+
+ const QStringList &styles ( ) const
+ {
+ return m_styles;
+ }
+
+ const QValueList<int> &sizes ( ) const
+ {
+ return m_sizes;
+ }
+
+private:
+ QStringList m_styles;
+ QValueList<int> m_sizes;
+ QString m_name;
+};
+
+
+static int findItemCB ( QComboBox *box, const QString &str )
+{
+ for ( int i = 0; i < box-> count ( ); i++ ) {
+ if ( box-> text ( i ) == str )
+ return i;
+ }
+ return -1;
+}
+
+}
+/* static same as anon. namespace */
+static int qt_version ( )
+{
+ const char *qver = qVersion ( );
+
+ return ( qver [0] - '0' ) * 100 + ( qver [2] - '0' ) * 10 + ( qver [4] - '0' );
+}
+
+/**
+ * Constructs the Selector object
+ * @param withpreview If a font preview should be given
+ * @param parent The parent of the Font Selector
+ * @param name The name of the object
+ * @param fl WidgetFlags
+ */
+OFontSelector::OFontSelector ( bool withpreview, QWidget *parent, const char *name, WFlags fl ) : QWidget ( parent, name, fl )
+{
+ d = new OFontSelectorPrivate ( );
+
+ QGridLayout *gridLayout = new QGridLayout ( this, 0, 0, 4, 4 );
+ gridLayout->setRowStretch ( 4, 10 );
+
+ d-> m_font_family_list = new QListBox( this, "FontListBox" );
+ gridLayout->addMultiCellWidget( d-> m_font_family_list, 0, 4, 0, 0 );
+ connect( d-> m_font_family_list, SIGNAL( highlighted(int) ), this, SLOT( fontFamilyClicked(int) ) );
+
+ QLabel *label = new QLabel( tr( "Style" ), this );
+ gridLayout->addWidget( label, 0, 1 );
+
+ d-> m_font_style_list = new QComboBox( this, "StyleListBox" );
+ connect( d-> m_font_style_list, SIGNAL( activated(int) ), this, SLOT( fontStyleClicked(int) ) );
+ gridLayout->addWidget( d-> m_font_style_list, 1, 1 );
+
+ label = new QLabel( tr( "Size" ), this );
+ gridLayout->addWidget( label, 2, 1 );
+
+ d-> m_font_size_list = new QComboBox( this, "SizeListBox" );
+ connect( d-> m_font_size_list, SIGNAL( activated(int) ),
+ this, SLOT( fontSizeClicked(int) ) );
+ gridLayout->addWidget( d-> m_font_size_list, 3, 1 );
+
+ d-> m_pointbug = ( qt_version ( ) <= 233 );
+
+ if ( withpreview ) {
+ d-> m_preview = new QMultiLineEdit ( this, "Preview" );
+ d-> m_preview-> setAlignment ( AlignCenter );
+ d-> m_preview-> setWordWrap ( QMultiLineEdit::WidgetWidth );
+ d-> m_preview-> setMargin ( 3 );
+ d-> m_preview-> setText ( tr( "The Quick Brown Fox Jumps Over The Lazy Dog" ));
+ gridLayout-> addRowSpacing ( 5, 4 );
+ gridLayout-> addMultiCellWidget ( d-> m_preview, 6, 6, 0, 1 );
+ gridLayout-> setRowStretch ( 6, 5 );
+ }
+ else
+ d-> m_preview = 0;
+
+ loadFonts ( d-> m_font_family_list );
+}
+
+OFontSelector::~OFontSelector ( )
+{
+ delete d;
+}
+
+/**
+ * This methods tries to set the font
+ * @param f The wishes font
+ * @return success or failure
+ */
+bool OFontSelector::setSelectedFont ( const QFont &f )
+{
+ return setSelectedFont ( f. family ( ), d-> m_fdb. styleString ( f ), f. pointSize ( ), QFont::encodingName ( f. charSet ( )));
+}
+
+
+/**
+ * This is an overloaded method @see setSelectedFont
+ * @param familyStr The family of the font
+ * @param styleStr The style of the font
+ * @param sizeVal The size of font
+ * @param charset The charset to be used. Will be deprecated by QT3
+ */
+bool OFontSelector::setSelectedFont ( const QString &familyStr, const QString &styleStr, int sizeVal, const QString & charset )
+{
+ QString sizeStr = QString::number ( sizeVal );
+
+ QListBoxItem *family = d-> m_font_family_list-> findItem ( familyStr );
+ if ( !family )
+ family = d-> m_font_family_list-> findItem ( "Helvetica" );
+ if ( !family )
+ family = d-> m_font_family_list-> firstItem ( );
+ d-> m_font_family_list-> setCurrentItem ( family );
+ fontFamilyClicked ( d-> m_font_family_list-> index ( family ));
+
+ int style = findItemCB ( d-> m_font_style_list, styleStr );
+ if ( style < 0 )
+ style = findItemCB ( d-> m_font_style_list, "Regular" );
+ if ( style < 0 && d-> m_font_style_list-> count ( ) > 0 )
+ style = 0;
+ d-> m_font_style_list-> setCurrentItem ( style );
+ fontStyleClicked ( style );
+
+ int size = findItemCB ( d-> m_font_size_list, sizeStr );
+ if ( size < 0 )
+ size = findItemCB ( d-> m_font_size_list, "10" );
+ if ( size < 0 && d-> m_font_size_list-> count ( ) > 0 )
+ size = 0;
+ d-> m_font_size_list-> setCurrentItem ( size );
+ fontSizeClicked ( size );
+
+ return (( family ) && ( style >= 0 ) && ( size >= 0 ));
+}
+
+/**
+ * This method returns the name, style and size of the currently selected
+ * font or false if no font is selected
+ * @param family The font family will be written there
+ * @param style The style will be written there
+ * @param size The size will be written there
+ * @return success or failure
+ */
+bool OFontSelector::selectedFont ( QString &family, QString &style, int &size )
+{
+ QString dummy;
+ return selectedFont ( family, style, size, dummy );
+}
+
+
+/**
+ * This method does return the font family or QString::null if there is
+ * no font item selected
+ * @return the font family
+ */
+QString OFontSelector::fontFamily ( ) const
+{
+ FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( ));
+
+ return fli ? fli-> family ( ) : QString::null;
+}
+
+/**
+ * This method will return the style of the font or QString::null
+ * @return the style of the font
+ */
+QString OFontSelector::fontStyle ( ) const
+{
+ FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( ));
+ int fst = d-> m_font_style_list-> currentItem ( );
+
+ return ( fli && fst >= 0 ) ? fli-> styles ( ) [fst] : QString::null;
+}
+
+/**
+ * This method will return the font size or 10 if no font size is available
+ */
+int OFontSelector::fontSize ( ) const
+{
+ FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( ));
+ int fsi = d-> m_font_size_list-> currentItem ( );
+
+ return ( fli && fsi >= 0 ) ? fli-> sizes ( ) [fsi] : 10;
+}
+
+/**
+ * returns the charset of the font or QString::null
+ */
+QString OFontSelector::fontCharSet ( ) const
+{
+ FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( ));
+
+ return fli ? d-> m_fdb. charSets ( fli-> family ( )) [0] : QString::null;
+}
+
+/**
+ * Overloaded member function see above
+ * @see selectedFont
+ */
+bool OFontSelector::selectedFont ( QString &family, QString &style, int &size, QString &charset )
+{
+ int ffa = d-> m_font_family_list-> currentItem ( );
+ int fst = d-> m_font_style_list-> currentItem ( );
+ int fsi = d-> m_font_size_list-> currentItem ( );
+
+ FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( ffa );
+
+ if ( fli ) {
+ family = fli-> family ( );
+ style = fst >= 0 ? fli-> styles ( ) [fst] : QString::null;
+ size = fsi >= 0 ? fli-> sizes ( ) [fsi] : 10;
+ charset = d-> m_fdb. charSets ( fli-> family ( )) [0];
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+void OFontSelector::loadFonts ( QListBox *list )
+{
+ QStringList f = d-> m_fdb. families ( );
+
+ for ( QStringList::ConstIterator it = f. begin ( ); it != f. end ( ); ++it ) {
+ QValueList <int> ps = d-> m_fdb. pointSizes ( *it );
+
+ if ( d-> m_pointbug ) {
+ for ( QValueList <int>::Iterator it = ps. begin ( ); it != ps. end ( ); it++ )
+ *it /= 10;
+ }
+
+ list-> insertItem ( new FontListItem ( *it, d-> m_fdb. styles ( *it ), ps ));
+ }
+}
+
+void OFontSelector::fontFamilyClicked ( int index )
+{
+ QString oldstyle = d-> m_font_style_list-> currentText ( );
+ QString oldsize = d-> m_font_size_list-> currentText ( );
+
+ FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( index );
+
+ d-> m_font_style_list-> clear ( );
+ d-> m_font_style_list-> insertStringList ( fli-> styles ( ));
+ d-> m_font_style_list-> setEnabled ( !fli-> styles ( ). isEmpty ( ));
+
+ int i;
+
+ i = findItemCB ( d-> m_font_style_list, oldstyle );
+ if ( i < 0 )
+ i = findItemCB ( d-> m_font_style_list, "Regular" );
+ if (( i < 0 ) && ( d-> m_font_style_list-> count ( ) > 0 ))
+ i = 0;
+
+ if ( i >= 0 ) {
+ d-> m_font_style_list-> setCurrentItem ( i );
+ fontStyleClicked ( i );
+ }
+
+ d-> m_font_size_list-> clear ( );
+ QValueList<int> sl = fli-> sizes ( );
+
+ for ( QValueList<int>::Iterator it = sl. begin ( ); it != sl. end ( ); ++it )
+ d-> m_font_size_list-> insertItem ( QString::number ( *it ));
+
+ i = findItemCB ( d-> m_font_size_list, oldsize );
+ if ( i < 0 )
+ i = findItemCB ( d-> m_font_size_list, "10" );
+ if (( i < 0 ) && ( d-> m_font_size_list-> count ( ) > 0 ))
+ i = 0;
+
+ if ( i >= 0 ) {
+ d-> m_font_size_list-> setCurrentItem ( i );
+ fontSizeClicked ( i );
+ }
+ changeFont ( );
+}
+
+void OFontSelector::fontStyleClicked ( int /*index*/ )
+{
+ changeFont ( );
+}
+
+void OFontSelector::fontSizeClicked ( int /*index*/ )
+{
+ changeFont ( );
+}
+
+void OFontSelector::changeFont ( )
+{
+ QFont f = selectedFont ( );
+
+ if ( d-> m_preview )
+ d-> m_preview-> setFont ( f );
+
+ emit fontSelected ( f );
+}
+
+/**
+ * Return the selected font
+ */
+QFont OFontSelector::selectedFont ( )
+{
+ int ffa = d-> m_font_family_list-> currentItem ( );
+ int fst = d-> m_font_style_list-> currentItem ( );
+ int fsi = d-> m_font_size_list-> currentItem ( );
+
+ FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( ffa );
+
+ if ( fli ) {
+ return d-> m_fdb. font ( fli-> family ( ), \
+ fst >= 0 ? fli-> styles ( ) [fst] : QString::null, \
+ fsi >= 0 ? fli-> sizes ( ) [fsi] : 10, \
+ d-> m_fdb. charSets ( fli-> family ( )) [0] );
+ }
+ else
+ return QFont ( );
+}
+
+
+void OFontSelector::resizeEvent ( QResizeEvent *re )
+{
+ if ( d-> m_preview ) {
+ d-> m_preview-> setMinimumHeight ( 1 );
+ d-> m_preview-> setMaximumHeight ( 32767 );
+ }
+
+ QWidget::resizeEvent ( re );
+
+ if ( d-> m_preview )
+ d-> m_preview-> setFixedHeight ( d-> m_preview-> height ( ));
+
+}
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 @@
+/*
+               =. This file is part of the OPIE Project
+             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
+           .>+-=
+ _;:,     .>    :=|. This library is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This library is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OPIE_FONTSELECTOR_H__
+#define OPIE_FONTSELECTOR_H__
+
+#include <qwidget.h>
+
+class QListBox;
+class OFontSelectorPrivate;
+
+/**
+ * This class lets you chose a Font out of a list of Fonts.
+ * It can show a preview too. This selector will use all available
+ * fonts
+ *
+ *
+ * @short A widget to select a font
+ * @see QWidget
+ * @see QFont
+ * @author Rober Griebl
+ */
+class OFontSelector : public QWidget
+{
+ Q_OBJECT
+
+public:
+ OFontSelector ( bool withpreview, QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
+ virtual ~OFontSelector ( );
+
+ bool selectedFont ( QString &family, QString &style, int &size );
+ bool selectedFont ( QString &family, QString &style, int &size, QString &charset );
+
+ QFont selectedFont ( );
+
+ bool setSelectedFont ( const QFont & );
+ bool setSelectedFont ( const QString &family, const QString &style, int size, const QString &charset = 0 );
+
+ QString fontFamily ( ) const;
+ QString fontStyle ( ) const;
+ int fontSize ( ) const;
+ QString fontCharSet ( ) const;
+
+signals:
+ /**
+ * This signal gets emitted when a font got chosen
+ */
+ void fontSelected ( const QFont & );
+
+protected slots:
+ /** @internal */
+ virtual void fontFamilyClicked ( int );
+ /** @internal */
+ virtual void fontStyleClicked ( int );
+ /** @internal */
+ virtual void fontSizeClicked ( int );
+
+protected:
+ virtual void resizeEvent ( QResizeEvent *re );
+
+private:
+ void loadFonts ( QListBox * );
+
+ void changeFont ( );
+
+private:
+ OFontSelectorPrivate *d;
+};
+
+#endif
+
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 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+//
+// KPROCESSCONTROLLER -- A helper class for KProcess
+//
+// version 0.3.1, Jan, 8th 1997
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+// Ported by Holger Freyther
+//
+
+//#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <qsocketnotifier.h>
+#include "oprocctrl.h"
+
+OProcessController *OProcessController::theOProcessController = 0;
+
+struct sigaction OProcessController::oldChildHandlerData;
+bool OProcessController::handlerSet = false;
+
+OProcessController::OProcessController()
+{
+ assert( theOProcessController == 0 );
+
+ if (0 > pipe(fd))
+ printf(strerror(errno));
+
+ notifier = new QSocketNotifier(fd[0], QSocketNotifier::Read);
+ notifier->setEnabled(true);
+ QObject::connect(notifier, SIGNAL(activated(int)),
+ this, SLOT(slotDoHousekeeping(int)));
+ connect( &delayedChildrenCleanupTimer, SIGNAL( timeout()),
+ SLOT( delayedChildrenCleanup()));
+
+ theOProcessController = this;
+
+ setupHandlers();
+}
+
+
+void OProcessController::setupHandlers()
+{
+ if( handlerSet )
+ return;
+ struct sigaction act;
+ act.sa_handler=theSigCHLDHandler;
+ sigemptyset(&(act.sa_mask));
+ sigaddset(&(act.sa_mask), SIGCHLD);
+ // Make sure we don't block this signal. gdb tends to do that :-(
+ sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0);
+
+ act.sa_flags = SA_NOCLDSTOP;
+
+ // CC: take care of SunOS which automatically restarts interrupted system
+ // calls (and thus does not have SA_RESTART)
+
+#ifdef SA_RESTART
+ act.sa_flags |= SA_RESTART;
+#endif
+
+ sigaction( SIGCHLD, &act, &oldChildHandlerData );
+
+ act.sa_handler=SIG_IGN;
+ sigemptyset(&(act.sa_mask));
+ sigaddset(&(act.sa_mask), SIGPIPE);
+ act.sa_flags = 0;
+ sigaction( SIGPIPE, &act, 0L);
+ handlerSet = true;
+}
+
+void OProcessController::resetHandlers()
+{
+ if( !handlerSet )
+ return;
+ sigaction( SIGCHLD, &oldChildHandlerData, 0 );
+ // there should be no problem with SIGPIPE staying SIG_IGN
+ handlerSet = false;
+}
+
+// block SIGCHLD handler, because it accesses processList
+void OProcessController::addOProcess( OProcess* p )
+{
+ sigset_t newset, oldset;
+ sigemptyset( &newset );
+ sigaddset( &newset, SIGCHLD );
+ sigprocmask( SIG_BLOCK, &newset, &oldset );
+ processList.append( p );
+ sigprocmask( SIG_SETMASK, &oldset, 0 );
+}
+
+void OProcessController::removeOProcess( OProcess* p )
+{
+ sigset_t newset, oldset;
+ sigemptyset( &newset );
+ sigaddset( &newset, SIGCHLD );
+ sigprocmask( SIG_BLOCK, &newset, &oldset );
+ processList.remove( p );
+ sigprocmask( SIG_SETMASK, &oldset, 0 );
+}
+
+//using a struct which contains both the pid and the status makes it easier to write
+//and read the data into the pipe
+//especially this solves a problem which appeared on my box where slotDoHouseKeeping() received
+//only 4 bytes (with some debug output around the write()'s it received all 8 bytes)
+//don't know why this happened, but when writing all 8 bytes at once it works here, aleXXX
+struct waitdata
+{
+ pid_t pid;
+ int status;
+};
+
+void OProcessController::theSigCHLDHandler(int arg)
+{
+ struct waitdata wd;
+// int status;
+// pid_t this_pid;
+ int saved_errno;
+
+ saved_errno = errno;
+ // since waitpid and write change errno, we have to save it and restore it
+ // (Richard Stevens, Advanced programming in the Unix Environment)
+
+ bool found = false;
+ if( theOProcessController != 0 ) {
+ // iterating the list doesn't perform any system call
+ for( QValueList<OProcess*>::ConstIterator it = theOProcessController->processList.begin();
+ it != theOProcessController->processList.end();
+ ++it )
+ {
+ if( !(*it)->isRunning())
+ continue;
+ wd.pid = waitpid( (*it)->pid(), &wd.status, WNOHANG );
+ if ( wd.pid > 0 ) {
+ ::write(theOProcessController->fd[1], &wd, sizeof(wd));
+ found = true;
+ }
+ }
+ }
+ if( !found && oldChildHandlerData.sa_handler != SIG_IGN
+ && oldChildHandlerData.sa_handler != SIG_DFL )
+ oldChildHandlerData.sa_handler( arg ); // call the old handler
+ // handle the rest
+ if( theOProcessController != 0 ) {
+ static const struct waitdata dwd = { 0, 0 }; // delayed waitpid()
+ ::write(theOProcessController->fd[1], &dwd, sizeof(dwd));
+ } else {
+ int dummy;
+ while( waitpid( -1, &dummy, WNOHANG ) > 0 )
+ ;
+ }
+
+ errno = saved_errno;
+}
+
+
+
+void OProcessController::slotDoHousekeeping(int )
+{
+ unsigned int bytes_read = 0;
+ unsigned int errcnt=0;
+ // read pid and status from the pipe.
+ struct waitdata wd;
+ while ((bytes_read < sizeof(wd)) && (errcnt < 50)) {
+ int r = ::read(fd[0], ((char *)&wd) + bytes_read, sizeof(wd) - bytes_read);
+ if (r > 0) bytes_read += r;
+ else if (r < 0) errcnt++;
+ }
+ if (errcnt >= 50) {
+ fprintf(stderr,
+ "Error: Max. error count for pipe read "
+ "exceeded in OProcessController::slotDoHousekeeping\n");
+ return; // it makes no sense to continue here!
+ }
+ if (bytes_read != sizeof(wd)) {
+ fprintf(stderr,
+ "Error: Could not read info from signal handler %d <> %d!\n",
+ bytes_read, sizeof(wd));
+ return; // it makes no sense to continue here!
+ }
+ if (wd.pid==0) { // special case, see delayedChildrenCleanup()
+ delayedChildrenCleanupTimer.start( 1000, true );
+ return;
+ }
+
+ for( QValueList<OProcess*>::ConstIterator it = processList.begin();
+ it != processList.end();
+ ++it ) {
+ OProcess* proc = *it;
+ if (proc->pid() == wd.pid) {
+ // process has exited, so do emit the respective events
+ if (proc->run_mode == OProcess::Block) {
+ // If the reads are done blocking then set the status in proc
+ // but do nothing else because OProcess will perform the other
+ // actions of processHasExited.
+ proc->status = wd.status;
+ proc->runs = false;
+ } else {
+ proc->processHasExited(wd.status);
+ }
+ return;
+ }
+ }
+}
+
+// this is needed e.g. for popen(), which calls waitpid() checking
+// for its forked child, if we did waitpid() directly in the SIGCHLD
+// handler, popen()'s waitpid() call would fail
+void OProcessController::delayedChildrenCleanup()
+{
+ struct waitdata wd;
+ while(( wd.pid = waitpid( -1, &wd.status, WNOHANG ) ) > 0 ) {
+ for( QValueList<OProcess*>::ConstIterator it = processList.begin();
+ it != processList.end();
+ ++it )
+ {
+ if( !(*it)->isRunning() || (*it)->pid() != wd.pid )
+ continue;
+ // it's OProcess, handle it
+ ::write(fd[1], &wd, sizeof(wd));
+ break;
+ }
+ }
+}
+
+OProcessController::~OProcessController()
+{
+ assert( theOProcessController == this );
+ resetHandlers();
+
+ notifier->setEnabled(false);
+
+ close(fd[0]);
+ close(fd[1]);
+
+ delete notifier;
+ theOProcessController = 0;
+}
+
+//#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 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+//
+// KPROCESSCONTROLLER -- A helper class for KProcess
+//
+// version 0.3.1, Jan 8th 1997
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+// Ported by Holger Freyther
+//
+
+#ifndef __KPROCCTRL_H__
+#define __KPROCCTRL_H__
+
+#include <qvaluelist.h>
+#include <qtimer.h>
+
+#include "oprocess.h"
+
+class OProcessControllerPrivate;
+class QSocketNotifier;
+
+/**
+ * @short Used internally by @ref OProcess
+ * @internal
+ * @author Christian Czezakte <e9025461@student.tuwien.ac.at>
+ *
+ * A class for internal use by OProcess only. -- Exactly one instance
+ * of this class is generated by the first instance of OProcess that is
+ * created (a pointer to it gets stored in @ref theOProcessController ).
+ *
+ * This class takes care of the actual (UN*X) signal handling.
+*/
+class OProcessController : public QObject
+{
+ Q_OBJECT
+
+public:
+ OProcessController();
+ ~OProcessController();
+ //CC: WARNING! Destructor Not virtual (but you don't derive classes from this anyhow...)
+
+public:
+
+ /**
+ * Only a single instance of this class is allowed at a time,
+ * and this static variable is used to track the one instance.
+ */
+ static OProcessController *theOProcessController;
+
+ /**
+ * Automatically called upon SIGCHLD.
+ *
+ * Normally you do not need to do anything with this function but
+ * if your application needs to disable SIGCHLD for some time for
+ * reasons beyond your control, you should call this function afterwards
+ * to make sure that no SIGCHLDs where missed.
+ */
+ static void theSigCHLDHandler(int signal);
+ // handler for sigchld
+
+ /**
+ * @internal
+ */
+ static void setupHandlers();
+ /**
+ * @internal
+ */
+ static void resetHandlers();
+ /**
+ * @internal
+ */
+ void addOProcess( OProcess* );
+ /**
+ * @internal
+ */
+ void removeOProcess( OProcess* );
+ public slots:
+ /**
+ * @internal
+ */
+ void slotDoHousekeeping(int socket);
+
+ private slots:
+ void delayedChildrenCleanup();
+private:
+ int fd[2];
+ QSocketNotifier *notifier;
+ static struct sigaction oldChildHandlerData;
+ static bool handlerSet;
+ QValueList<OProcess*> processList;
+ QTimer delayedChildrenCleanupTimer;
+
+ // Disallow assignment and copy-construction
+ OProcessController( const OProcessController& );
+ OProcessController& operator= ( const OProcessController& );
+
+ OProcessControllerPrivate *d;
+};
+
+
+
+#endif
+
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 @@
+/*
+
+ $Id$
+
+ This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+
+//
+// KPROCESS -- A class for handling child processes in KDE without
+// having to take care of Un*x specific implementation details
+//
+// version 0.3.1, Jan 8th 1998
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+//
+// Changes:
+//
+// March 2nd, 1998: Changed parameter list for KShellProcess:
+// Arguments are now placed in a single string so that
+// <shell> -c <commandstring> is passed to the shell
+// to make the use of "operator<<" consistent with KProcess
+//
+//
+// Ported by Holger Freyther
+// <zekce> Harlekin: oprocess and say it was ported to Qt by the Opie developers an Qt 2
+
+
+
+#include "oprocess.h"
+#define _MAY_INCLUDE_KPROCESSCONTROLLER_
+#include "oprocctrl.h"
+
+//#include <config.h>
+
+#include <qfile.h>
+#include <qsocketnotifier.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_INITGROUPS
+#include <grp.h>
+#endif
+#include <pwd.h>
+
+#include <qapplication.h>
+#include <qmap.h>
+//#include <kdebug.h>
+
+/////////////////////////////
+// public member functions //
+/////////////////////////////
+
+class OProcessPrivate {
+public:
+ OProcessPrivate() : useShell(false) { }
+
+ bool useShell;
+ QMap<QString,QString> env;
+ QString wd;
+ QCString shell;
+};
+
+
+OProcess::OProcess(QObject *parent, const char *name)
+ : QObject(parent, name)
+{
+ init ( );
+}
+
+OProcess::OProcess(const QString &arg0, QObject *parent, const char *name)
+ : QObject(parent, name)
+{
+ init ( );
+ *this << arg0;
+}
+
+OProcess::OProcess(const QStringList &args, QObject *parent, const char *name)
+ : QObject(parent, name)
+{
+ init ( );
+ *this << args;
+}
+
+void OProcess::init ( )
+{
+ run_mode = NotifyOnExit;
+ runs = false;
+ pid_ = 0;
+ status = 0;
+ keepPrivs = false;
+ innot = 0;
+ outnot = 0;
+ errnot = 0;
+ communication = NoCommunication;
+ input_data = 0;
+ input_sent = 0;
+ input_total = 0;
+ d = 0;
+
+ if (0 == OProcessController::theOProcessController) {
+ (void) new OProcessController();
+ CHECK_PTR(OProcessController::theOProcessController);
+ }
+
+ OProcessController::theOProcessController->addOProcess(this);
+ out[0] = out[1] = -1;
+ in[0] = in[1] = -1;
+ err[0] = err[1] = -1;
+}
+
+void
+OProcess::setEnvironment(const QString &name, const QString &value)
+{
+ if (!d)
+ d = new OProcessPrivate;
+ d->env.insert(name, value);
+}
+
+void
+OProcess::setWorkingDirectory(const QString &dir)
+{
+ if (!d)
+ d = new OProcessPrivate;
+ d->wd = dir;
+}
+
+void
+OProcess::setupEnvironment()
+{
+ if (d)
+ {
+ QMap<QString,QString>::Iterator it;
+ for(it = d->env.begin(); it != d->env.end(); ++it)
+ setenv(QFile::encodeName(it.key()).data(),
+ QFile::encodeName(it.data()).data(), 1);
+ if (!d->wd.isEmpty())
+ chdir(QFile::encodeName(d->wd).data());
+ }
+}
+
+void
+OProcess::setRunPrivileged(bool keepPrivileges)
+{
+ keepPrivs = keepPrivileges;
+}
+
+bool
+OProcess::runPrivileged() const
+{
+ return keepPrivs;
+}
+
+
+OProcess::~OProcess()
+{
+ // destroying the OProcess instance sends a SIGKILL to the
+ // child process (if it is running) after removing it from the
+ // list of valid processes (if the process is not started as
+ // "DontCare")
+
+ OProcessController::theOProcessController->removeOProcess(this);
+ // this must happen before we kill the child
+ // TODO: block the signal while removing the current process from the process list
+
+ if (runs && (run_mode != DontCare))
+ kill(SIGKILL);
+
+ // Clean up open fd's and socket notifiers.
+ closeStdin();
+ closeStdout();
+ closeStderr();
+
+ // TODO: restore SIGCHLD and SIGPIPE handler if this is the last OProcess
+ delete d;
+}
+
+void OProcess::detach()
+{
+ OProcessController::theOProcessController->removeOProcess(this);
+
+ runs = false;
+ pid_ = 0;
+
+ // Clean up open fd's and socket notifiers.
+ closeStdin();
+ closeStdout();
+ closeStderr();
+}
+
+bool OProcess::setExecutable(const QString& proc)
+{
+ if (runs) return false;
+
+ if (proc.isEmpty()) return false;
+
+ if (!arguments.isEmpty())
+ arguments.remove(arguments.begin());
+ arguments.prepend(QFile::encodeName(proc));
+
+ return true;
+}
+
+OProcess &OProcess::operator<<(const QStringList& args)
+{
+ QStringList::ConstIterator it = args.begin();
+ for ( ; it != args.end() ; ++it )
+ arguments.append(QFile::encodeName(*it));
+ return *this;
+}
+
+OProcess &OProcess::operator<<(const QCString& arg)
+{
+ return operator<< (arg.data());
+}
+
+OProcess &OProcess::operator<<(const char* arg)
+{
+ arguments.append(arg);
+ return *this;
+}
+
+OProcess &OProcess::operator<<(const QString& arg)
+{
+ arguments.append(QFile::encodeName(arg));
+ return *this;
+}
+
+void OProcess::clearArguments()
+{
+ arguments.clear();
+}
+
+bool OProcess::start(RunMode runmode, Communication comm)
+{
+ uint i;
+ uint n = arguments.count();
+ char **arglist;
+
+ if (runs || (0 == n)) {
+ return false; // cannot start a process that is already running
+ // or if no executable has been assigned
+ }
+ run_mode = runmode;
+ status = 0;
+
+ QCString shellCmd;
+ if (d && d->useShell)
+ {
+ if (d->shell.isEmpty())
+ {
+ qWarning( "Could not find a valid shell" );
+ return false;
+ }
+
+ arglist = static_cast<char **>(malloc( (4)*sizeof(char *)));
+ for (i=0; i < n; i++) {
+ shellCmd += arguments[i];
+ shellCmd += " "; // CC: to separate the arguments
+ }
+
+ arglist[0] = d->shell.data();
+ arglist[1] = (char *) "-c";
+ arglist[2] = shellCmd.data();
+ arglist[3] = 0;
+ }
+ else
+ {
+ arglist = static_cast<char **>(malloc( (n+1)*sizeof(char *)));
+ for (i=0; i < n; i++)
+ arglist[i] = arguments[i].data();
+ arglist[n]= 0;
+ }
+
+ if (!setupCommunication(comm))
+ qWarning( "Could not setup Communication!");
+
+ // We do this in the parent because if we do it in the child process
+ // gdb gets confused when the application runs from gdb.
+ uid_t uid = getuid();
+ gid_t gid = getgid();
+#ifdef HAVE_INITGROUPS
+ struct passwd *pw = getpwuid(uid);
+#endif
+
+ int fd[2];
+ if (0 > pipe(fd))
+ {
+ fd[0] = fd[1] = 0; // Pipe failed.. continue
+ }
+
+ runs = true;
+
+ QApplication::flushX();
+
+ // WABA: Note that we use fork() and not vfork() because
+ // vfork() has unclear semantics and is not standardized.
+ pid_ = fork();
+
+ if (0 == pid_) {
+ if (fd[0])
+ close(fd[0]);
+ if (!runPrivileged())
+ {
+ setgid(gid);
+#if defined( HAVE_INITGROUPS)
+ if(pw)
+ initgroups(pw->pw_name, pw->pw_gid);
+#endif
+ setuid(uid);
+ }
+ // The child process
+ if(!commSetupDoneC())
+ qWarning( "Could not finish comm setup in child!" );
+
+ setupEnvironment();
+
+ // Matthias
+ if (run_mode == DontCare)
+ setpgid(0,0);
+ // restore default SIGPIPE handler (Harri)
+ struct sigaction act;
+ sigemptyset(&(act.sa_mask));
+ sigaddset(&(act.sa_mask), SIGPIPE);
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigaction(SIGPIPE, &act, 0L);
+
+ // We set the close on exec flag.
+ // Closing of fd[1] indicates that the execvp succeeded!
+ if (fd[1])
+ fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+ execvp(arglist[0], arglist);
+ char resultByte = 1;
+ if (fd[1])
+ write(fd[1], &resultByte, 1);
+ _exit(-1);
+ } else if (-1 == pid_) {
+ // forking failed
+
+ runs = false;
+ free(arglist);
+ return false;
+ } else {
+ if (fd[1])
+ close(fd[1]);
+ // the parent continues here
+
+ // Discard any data for stdin that might still be there
+ input_data = 0;
+
+ // Check whether client could be started.
+ if (fd[0]) for(;;)
+ {
+ char resultByte;
+ int n = ::read(fd[0], &resultByte, 1);
+ if (n == 1)
+ {
+ // Error
+ runs = false;
+ close(fd[0]);
+ free(arglist);
+ pid_ = 0;
+ return false;
+ }
+ if (n == -1)
+ {
+ if ((errno == ECHILD) || (errno == EINTR))
+ continue; // Ignore
+ }
+ break; // success
+ }
+ if (fd[0])
+ close(fd[0]);
+
+ if (!commSetupDoneP()) // finish communication socket setup for the parent
+ qWarning( "Could not finish comm setup in parent!" );
+
+ if (run_mode == Block) {
+ commClose();
+
+ // The SIGCHLD handler of the process controller will catch
+ // the exit and set the status
+ while(runs)
+ {
+ OProcessController::theOProcessController->
+ slotDoHousekeeping(0);
+ }
+ runs = FALSE;
+ emit processExited(this);
+ }
+ }
+ free(arglist);
+ return true;
+}
+
+
+
+bool OProcess::kill(int signo)
+{
+ bool rv=false;
+
+ if (0 != pid_)
+ rv= (-1 != ::kill(pid_, signo));
+ // probably store errno somewhere...
+ return rv;
+}
+
+
+
+bool OProcess::isRunning() const
+{
+ return runs;
+}
+
+
+
+pid_t OProcess::pid() const
+{
+ return pid_;
+}
+
+
+
+bool OProcess::normalExit() const
+{
+ int _status = status;
+ return (pid_ != 0) && (!runs) && (WIFEXITED((_status)));
+}
+
+
+
+int OProcess::exitStatus() const
+{
+ int _status = status;
+ return WEXITSTATUS((_status));
+}
+
+
+
+bool OProcess::writeStdin(const char *buffer, int buflen)
+{
+ bool rv;
+
+ // if there is still data pending, writing new data
+ // to stdout is not allowed (since it could also confuse
+ // kprocess...
+ if (0 != input_data)
+ return false;
+
+ if (runs && (communication & Stdin)) {
+ input_data = buffer;
+ input_sent = 0;
+ input_total = buflen;
+ slotSendData(0);
+ innot->setEnabled(true);
+ rv = true;
+ } else
+ rv = false;
+ return rv;
+}
+
+void OProcess::flushStdin ( )
+{
+ if ( !input_data || ( input_sent == input_total ))
+ return;
+
+ int d1, d2;
+
+ do {
+ d1 = input_total - input_sent;
+ slotSendData ( 0 );
+ d2 = input_total - input_sent;
+ } while ( d2 <= d1 );
+}
+
+void OProcess::suspend()
+{
+ if ((communication & Stdout) && outnot)
+ outnot->setEnabled(false);
+}
+
+void OProcess::resume()
+{
+ if ((communication & Stdout) && outnot)
+ outnot->setEnabled(true);
+}
+
+bool OProcess::closeStdin()
+{
+ bool rv;
+
+ if (communication & Stdin) {
+ communication = (Communication) (communication & ~Stdin);
+ delete innot;
+ innot = 0;
+ close(in[1]);
+ rv = true;
+ } else
+ rv = false;
+ return rv;
+}
+
+bool OProcess::closeStdout()
+{
+ bool rv;
+
+ if (communication & Stdout) {
+ communication = (Communication) (communication & ~Stdout);
+ delete outnot;
+ outnot = 0;
+ close(out[0]);
+ rv = true;
+ } else
+ rv = false;
+ return rv;
+}
+
+bool OProcess::closeStderr()
+{
+ bool rv;
+
+ if (communication & Stderr) {
+ communication = static_cast<Communication>(communication & ~Stderr);
+ delete errnot;
+ errnot = 0;
+ close(err[0]);
+ rv = true;
+ } else
+ rv = false;
+ return rv;
+}
+
+
+/////////////////////////////
+// protected slots //
+/////////////////////////////
+
+
+
+void OProcess::slotChildOutput(int fdno)
+{
+ if (!childOutput(fdno))
+ closeStdout();
+}
+
+
+void OProcess::slotChildError(int fdno)
+{
+ if (!childError(fdno))
+ closeStderr();
+}
+
+
+void OProcess::slotSendData(int)
+{
+ if (input_sent == input_total) {
+ innot->setEnabled(false);
+ input_data = 0;
+ emit wroteStdin(this);
+ } else
+ input_sent += ::write(in[1], input_data+input_sent, input_total-input_sent);
+}
+
+
+
+//////////////////////////////
+// private member functions //
+//////////////////////////////
+
+
+
+void OProcess::processHasExited(int state)
+{
+ if (runs)
+ {
+ runs = false;
+ status = state;
+
+ commClose(); // cleanup communication sockets
+
+ // also emit a signal if the process was run Blocking
+ if (DontCare != run_mode)
+ {
+ emit processExited(this);
+ }
+ }
+}
+
+
+
+int OProcess::childOutput(int fdno)
+{
+ if (communication & NoRead) {
+ int len = -1;
+ emit receivedStdout(fdno, len);
+ errno = 0; // Make sure errno doesn't read "EAGAIN"
+ return len;
+ }
+ else
+ {
+ char buffer[1024];
+ int len;
+
+ len = ::read(fdno, buffer, 1024);
+
+ if ( 0 < len) {
+ emit receivedStdout(this, buffer, len);
+ }
+ return len;
+ }
+}
+
+
+
+int OProcess::childError(int fdno)
+{
+ char buffer[1024];
+ int len;
+
+ len = ::read(fdno, buffer, 1024);
+
+ if ( 0 < len)
+ emit receivedStderr(this, buffer, len);
+ return len;
+}
+
+
+
+int OProcess::setupCommunication(Communication comm)
+{
+ int ok;
+
+ communication = comm;
+
+ ok = 1;
+ if (comm & Stdin)
+ ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, in) >= 0;
+
+ if (comm & Stdout)
+ ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, out) >= 0;
+
+ if (comm & Stderr)
+ ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, err) >= 0;
+
+ return ok;
+}
+
+
+
+int OProcess::commSetupDoneP()
+{
+ int ok = 1;
+
+ if (communication != NoCommunication) {
+ if (communication & Stdin)
+ close(in[0]);
+ if (communication & Stdout)
+ close(out[1]);
+ if (communication & Stderr)
+ close(err[1]);
+
+ // Don't create socket notifiers and set the sockets non-blocking if
+ // blocking is requested.
+ if (run_mode == Block) return ok;
+
+ if (communication & Stdin) {
+// ok &= (-1 != fcntl(in[1], F_SETFL, O_NONBLOCK));
+ innot = new QSocketNotifier(in[1], QSocketNotifier::Write, this);
+ CHECK_PTR(innot);
+ innot->setEnabled(false); // will be enabled when data has to be sent
+ QObject::connect(innot, SIGNAL(activated(int)),
+ this, SLOT(slotSendData(int)));
+ }
+
+ if (communication & Stdout) {
+// ok &= (-1 != fcntl(out[0], F_SETFL, O_NONBLOCK));
+ outnot = new QSocketNotifier(out[0], QSocketNotifier::Read, this);
+ CHECK_PTR(outnot);
+ QObject::connect(outnot, SIGNAL(activated(int)),
+ this, SLOT(slotChildOutput(int)));
+ if (communication & NoRead)
+ suspend();
+ }
+
+ if (communication & Stderr) {
+// ok &= (-1 != fcntl(err[0], F_SETFL, O_NONBLOCK));
+ errnot = new QSocketNotifier(err[0], QSocketNotifier::Read, this );
+ CHECK_PTR(errnot);
+ QObject::connect(errnot, SIGNAL(activated(int)),
+ this, SLOT(slotChildError(int)));
+ }
+ }
+ return ok;
+}
+
+
+
+int OProcess::commSetupDoneC()
+{
+ int ok = 1;
+ struct linger so;
+ memset(&so, 0, sizeof(so));
+
+ if (communication & Stdin)
+ close(in[1]);
+ if (communication & Stdout)
+ close(out[0]);
+ if (communication & Stderr)
+ close(err[0]);
+
+ if (communication & Stdin)
+ ok &= dup2(in[0], STDIN_FILENO) != -1;
+ else {
+ int null_fd = open( "/dev/null", O_RDONLY );
+ ok &= dup2( null_fd, STDIN_FILENO ) != -1;
+ close( null_fd );
+ }
+ if (communication & Stdout) {
+ ok &= dup2(out[1], STDOUT_FILENO) != -1;
+ ok &= !setsockopt(out[1], SOL_SOCKET, SO_LINGER, (char*)&so, sizeof(so));
+ }
+ else {
+ int null_fd = open( "/dev/null", O_WRONLY );
+ ok &= dup2( null_fd, STDOUT_FILENO ) != -1;
+ close( null_fd );
+ }
+ if (communication & Stderr) {
+ ok &= dup2(err[1], STDERR_FILENO) != -1;
+ ok &= !setsockopt(err[1], SOL_SOCKET, SO_LINGER, reinterpret_cast<char *>(&so), sizeof(so));
+ }
+ else {
+ int null_fd = open( "/dev/null", O_WRONLY );
+ ok &= dup2( null_fd, STDERR_FILENO ) != -1;
+ close( null_fd );
+ }
+ return ok;
+}
+
+
+
+void OProcess::commClose()
+{
+ if (NoCommunication != communication) {
+ bool b_in = (communication & Stdin);
+ bool b_out = (communication & Stdout);
+ bool b_err = (communication & Stderr);
+ if (b_in)
+ delete innot;
+
+ if (b_out || b_err) {
+ // If both channels are being read we need to make sure that one socket buffer
+ // doesn't fill up whilst we are waiting for data on the other (causing a deadlock).
+ // Hence we need to use select.
+
+ // Once one or other of the channels has reached EOF (or given an error) go back
+ // to the usual mechanism.
+
+ int fds_ready = 1;
+ fd_set rfds;
+
+ int max_fd = 0;
+ if (b_out) {
+ fcntl(out[0], F_SETFL, O_NONBLOCK);
+ if (out[0] > max_fd)
+ max_fd = out[0];
+ delete outnot;
+ outnot = 0;
+ }
+ if (b_err) {
+ fcntl(err[0], F_SETFL, O_NONBLOCK);
+ if (err[0] > max_fd)
+ max_fd = err[0];
+ delete errnot;
+ errnot = 0;
+ }
+
+
+ while (b_out || b_err) {
+ // * If the process is still running we block until we
+ // receive data. (p_timeout = 0, no timeout)
+ // * If the process has already exited, we only check
+ // the available data, we don't wait for more.
+ // (p_timeout = &timeout, timeout immediately)
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ struct timeval *p_timeout = runs ? 0 : &timeout;
+
+ FD_ZERO(&rfds);
+ if (b_out)
+ FD_SET(out[0], &rfds);
+
+ if (b_err)
+ FD_SET(err[0], &rfds);
+
+ fds_ready = select(max_fd+1, &rfds, 0, 0, p_timeout);
+ if (fds_ready <= 0) break;
+
+ if (b_out && FD_ISSET(out[0], &rfds)) {
+ int ret = 1;
+ while (ret > 0) ret = childOutput(out[0]);
+ if ((ret == -1 && errno != EAGAIN) || ret == 0)
+ b_out = false;
+ }
+
+ if (b_err && FD_ISSET(err[0], &rfds)) {
+ int ret = 1;
+ while (ret > 0) ret = childError(err[0]);
+ if ((ret == -1 && errno != EAGAIN) || ret == 0)
+ b_err = false;
+ }
+ }
+ }
+
+ if (b_in) {
+ communication = (Communication) (communication & ~Stdin);
+ close(in[1]);
+ }
+ if (b_out) {
+ communication = (Communication) (communication & ~Stdout);
+ close(out[0]);
+ }
+ if (b_err) {
+ communication = (Communication) (communication & ~Stderr);
+ close(err[0]);
+ }
+ }
+}
+
+void OProcess::setUseShell(bool useShell, const char *shell)
+{
+ if (!d)
+ d = new OProcessPrivate;
+ d->useShell = useShell;
+ d->shell = shell;
+ if (d->shell.isEmpty())
+ d->shell = searchShell();
+}
+
+QString OProcess::quote(const QString &arg)
+{
+ QString res = arg;
+ res.replace(QRegExp(QString::fromLatin1("\'")),
+ QString::fromLatin1("'\"'\"'"));
+ res.prepend('\'');
+ res.append('\'');
+ return res;
+}
+
+QCString OProcess::searchShell()
+{
+ QCString tmpShell = QCString(getenv("SHELL")).stripWhiteSpace();
+ if (!isExecutable(tmpShell))
+ {
+ tmpShell = "/bin/sh";
+ }
+
+ return tmpShell;
+}
+
+bool OProcess::isExecutable(const QCString &filename)
+{
+ struct stat fileinfo;
+
+ if (filename.isEmpty()) return false;
+
+ // CC: we've got a valid filename, now let's see whether we can execute that file
+
+ if (-1 == stat(filename.data(), &fileinfo)) return false;
+ // CC: return false if the file does not exist
+
+ // CC: anyway, we cannot execute directories, block/character devices, fifos or sockets
+ if ( (S_ISDIR(fileinfo.st_mode)) ||
+ (S_ISCHR(fileinfo.st_mode)) ||
+ (S_ISBLK(fileinfo.st_mode)) ||
+#ifdef S_ISSOCK
+ // CC: SYSVR4 systems don't have that macro
+ (S_ISSOCK(fileinfo.st_mode)) ||
+#endif
+ (S_ISFIFO(fileinfo.st_mode)) ||
+ (S_ISDIR(fileinfo.st_mode)) ) {
+ return false;
+ }
+
+ // CC: now check for permission to execute the file
+ if (access(filename.data(), X_OK) != 0) return false;
+
+ // CC: we've passed all the tests...
+ return true;
+}
+
+
+
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 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+//
+// KPROCESS -- A class for handling child processes in KDE without
+// having to take care of Un*x specific implementation details
+//
+// version 0.3.1, Jan 8th 1998
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+// Ported by Holger Freyther to the Open Palmtop Integrated Environment
+//
+
+#ifndef __kprocess_h__
+#define __kprocess_h__
+
+#include <sys/types.h> // for pid_t
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <qvaluelist.h>
+#include <qcstring.h>
+#include <qobject.h>
+
+class QSocketNotifier;
+class OProcessPrivate;
+
+/**
+ * Child process invocation, monitoring and control.
+ *
+ * @sect General usage and features
+ *
+ *This class allows a KDE and OPIE application to start child processes without having
+ *to worry about UN*X signal handling issues and zombie process reaping.
+ *
+ *@see KProcIO
+ *
+ *Basically, this class distinguishes three different ways of running
+ *child processes:
+ *
+ *@li OProcess::DontCare -- The child process is invoked and both the child
+ *process and the parent process continue concurrently.
+ *
+ *Starting a DontCare child process means that the application is
+ *not interested in any notification to determine whether the
+ *child process has already exited or not.
+ *
+ *@li OProcess::NotifyOnExit -- The child process is invoked and both the
+ *child and the parent process run concurrently.
+ *
+ *When the child process exits, the OProcess instance
+ *corresponding to it emits the Qt signal @ref processExited().
+ *
+ *Since this signal is @em not emitted from within a UN*X
+ *signal handler, arbitrary function calls can be made.
+ *
+ *Be aware: When the OProcess objects gets destructed, the child
+ *process will be killed if it is still running!
+ *This means in particular, that you cannot use a OProcess on the stack
+ *with OProcess::NotifyOnExit.
+ *
+ *@li OProcess::Block -- The child process starts and the parent process
+ *is suspended until the child process exits. (@em Really not recommended
+ *for programs with a GUI.)
+ *
+ *OProcess also provides several functions for determining the exit status
+ *and the pid of the child process it represents.
+ *
+ *Furthermore it is possible to supply command-line arguments to the process
+ *in a clean fashion (no null -- terminated stringlists and such...)
+ *
+ *A small usage example:
+ *<pre>
+ *OProcess *proc = new OProcess;
+ *
+ **proc << "my_executable";
+ **proc << "These" << "are" << "the" << "command" << "line" << "args";
+ *QApplication::connect(proc, SIGNAL(processExited(OProcess *)),
+ * pointer_to_my_object, SLOT(my_objects_slot(OProcess *)));
+ *proc->start();
+ *</pre>
+ *
+ *This will start "my_executable" with the commandline arguments "These"...
+ *
+ *When the child process exits, the respective Qt signal will be emitted.
+ *
+ *@sect Communication with the child process
+ *
+ *OProcess supports communication with the child process through
+ *stdin/stdout/stderr.
+ *
+ *The following functions are provided for getting data from the child
+ *process or sending data to the child's stdin (For more information,
+ *have a look at the documentation of each function):
+ *
+ *@li bool @ref writeStdin(char *buffer, int buflen);
+ *@li -- Transmit data to the child process's stdin.
+ *
+ *@li bool @ref closeStdin();
+ *@li -- Closes the child process's stdin (which causes it to see an feof(stdin)).
+ *Returns false if you try to close stdin for a process that has been started
+ *without a communication channel to stdin.
+ *
+ *@li bool @ref closeStdout();
+ *@li -- Closes the child process's stdout.
+ *Returns false if you try to close stdout for a process that has been started
+ *without a communication channel to stdout.
+ *
+ *@li bool @ref closeStderr();
+ *@li -- Closes the child process's stderr.
+ *Returns false if you try to close stderr for a process that has been started
+ *without a communication channel to stderr.
+ *
+ *
+ *@sect QT signals:
+ *
+ *@li void @ref receivedStdout(OProcess *proc, char *buffer, int buflen);
+ *@li void @ref receivedStderr(OProcess *proc, char *buffer, int buflen);
+ *@li -- Indicates that new data has arrived from either the
+ *child process's stdout or stderr.
+ *
+ *@li void @ref wroteStdin(OProcess *proc);
+ *@li -- Indicates that all data that has been sent to the child process
+ *by a prior call to @ref writeStdin() has actually been transmitted to the
+ *client .
+ *
+ *@author Christian Czezakte e9025461@student.tuwien.ac.at
+ *
+ *
+ **/
+class OProcess : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * Modes in which the communication channel can be opened.
+ *
+ * If communication for more than one channel is required,
+ * the values have to be or'ed together, for example to get
+ * communication with stdout as well as with stdin, you would
+ * specify @p Stdin @p | @p Stdout
+ *
+ * If @p NoRead is specified in conjunction with @p Stdout,
+ * no data is actually read from @p Stdout but only
+ * the signal @ref childOutput(int fd) is emitted.
+ */
+ enum Communication { NoCommunication = 0, Stdin = 1, Stdout = 2, Stderr = 4,
+ AllOutput = 6, All = 7,
+ NoRead };
+
+ /**
+ * Run-modes for a child process.
+ */
+ enum RunMode {
+ /**
+ * The application does not receive notifications from the subprocess when
+ * it is finished or aborted.
+ */
+ DontCare,
+ /**
+ * The application is notified when the subprocess dies.
+ */
+ NotifyOnExit,
+ /**
+ * The application is suspended until the started process is finished.
+ */
+ Block };
+
+ /**
+ * Constructor
+ */
+ OProcess(QObject *parent = 0, const char *name = 0);
+ /**
+ * Constructor
+ */
+ OProcess(const QString &arg0, QObject *parent = 0, const char *name = 0);
+ /**
+ * Constructor
+ */
+ OProcess(const QStringList &args, QObject *parent = 0, const char *name = 0);
+
+ /**
+ *Destructor:
+ *
+ * If the process is running when the destructor for this class
+ * is called, the child process is killed with a SIGKILL, but
+ * only if the run mode is not of type @p DontCare.
+ * Processes started as @p DontCare keep running anyway.
+ */
+ virtual ~OProcess();
+
+ /**
+ @deprecated
+
+ The use of this function is now deprecated. -- Please use the
+ "operator<<" instead of "setExecutable".
+
+ Sets the executable to be started with this OProcess object.
+ Returns false if the process is currently running (in that
+ case the executable remains unchanged.)
+
+ @see operator<<
+
+ */
+ bool setExecutable(const QString& proc);
+
+
+ /**
+ * Sets the executable and the command line argument list for this process.
+ *
+ * For example, doing an "ls -l /usr/local/bin" can be achieved by:
+ * <pre>
+ * OProcess p;
+ * ...
+ * p << "ls" << "-l" << "/usr/local/bin"
+ * </pre>
+ *
+ **/
+ OProcess &operator<<(const QString& arg);
+ /**
+ * Similar to previous method, takes a char *, supposed to be in locale 8 bit already.
+ */
+ OProcess &operator<<(const char * arg);
+ /**
+ * Similar to previous method, takes a QCString, supposed to be in locale 8 bit already.
+ */
+ OProcess &operator<<(const QCString & arg);
+
+ /**
+ * Sets the executable and the command line argument list for this process,
+ * in a single method call, or add a list of arguments.
+ **/
+ OProcess &operator<<(const QStringList& args);
+
+ /**
+ * Clear a command line argument list that has been set by using
+ * the "operator<<".
+ */
+ void clearArguments();
+
+ /**
+ * Starts the process.
+ * For a detailed description of the
+ * various run modes and communication semantics, have a look at the
+ * general description of the OProcess class.
+ *
+ * The following problems could cause this function to
+ * return false:
+ *
+ * @li The process is already running.
+ * @li The command line argument list is empty.
+ * @li The starting of the process failed (could not fork).
+ * @li The executable was not found.
+ *
+ * @param comm Specifies which communication links should be
+ * established to the child process (stdin/stdout/stderr). By default,
+ * no communication takes place and the respective communication
+ * signals will never get emitted.
+ *
+ * @return true on success, false on error
+ * (see above for error conditions)
+ **/
+ virtual bool start(RunMode runmode = NotifyOnExit,
+ Communication comm = NoCommunication);
+
+ /**
+ * Stop the process (by sending it a signal).
+ *
+ * @param signo The signal to send. The default is SIGTERM.
+ * @return @p true if the signal was delivered successfully.
+ */
+ virtual bool kill(int signo = SIGTERM);
+
+ /**
+ @return @p true if the process is (still) considered to be running
+ */
+ bool isRunning() const;
+
+ /** Returns the process id of the process.
+ *
+ * If it is called after
+ * the process has exited, it returns the process id of the last
+ * child process that was created by this instance of OProcess.
+ *
+ * Calling it before any child process has been started by this
+ * OProcess instance causes pid() to return 0.
+ **/
+ pid_t pid() const;
+
+ /**
+ * Suspend processing of data from stdout of the child process.
+ */
+ void suspend();
+
+ /**
+ * Resume processing of data from stdout of the child process.
+ */
+ void resume();
+
+ /**
+ * @return @p true if the process has already finished and has exited
+ * "voluntarily", ie: it has not been killed by a signal.
+ *
+ * Note that you should check @ref OProcess::exitStatus() to determine
+ * whether the process completed its task successful or not.
+ */
+ bool normalExit() const;
+
+ /**
+ * Returns the exit status of the process.
+ *
+ * Please use
+ * @ref OProcess::normalExit() to check whether the process has exited
+ * cleanly (i.e., @ref OProcess::normalExit() returns @p true) before calling
+ * this function because if the process did not exit normally,
+ * it does not have a valid exit status.
+ */
+ int exitStatus() const;
+
+
+ /**
+ * Transmit data to the child process's stdin.
+ *
+ * OProcess::writeStdin may return false in the following cases:
+ *
+ * @li The process is not currently running.
+ *
+ * @li Communication to stdin has not been requested in the @ref start() call.
+ *
+ * @li Transmission of data to the child process by a previous call to
+ * @ref writeStdin() is still in progress.
+ *
+ * Please note that the data is sent to the client asynchronously,
+ * so when this function returns, the data might not have been
+ * processed by the child process.
+ *
+ * If all the data has been sent to the client, the signal
+ * @ref wroteStdin() will be emitted.
+ *
+ * Please note that you must not free "buffer" or call @ref writeStdin()
+ * again until either a @ref wroteStdin() signal indicates that the
+ * data has been sent or a @ref processHasExited() signal shows that
+ * the child process is no longer alive...
+ **/
+ bool writeStdin(const char *buffer, int buflen);
+
+ void flushStdin();
+
+ /**
+ * This causes the stdin file descriptor of the child process to be
+ * closed indicating an "EOF" to the child.
+ *
+ * @return @p false if no communication to the process's stdin
+ * had been specified in the call to @ref start().
+ */
+ bool closeStdin();
+
+ /**
+ * This causes the stdout file descriptor of the child process to be
+ * closed.
+ *
+ * @return @p false if no communication to the process's stdout
+ * had been specified in the call to @ref start().
+ */
+ bool closeStdout();
+
+ /**
+ * This causes the stderr file descriptor of the child process to be
+ * closed.
+ *
+ * @return @p false if no communication to the process's stderr
+ * had been specified in the call to @ref start().
+ */
+ bool closeStderr();
+
+ /**
+ * Lets you see what your arguments are for debugging.
+ */
+
+ const QValueList<QCString> &args() { return arguments; }
+
+ /**
+ * Controls whether the started process should drop any
+ * setuid/segid privileges or whether it should keep them
+ *
+ * The default is @p false : drop privileges
+ */
+ void setRunPrivileged(bool keepPrivileges);
+
+ /**
+ * Returns whether the started process will drop any
+ * setuid/segid privileges or whether it will keep them
+ */
+ bool runPrivileged() const;
+
+ /**
+ * Modifies the environment of the process to be started.
+ * This function must be called before starting the process.
+ */
+ void setEnvironment(const QString &name, const QString &value);
+
+ /**
+ * Changes the current working directory (CWD) of the process
+ * to be started.
+ * This function must be called before starting the process.
+ */
+ void setWorkingDirectory(const QString &dir);
+
+ /**
+ * Specify whether to start the command via a shell or directly.
+ * The default is to start the command directly.
+ * If @p useShell is true @p shell will be used as shell, or
+ * if shell is empty, the standard shell is used.
+ * @p quote A flag indicating whether to quote the arguments.
+ *
+ * When using a shell, the caller should make sure that all filenames etc.
+ * are properly quoted when passed as argument.
+ * @see quote()
+ */
+ void setUseShell(bool useShell, const char *shell = 0);
+
+ /**
+ * This function can be used to quote an argument string such that
+ * the shell processes it properly. This is e. g. necessary for
+ * user-provided file names which may contain spaces or quotes.
+ * It also prevents expansion of wild cards and environment variables.
+ */
+ static QString quote(const QString &arg);
+
+ /**
+ * Detaches OProcess from child process. All communication is closed.
+ * No exit notification is emitted any more for the child process.
+ * Deleting the OProcess will no longer kill the child process.
+ * Note that the current process remains the parent process of the
+ * child process.
+ */
+ void detach();
+
+
+
+signals:
+
+ /**
+ * Emitted after the process has terminated when
+ * the process was run in the @p NotifyOnExit (==default option to
+ * @ref start()) or the @ref Block mode.
+ **/
+ void processExited(OProcess *proc);
+
+
+ /**
+ * Emitted, when output from the child process has
+ * been received on stdout.
+ *
+ * To actually get
+ * these signals, the respective communication link (stdout/stderr)
+ * has to be turned on in @ref start().
+ *
+ * @param buffer The data received.
+ * @param buflen The number of bytes that are available.
+ *
+ * You should copy the information contained in @p buffer to your private
+ * data structures before returning from this slot.
+ **/
+ void receivedStdout(OProcess *proc, char *buffer, int buflen);
+
+ /**
+ * Emitted when output from the child process has
+ * been received on stdout.
+ *
+ * To actually get these signals, the respective communications link
+ * (stdout/stderr) has to be turned on in @ref start() and the
+ * @p NoRead flag should have been passed.
+ *
+ * You will need to explicitly call resume() after your call to start()
+ * to begin processing data from the child process's stdout. This is
+ * to ensure that this signal is not emitted when no one is connected
+ * to it, otherwise this signal will not be emitted.
+ *
+ * The data still has to be read from file descriptor @p fd.
+ **/
+ void receivedStdout(int fd, int &len);
+
+
+ /**
+ * Emitted, when output from the child process has
+ * been received on stderr.
+ * To actually get
+ * these signals, the respective communication link (stdout/stderr)
+ * has to be turned on in @ref start().
+ *
+ * @param buffer The data received.
+ * @param buflen The number of bytes that are available.
+ *
+ * You should copy the information contained in @p buffer to your private
+ * data structures before returning from this slot.
+ */
+ void receivedStderr(OProcess *proc, char *buffer, int buflen);
+
+ /**
+ * Emitted after all the data that has been
+ * specified by a prior call to @ref writeStdin() has actually been
+ * written to the child process.
+ **/
+ void wroteStdin(OProcess *proc);
+
+
+protected slots:
+
+ /**
+ * This slot gets activated when data from the child's stdout arrives.
+ * It usually calls "childOutput"
+ */
+ void slotChildOutput(int fdno);
+
+ /**
+ * This slot gets activated when data from the child's stderr arrives.
+ * It usually calls "childError"
+ */
+ void slotChildError(int fdno);
+ /*
+ Slot functions for capturing stdout and stderr of the child
+ */
+
+ /**
+ * Called when another bulk of data can be sent to the child's
+ * stdin. If there is no more data to be sent to stdin currently
+ * available, this function must disable the QSocketNotifier "innot".
+ */
+ void slotSendData(int dummy);
+
+protected:
+
+ /**
+ * Sets up the environment according to the data passed via
+ * setEnvironment(...)
+ */
+ void setupEnvironment();
+
+ /**
+ * The list of the process' command line arguments. The first entry
+ * in this list is the executable itself.
+ */
+ QValueList<QCString> arguments;
+ /**
+ * How to run the process (Block, NotifyOnExit, DontCare). You should
+ * not modify this data member directly from derived classes.
+ */
+ RunMode run_mode;
+ /**
+ * true if the process is currently running. You should not
+ * modify this data member directly from derived classes. For
+ * reading the value of this data member, please use "isRunning()"
+ * since "runs" will probably be made private in later versions
+ * of OProcess.
+ */
+ bool runs;
+
+ /**
+ * The PID of the currently running process (see "getPid()").
+ * You should not modify this data member in derived classes.
+ * Please use "getPid()" instead of directly accessing this
+ * member function since it will probably be made private in
+ * later versions of OProcess.
+ */
+ pid_t pid_;
+
+ /**
+ * The process' exit status as returned by "waitpid". You should not
+ * modify the value of this data member from derived classes. You should
+ * rather use @ref exitStatus than accessing this data member directly
+ * since it will probably be made private in further versions of
+ * OProcess.
+ */
+ int status;
+
+
+ /**
+ * See setRunPrivileged()
+ */
+ bool keepPrivs;
+
+ /*
+ Functions for setting up the sockets for communication.
+ setupCommunication
+ -- is called from "start" before "fork"ing.
+ commSetupDoneP
+ -- completes communication socket setup in the parent
+ commSetupDoneC
+ -- completes communication setup in the child process
+ commClose
+ -- frees all allocated communication resources in the parent
+ after the process has exited
+ */
+
+ /**
+ * This function is called from "OProcess::start" right before a "fork" takes
+ * place. According to
+ * the "comm" parameter this function has to initialize the "in", "out" and
+ * "err" data member of OProcess.
+ *
+ * This function should return 0 if setting the needed communication channels
+ * was successful.
+ *
+ * The default implementation is to create UNIX STREAM sockets for the communication,
+ * but you could overload this function and establish a TCP/IP communication for
+ * network communication, for example.
+ */
+ virtual int setupCommunication(Communication comm);
+
+ /**
+ * Called right after a (successful) fork on the parent side. This function
+ * will usually do some communications cleanup, like closing the reading end
+ * of the "stdin" communication channel.
+ *
+ * Furthermore, it must also create the QSocketNotifiers "innot", "outnot" and
+ * "errnot" and connect their Qt slots to the respective OProcess member functions.
+ *
+ * For a more detailed explanation, it is best to have a look at the default
+ * implementation of "setupCommunication" in kprocess.cpp.
+ */
+ virtual int commSetupDoneP();
+
+ /**
+ * Called right after a (successful) fork, but before an "exec" on the child
+ * process' side. It usually just closes the unused communication ends of
+ * "in", "out" and "err" (like the writing end of the "in" communication
+ * channel.
+ */
+ virtual int commSetupDoneC();
+
+
+ /**
+ * Immediately called after a process has exited. This function normally
+ * calls commClose to close all open communication channels to this
+ * process and emits the "processExited" signal (if the process was
+ * not running in the "DontCare" mode).
+ */
+ virtual void processHasExited(int state);
+
+ /**
+ * Should clean up the communication links to the child after it has
+ * exited. Should be called from "processHasExited".
+ */
+ virtual void commClose();
+
+
+ /**
+ * the socket descriptors for stdin/stdout/stderr.
+ */
+ int out[2];
+ int in[2];
+ int err[2];
+
+ /**
+ * The socket notifiers for the above socket descriptors.
+ */
+ QSocketNotifier *innot;
+ QSocketNotifier *outnot;
+ QSocketNotifier *errnot;
+
+ /**
+ * Lists the communication links that are activated for the child
+ * process. Should not be modified from derived classes.
+ */
+ Communication communication;
+
+ /**
+ * Called by "slotChildOutput" this function copies data arriving from the
+ * child process's stdout to the respective buffer and emits the signal
+ * "@ref receivedStderr".
+ */
+ int childOutput(int fdno);
+
+ /**
+ * Called by "slotChildOutput" this function copies data arriving from the
+ * child process's stdout to the respective buffer and emits the signal
+ * "@ref receivedStderr"
+ */
+ int childError(int fdno);
+
+ // information about the data that has to be sent to the child:
+
+ const char *input_data; // the buffer holding the data
+ int input_sent; // # of bytes already transmitted
+ int input_total; // total length of input_data
+
+ /**
+ * @ref OProcessController is a friend of OProcess because it has to have
+ * access to various data members.
+ */
+ friend class OProcessController;
+
+
+private:
+ /**
+ * Searches for a valid shell.
+ * Here is the algorithm used for finding an executable shell:
+ *
+ * @li Try the executable pointed to by the "SHELL" environment
+ * variable with white spaces stripped off
+ *
+ * @li If your process runs with uid != euid or gid != egid, a shell
+ * not listed in /etc/shells will not used.
+ *
+ * @li If no valid shell could be found, "/bin/sh" is used as a last resort.
+ */
+ QCString searchShell();
+
+ /**
+ * Used by @ref searchShell in order to find out whether the shell found
+ * is actually executable at all.
+ */
+ bool isExecutable(const QCString &filename);
+
+ // Disallow assignment and copy-construction
+ OProcess( const OProcess& );
+ OProcess& operator= ( const OProcess& );
+
+private:
+ void init ( );
+
+ OProcessPrivate *d;
+};
+
+
+
+#endif
+
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 @@
+<!DOCTYPE UI><UI>
+<class>ORecurranceBase</class>
+<comment>*********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+** $Id$
+**
+*********************************************************************</comment>
+<widget>
+ <class>QDialog</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>ORecurranceBase</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>246</width>
+ <height>309</height>
+ </rect>
+ </property>
+ <property stdset="1">
+ <name>caption</name>
+ <string>Repeating Event </string>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>5</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>1</number>
+ </property>
+ <widget>
+ <class>QButtonGroup</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>fraType</cstring>
+ </property>
+ <property stdset="1">
+ <name>frameShape</name>
+ <enum>NoFrame</enum>
+ </property>
+ <property stdset="1">
+ <name>frameShadow</name>
+ <enum>Sunken</enum>
+ </property>
+ <property stdset="1">
+ <name>title</name>
+ <string></string>
+ </property>
+ <property stdset="1">
+ <name>exclusive</name>
+ <bool>true</bool>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>5</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>1</number>
+ </property>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdNone</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>None</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdDay</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Day</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdWeek</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Week</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdMonth</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Month</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdYear</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Year</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout4</cstring>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>lblEvery</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Every:</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QSpinBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>spinFreq</cstring>
+ </property>
+ <property stdset="1">
+ <name>minValue</name>
+ <number>1</number>
+ </property>
+ </widget>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>lblFreq</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Frequency</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout8</cstring>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>lblEnd</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>End On:</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdEnd</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>No End Date</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QCheckBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>chkNoEnd</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>No End Date</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget>
+ <class>QButtonGroup</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>fraExtra</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>frameShape</name>
+ <enum>Box</enum>
+ </property>
+ <property stdset="1">
+ <name>title</name>
+ <string>Repeat On</string>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>5</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>1</number>
+ </property>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdExtra1</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Mon</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdExtra2</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Tue</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdExtra3</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Wed</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdExtra4</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Thu</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdExtra5</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Fri</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdExtra6</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Sat</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>cmdExtra7</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Sun</string>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget>
+ <class>QFrame</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Frame3</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>frameShape</name>
+ <enum>Box</enum>
+ </property>
+ <property stdset="1">
+ <name>frameShadow</name>
+ <enum>Sunken</enum>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>5</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>1</number>
+ </property>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout6</cstring>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>0</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>lblRepeat</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>3</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Every</string>
+ </property>
+ <property stdset="1">
+ <name>alignment</name>
+ <set>AlignTop|AlignLeft</set>
+ </property>
+ <property>
+ <name>hAlign</name>
+ </property>
+ <property>
+ <name>vAlign</name>
+ </property>
+ </widget>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>lblVar1</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Var1</string>
+ </property>
+ <property stdset="1">
+ <name>alignment</name>
+ <set>AlignTop|AlignLeft</set>
+ </property>
+ <property>
+ <name>hAlign</name>
+ </property>
+ <property>
+ <name>vAlign</name>
+ </property>
+ </widget>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>lblVar2</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>1</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Var 2</string>
+ </property>
+ <property stdset="1">
+ <name>alignment</name>
+ <set>AlignTop|AlignRight</set>
+ </property>
+ <property>
+ <name>hAlign</name>
+ </property>
+ <property>
+ <name>vAlign</name>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>lblWeekVar</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>7</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>WeekVar</string>
+ </property>
+ <property stdset="1">
+ <name>alignment</name>
+ <set>AlignTop|AlignHCenter</set>
+ </property>
+ <property>
+ <name>hAlign</name>
+ </property>
+ <property>
+ <name>vAlign</name>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>chkNoEnd</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>cmdEnd</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>chkNoEnd</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>ORecurranceBase</receiver>
+ <slot>slotNoEnd(bool)</slot>
+ </connection>
+ <connection>
+ <sender>spinFreq</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>lblVar1</receiver>
+ <slot>setNum(int)</slot>
+ </connection>
+ <connection>
+ <sender>spinFreq</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>ORecurranceBase</receiver>
+ <slot>setupRepeatLabel( int )</slot>
+ </connection>
+ <connection>
+ <sender>fraType</sender>
+ <signal>clicked(int)</signal>
+ <receiver>ORecurranceBase</receiver>
+ <slot>slotSetRType( int )</slot>
+ </connection>
+ <connection>
+ <sender>fraExtra</sender>
+ <signal>clicked(int)</signal>
+ <receiver>ORecurranceBase</receiver>
+ <slot>slotMonthLabel( int )</slot>
+ </connection>
+ <connection>
+ <sender>fraExtra</sender>
+ <signal>clicked(int)</signal>
+ <receiver>ORecurranceBase</receiver>
+ <slot>slotWeekLabel()</slot>
+ </connection>
+ <slot access="public">setupRepeatLabel( const QString &amp; )</slot>
+ <slot access="public">setupRepeatLabel( int )</slot>
+ <slot access="public">slotMonthLabel( int )</slot>
+ <slot access="public">slotNoEnd(bool)</slot>
+ <slot access="public">slotSetRType( int )</slot>
+ <slot access="public">slotWeekLabel()</slot>
+</connections>
+</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 @@
+#include <qapplication.h>
+#include <qlabel.h>
+#include <qspinbox.h>
+
+
+#include "orecurrancewidget.h"
+
+// Global Templates for use in setting up the repeat label...
+// the problem is these strings get initialized before QPEApplication can install the translator -zecke
+namespace {
+QString strDayTemplate;
+QString strYearTemplate;
+QString strMonthDateTemplate;
+QString strMonthDayTemplate;
+QString strWeekTemplate;
+QString dayLabel[7];
+}
+
+/*
+ * static linkage to not polute the symbol table...
+ * The problem is that const and static linkage are resolved prior to installing a translator
+ * leading to that the above strings are translted but to the original we delay the init of these strings...
+ * -zecke
+ */
+static void fillStrings() {
+ strDayTemplate = QObject::tr("Every");
+ strYearTemplate = QObject::tr("%1 %2 every ");
+ strMonthDateTemplate = QObject::tr("The %1 every ");
+ strMonthDayTemplate = QObject::tr("The %1 %2 of every");
+ strWeekTemplate = QObject::tr("Every ");
+ dayLabel[0] = QObject::tr("Monday");
+ dayLabel[1] = QObject::tr("Tuesday");
+ dayLabel[2] = QObject::tr("Wednesday");
+ dayLabel[3] = QObject::tr("Thursday");
+ dayLabel[4] = QObject::tr("Friday");
+ dayLabel[5] = QObject::tr("Saturday");
+ dayLabel[6] = QObject::tr("Sunday");
+}
+
+static QString numberPlacing( int x ); // return the proper word format for
+ // x (1st, 2nd, etc)
+static int week( const QDate &dt ); // what week in the month is dt?
+
+/**
+ * Constructs the Widget
+ * @param startOnMonday Does the week start on monday
+ * @param newStart The start date of the recurrence
+ * @param parent The parent widget
+ * @param name the name of object
+ * @param modal if the dialog should be modal
+ * @param fl Additional window flags
+ */
+ORecurranceWidget::ORecurranceWidget( bool startOnMonday,
+ const QDate& newStart,
+ QWidget* parent,
+ const char* name,
+ bool modal,
+ WFlags fl )
+ : ORecurranceBase( parent, name, modal, fl ),
+ start( newStart ),
+ currInterval( None ),
+ startWeekOnMonday( startOnMonday )
+{
+ if (strDayTemplate.isEmpty() )
+ fillStrings();
+
+ init();
+ fraType->setButton( currInterval );
+ chkNoEnd->setChecked( TRUE );
+ setupNone();
+}
+
+/**
+ * Different constructor
+ * @param startOnMonday Does the week start on monday?
+ * @param rp Already set ORecur object
+ * @param startDate The start date
+ * @param parent The parent widget
+ * @param name The name of the object
+ * @param modal
+ * @param fl The flags for window
+ */
+ORecurranceWidget::ORecurranceWidget( bool startOnMonday,
+ const ORecur& rp, const QDate& startDate,
+ QWidget* parent, const char* name,
+ bool modal, WFlags fl)
+ : ORecurranceBase( parent, name, modal, fl ),
+ start( startDate ),
+ end( rp.endDate() ),
+ startWeekOnMonday( startOnMonday )
+{
+ if (strDayTemplate.isEmpty() )
+ fillStrings();
+ // do some stuff with the repeat pattern
+ init();
+ setRecurrence( rp );
+}
+
+ORecurranceWidget::~ORecurranceWidget() {
+}
+
+/**
+ * set the start date
+ * @param date the new start date
+ */
+void ORecurranceWidget::setStartDate( const QDate& date ) {
+ setRecurrence( recurrence(), date );
+}
+/**
+ * set the recurrence
+ * @param rp The ORecur object with the new recurrence rules
+ */
+void ORecurranceWidget::setRecurrence( const ORecur& rp ) {
+ setRecurrence( rp, start );
+}
+
+/**
+ * overloaded method taking ORecur and a new start date
+ * @param rp Recurrence rule
+ * @param date The new start date
+ */
+void ORecurranceWidget::setRecurrence( const ORecur& rp, const QDate& date ) {
+ start = date;
+ end = rp.endDate();
+ switch ( rp.type() ) {
+ default:
+ case ORecur::NoRepeat:
+ currInterval = None;
+ setupNone();
+ break;
+ case ORecur::Daily:
+ currInterval = Day;
+ setupDaily();
+ break;
+ case ORecur::Weekly:
+ currInterval = Week;
+ setupWeekly();
+ int day, buttons;
+ for ( day = 0x01, buttons = 0; buttons < 7;
+ day = day << 1, buttons++ ) {
+ if ( rp.days() & day ) {
+ if ( startWeekOnMonday )
+ fraExtra->setButton( buttons );
+ else {
+ if ( buttons == 7 )
+ fraExtra->setButton( 0 );
+ else
+ fraExtra->setButton( buttons + 1 );
+ }
+ }
+ }
+ slotWeekLabel();
+ break;
+ case ORecur::MonthlyDay:
+ currInterval = Month;
+ setupMonthly();
+ fraExtra->setButton( 0 );
+ slotMonthLabel( 0 );
+ break;
+ case ORecur::MonthlyDate:
+ currInterval = Month;
+ setupMonthly();
+ fraExtra->setButton( 1 );
+ slotMonthLabel( 1 );
+ break;
+ case ORecur::Yearly:
+ currInterval = Year;
+ setupYearly();
+ break;
+ }
+ fraType->setButton( currInterval );
+ spinFreq->setValue( rp.frequency() );
+ if ( !rp.hasEndDate() ) {
+ cmdEnd->setText( tr("No End Date") );
+ chkNoEnd->setChecked( TRUE );
+ } else
+ cmdEnd->setText( TimeString::shortDate( end ) );
+}
+
+/**
+ * the user selected recurrence rule.
+ * @return The recurrence rule.
+ */
+ORecur ORecurranceWidget::recurrence()const {
+ QListIterator<QToolButton> it( listRTypeButtons );
+ QListIterator<QToolButton> itExtra( listExtra );
+ ORecur rpTmp;
+ int i;
+ for ( i = 0; *it; ++it, i++ ) {
+ if ( (*it)->isOn() ) {
+ switch ( i ) {
+ case None:
+ rpTmp.setType( ORecur::NoRepeat );
+ break;
+ case Day:
+ rpTmp.setType( ORecur::Daily );
+ break;
+ case Week:{
+ rpTmp.setType( ORecur::Weekly );
+ int day;
+ int day2 = 0;
+ for ( day = 1; *itExtra; ++itExtra, day = day << 1 ) {
+ if ( (*itExtra)->isOn() ) {
+ if ( startWeekOnMonday )
+ day2 |= day;
+ else {
+ if ( day == 1 )
+ day2 |= Event::SUN;
+ else
+ day2 |= day >> 1;
+ }
+ }
+ }
+ rpTmp.setDays( day2 );
+ }
+ break;
+ case Month:
+ if ( cmdExtra1->isOn() )
+ rpTmp.setType( ORecur::MonthlyDay );
+ else if ( cmdExtra2->isOn() )
+ rpTmp.setType( ORecur::MonthlyDate );
+ // figure out the montly day...
+ rpTmp.setPosition( week( start ) );
+ break;
+ case Year:
+ rpTmp.setType( ORecur::Yearly );
+ break;
+ }
+ break; // no need to keep looking!
+ }
+ }
+ rpTmp.setFrequency(spinFreq->value() );
+ rpTmp.setHasEndDate( !chkNoEnd->isChecked() );
+ if ( rpTmp.hasEndDate() ) {
+ rpTmp.setEndDate( end );
+ }
+ // timestamp it...
+// rpTmp.setCreateTime( ); current DateTime is already set -zecke
+ return rpTmp;
+}
+
+/**
+ * Return the end date of the recurrence. This is only
+ * valid if the recurrence rule does contain an enddate
+ */
+QDate ORecurranceWidget::endDate()const {
+ return end;
+}
+void ORecurranceWidget::slotSetRType(int rtype) {
+ // now call the right function based on the type...
+ currInterval = static_cast<repeatButtons>(rtype);
+ switch ( currInterval ) {
+ case None:
+ setupNone();
+ break;
+ case Day:
+ setupDaily();
+ break;
+ case Week:
+ setupWeekly();
+ slotWeekLabel();
+ break;
+ case Month:
+ setupMonthly();
+ cmdExtra2->setOn( TRUE );
+ slotMonthLabel( 1 );
+ break;
+ case Year:
+ setupYearly();
+ break;
+ }
+}
+void ORecurranceWidget::endDateChanged(int y, int m, int d) {
+ end.setYMD( y, m, d );
+ if ( end < start )
+ end = start;
+ cmdEnd->setText( TimeString::shortDate( end ) );
+ repeatPicker->setDate( end.year(), end.month(), end.day() );
+}
+void ORecurranceWidget::slotNoEnd( bool unused) {
+ // if the item was toggled, then go ahead and set it to the maximum date
+ if ( unused ) {
+ end.setYMD( 3000, 12, 31 );
+ cmdEnd->setText( tr("No End Date") );
+ } else {
+ end = start;
+ cmdEnd->setText( TimeString::shortDate(end) );
+ }
+}
+void ORecurranceWidget::setupRepeatLabel( const QString& s) {
+ lblVar1->setText( s );
+}
+void ORecurranceWidget::setupRepeatLabel( int x) {
+ // change the spelling based on the value of x
+ QString strVar2;
+
+ if ( x > 1 )
+ lblVar1->show();
+ else
+ lblVar1->hide();
+
+ switch ( currInterval ) {
+ case None:
+ break;
+ case Day:
+ if ( x > 1 )
+ strVar2 = tr( "days" );
+ else
+ strVar2 = tr( "day" );
+ break;
+ case Week:
+ if ( x > 1 )
+ strVar2 = tr( "weeks" );
+ else
+ strVar2 = tr( "week" );
+ break;
+ case Month:
+ if ( x > 1 )
+ strVar2 = tr( "months" );
+ else
+ strVar2 = tr( "month" );
+ break;
+ case Year:
+ if ( x > 1 )
+ strVar2 = tr( "years" );
+ else
+ strVar2 = tr( "year" );
+ break;
+ }
+ if ( !strVar2.isNull() )
+ lblVar2->setText( strVar2 );
+}
+void ORecurranceWidget::slotWeekLabel() {
+ QString str;
+ QListIterator<QToolButton> it( listExtra );
+ unsigned int i;
+ unsigned int keepMe;
+ bool bNeedCarriage = FALSE;
+ // don't do something we'll regret!!!
+ if ( currInterval != Week )
+ return;
+
+ if ( startWeekOnMonday )
+ keepMe = start.dayOfWeek() - 1;
+ else
+ keepMe = start.dayOfWeek() % 7;
+
+ QStringList list;
+ for ( i = 0; *it; ++it, i++ ) {
+ // a crazy check, if you are repeating weekly, the current day
+ // must be selected!!!
+ if ( i == keepMe && !( (*it)->isOn() ) )
+ (*it)->setOn( TRUE );
+ if ( (*it)->isOn() ) {
+ if ( startWeekOnMonday )
+ list.append( dayLabel[i] );
+ else {
+ if ( i == 0 )
+ list.append( dayLabel[6] );
+ else
+ list.append( dayLabel[i - 1] );
+ }
+ }
+ }
+ QStringList::Iterator itStr;
+ for ( i = 0, itStr = list.begin(); itStr != list.end(); ++itStr, i++ ) {
+ if ( i == 3 )
+ bNeedCarriage = TRUE;
+ else
+ bNeedCarriage = FALSE;
+ if ( str.isNull() )
+ str = *itStr;
+ else if ( i == list.count() - 1 ) {
+ if ( i < 2 )
+ str += tr(" and ") + *itStr;
+ else {
+ if ( bNeedCarriage )
+ str += tr( ",\nand " ) + *itStr;
+ else
+ str += tr( ", and " ) + *itStr;
+ }
+ } else {
+ if ( bNeedCarriage )
+ str += ",\n" + *itStr;
+ else
+ str += ", " + *itStr;
+ }
+ }
+ str = str.prepend( tr("on ") );
+
+ lblWeekVar->setText( str );
+}
+void ORecurranceWidget::slotMonthLabel(int type) {
+ QString str;
+ if ( currInterval != Month || type > 1 )
+ return;
+ if ( type == 1 )
+ str = strMonthDateTemplate.arg( numberPlacing(start.day()) );
+ else
+ str = strMonthDayTemplate.arg( numberPlacing(week(start)))
+ .arg( dayLabel[start.dayOfWeek() - 1] );
+ lblRepeat->setText( str );
+}
+void ORecurranceWidget::slotChangeStartOfWeek( bool onMonday ) {
+ startWeekOnMonday = onMonday;
+ // we need to make this unintrusive as possible...
+ int saveSpin = spinFreq->value();
+ char days = 0;
+ int day;
+ QListIterator<QToolButton> itExtra( listExtra );
+ for ( day = 1; *itExtra; ++itExtra, day = day << 1 ) {
+ if ( (*itExtra)->isOn() ) {
+ if ( !startWeekOnMonday )
+ days |= day;
+ else {
+ if ( day == 1 )
+ days |= ORecur::SUN;
+ else
+ days |= day >> 1;
+ }
+ }
+ }
+ setupWeekly();
+ spinFreq->setValue( saveSpin );
+ int buttons;
+ for ( day = 0x01, buttons = 0; buttons < 7;
+ day = day << 1, buttons++ ) {
+ if ( days & day ) {
+ if ( startWeekOnMonday )
+ fraExtra->setButton( buttons );
+ else {
+ if ( buttons == 7 )
+ fraExtra->setButton( 0 );
+ else
+ fraExtra->setButton( buttons + 1 );
+ }
+ }
+ }
+ slotWeekLabel();
+}
+void ORecurranceWidget::setupNone() {
+ lblRepeat->setText( tr("No Repeat") );
+ lblVar1->hide();
+ lblVar2->hide();
+ hideExtras();
+ cmdEnd->hide();
+ lblFreq->hide();
+ lblEvery->hide();
+ lblFreq->hide();
+ spinFreq->hide();
+ lblEnd->hide();
+ lblWeekVar->hide();
+}
+void ORecurranceWidget::setupDaily() {
+ hideExtras();
+ lblWeekVar->hide();
+ spinFreq->setValue( 1 );
+ lblFreq->setText( tr("day(s)") );
+ lblVar2->show();
+ showRepeatStuff();
+ lblRepeat->setText( strDayTemplate );
+ setupRepeatLabel( 1 );
+}
+void ORecurranceWidget::setupWeekly() {
+// reshow the buttons...
+ fraExtra->setTitle( tr("Repeat On") );
+ fraExtra->setExclusive( FALSE );
+ fraExtra->show();
+ if ( startWeekOnMonday ) {
+ cmdExtra1->setText( tr("Mon") );
+ cmdExtra2->setText( tr("Tue") );
+ cmdExtra3->setText( tr("Wed") );
+ cmdExtra4->setText( tr("Thu") );
+ cmdExtra5->setText( tr("Fri") );
+ cmdExtra6->setText( tr("Sat") );
+ cmdExtra7->setText( tr("Sun") );
+ } else {
+ cmdExtra1->setText( tr("Sun") );
+ cmdExtra2->setText( tr("Mon") );
+ cmdExtra3->setText( tr("Tue") );
+ cmdExtra4->setText( tr("Wed") );
+ cmdExtra5->setText( tr("Thu") );
+ cmdExtra6->setText( tr("Fri") );
+ cmdExtra7->setText( tr("Sat") );
+ }
+ // I hope clustering these improve performance....
+ cmdExtra1->setOn( FALSE );
+ cmdExtra2->setOn( FALSE );
+ cmdExtra3->setOn( FALSE );
+ cmdExtra4->setOn( FALSE );
+ cmdExtra5->setOn( FALSE );
+ cmdExtra6->setOn( FALSE );
+ cmdExtra7->setOn( FALSE );
+
+ cmdExtra1->show();
+ cmdExtra2->show();
+ cmdExtra3->show();
+ cmdExtra4->show();
+ cmdExtra5->show();
+ cmdExtra6->show();
+ cmdExtra7->show();
+
+ lblWeekVar->show();
+ spinFreq->setValue( 1 );
+ // might as well set the day too...
+ if ( startWeekOnMonday ) {
+ fraExtra->setButton( start.dayOfWeek() - 1 );
+ } else {
+ fraExtra->setButton( start.dayOfWeek() % 7 );
+ }
+ lblFreq->setText( tr("week(s)") );
+ lblVar2->show();
+ showRepeatStuff();
+ setupRepeatLabel( 1 );
+}
+void ORecurranceWidget::setupMonthly() {
+ hideExtras();
+ lblWeekVar->hide();
+ fraExtra->setTitle( tr("Repeat By") );
+ fraExtra->setExclusive( TRUE );
+ fraExtra->show();
+ cmdExtra1->setText( tr("Day") );
+ cmdExtra1->show();
+ cmdExtra2->setText( tr("Date") );
+ cmdExtra2->show();
+ spinFreq->setValue( 1 );
+ lblFreq->setText( tr("month(s)") );
+ lblVar2->show();
+ showRepeatStuff();
+ setupRepeatLabel( 1 );
+}
+void ORecurranceWidget::setupYearly() {
+hideExtras();
+ lblWeekVar->hide();
+ spinFreq->setValue( 1 );
+ lblFreq->setText( tr("year(s)") );
+ lblFreq->show();
+ lblFreq->show();
+ showRepeatStuff();
+ lblVar2->show();
+ QString strEvery = strYearTemplate.arg( start.monthName(start.month()) ).arg( numberPlacing(start.day()) );
+ lblRepeat->setText( strEvery );
+ setupRepeatLabel( 1 );
+
+}
+void ORecurranceWidget::init() {
+ QPopupMenu *m1 = new QPopupMenu( this );
+ repeatPicker = new DateBookMonth( m1, 0, TRUE );
+ m1->insertItem( repeatPicker );
+ cmdEnd->setPopup( m1 );
+ cmdEnd->setPopupDelay( 0 );
+
+ QObject::connect( repeatPicker, SIGNAL(dateClicked(int,int,int)),
+ this, SLOT(endDateChanged(int,int,int)) );
+ QObject::connect( qApp, SIGNAL(weekChanged(bool)),
+ this, SLOT(slotChangeStartOfWeek(bool)) );
+
+ listRTypeButtons.setAutoDelete( TRUE );
+ listRTypeButtons.append( cmdNone );
+ listRTypeButtons.append( cmdDay );
+ listRTypeButtons.append( cmdWeek );
+ listRTypeButtons.append( cmdMonth );
+ listRTypeButtons.append( cmdYear );
+
+ listExtra.setAutoDelete( TRUE );
+ listExtra.append( cmdExtra1 );
+ listExtra.append( cmdExtra2 );
+ listExtra.append( cmdExtra3 );
+ listExtra.append( cmdExtra4 );
+ listExtra.append( cmdExtra5 );
+ listExtra.append( cmdExtra6 );
+ listExtra.append( cmdExtra7 );
+}
+void ORecurranceWidget::hideExtras() {
+ // hide the extra buttons...
+ fraExtra->hide();
+ chkNoEnd->hide();
+ QListIterator<QToolButton> it( listExtra );
+ for ( ; *it; ++it ) {
+ (*it)->hide();
+ (*it)->setOn( FALSE );
+ }
+}
+void ORecurranceWidget::showRepeatStuff() {
+ cmdEnd->show();
+ chkNoEnd->show();
+ lblFreq->show();
+ lblEvery->show();
+ lblFreq->show();
+ spinFreq->show();
+ lblEnd->show();
+ lblRepeat->setText( tr("Every") );
+}
+
+
+static int week( const QDate &start )
+{
+ // figure out the week...
+ int stop = start.day(),
+ sentinel = start.dayOfWeek(),
+ dayOfWeek = QDate( start.year(), start.month(), 1 ).dayOfWeek(),
+ week = 1,
+ i;
+ for ( i = 1; i < stop; i++ ) {
+ if ( dayOfWeek++ == sentinel )
+ week++;
+ if ( dayOfWeek > 7 )
+ dayOfWeek = 0;
+ }
+ return week;
+}
+
+static QString numberPlacing( int x )
+{
+ // I hope this works in other languages besides english...
+ QString str = QString::number( x );
+ switch ( x % 10 ) {
+ case 1:
+ str += QWidget::tr( "st" );
+ break;
+ case 2:
+ str += QWidget::tr( "nd" );
+ break;
+ case 3:
+ str += QWidget::tr( "rd" );
+ break;
+ default:
+ str += QWidget::tr( "th" );
+ break;
+ }
+ return str;
+}
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 @@
+/*
+ * GPL and based on the widget from TT
+ */
+
+#ifndef OPIE_RECURRANCE_WIDGET_H
+#define OPIE_RECURRANCE_WIDGET_H
+
+#include <qlist.h>
+#include <qtoolbutton.h>
+#include <qcheckbox.h>
+#include <qdatetime.h>
+#include <qbuttongroup.h>
+
+#include <qpe/datebookmonth.h>
+
+#include "orecurrancebase.h"
+#include <opie/orecur.h>
+
+// FIXME spelling!!!! -zecke
+// FIXME spelling filenames
+
+/**
+ * A widget to let the user select rules for recurrences.
+ * This widget can take care of weekly, monthly, daily and yearly recurrence
+ * It is used inside todolist and datebook.
+ *
+ *
+ * @short Widget of selecting Recurrance
+ * @author Trolltech, Holger Freyther
+ * @version 0.9
+ */
+class ORecurranceWidget : public ORecurranceBase {
+ Q_OBJECT
+public:
+ ORecurranceWidget( bool startOnMonday,
+ const QDate& start, QWidget* parent = 0,
+ const char* name = 0, bool modal = TRUE,
+ WFlags fl = 0 );
+ ORecurranceWidget( bool startOnMonday,
+ const ORecur& rp, const QDate& start,
+ QWidget* parent = 0, const char* name =0,
+ bool modal = TRUE, WFlags = 0 );
+ ~ORecurranceWidget();
+ ORecur recurrence()const;
+ QDate endDate()const;
+
+public slots:
+ void slotSetRType( int );
+ /**
+ * set the new end date
+ */
+ void endDateChanged( int, int, int );
+ /**
+ * enable/disable end date
+ */
+ void slotNoEnd( bool unused );
+ void setStartDate( const QDate& );
+ void setRecurrence( const ORecur& recur, const QDate& start );
+ void setRecurrence( const ORecur& recur );
+
+private slots:
+ void setupRepeatLabel( const QString& );
+ void setupRepeatLabel( int );
+ void slotWeekLabel();
+ void slotMonthLabel( int );
+ void slotChangeStartOfWeek( bool onMonday );
+
+private:
+ void setupNone();
+ void setupDaily();
+ void setupWeekly();
+ void setupMonthly();
+ void setupYearly();
+
+ enum repeatButtons { None, Day, Week, Month, Year };
+ void init();
+ void hideExtras();
+ void showRepeatStuff();
+
+ QList<QToolButton> listRTypeButtons;
+ QList<QToolButton> listExtra;
+ QDate start; // only used in one spot...
+ QDate end;
+ repeatButtons currInterval;
+ bool startWeekOnMonday : 1;
+ DateBookMonth *repeatPicker;
+
+ class Private;
+ Private *d;
+
+};
+
+#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 @@
+/*
+                This file is part of the Opie Project
+
+              Copyright (c) 2002 Dan Williams <williamsdr@acm.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include "otabbar.h"
+
+OTabBar::OTabBar( QWidget *parent , const char *name )
+ : QTabBar( parent, name )
+{
+}
+
+void OTabBar::paintLabel( QPainter* p, const QRect& br, QTab* t, bool has_focus ) const
+{
+
+ QRect r = br;
+ if ( t->iconset)
+ {
+ QIconSet::Mode mode = (t->enabled && isEnabled()) ? QIconSet::Normal : QIconSet::Disabled;
+ if ( mode == QIconSet::Normal && has_focus ) {
+ mode = QIconSet::Active;
+ }
+ QPixmap pixmap = t->iconset->pixmap( QIconSet::Small, mode );
+ int pixw = pixmap.width();
+ int pixh = pixmap.height();
+ r.setLeft( r.left() + pixw + 2 );
+ p->drawPixmap( br.left()+2, br.center().y()-pixh/2, pixmap );
+ }
+
+ QRect tr = r;
+ if ( t->id == currentTab() )
+ {
+ tr.setBottom( tr.bottom() - style().defaultFrameWidth() );
+ }
+
+ if ( t->enabled && isEnabled() )
+ {
+ p->setPen( colorGroup().foreground() );
+ p->drawText( tr, AlignCenter | ShowPrefix, t->label );
+ }
+ else if ( style() == MotifStyle )
+ {
+ p->setPen( palette().disabled().foreground() );
+ p->drawText( tr, AlignCenter | ShowPrefix, t->label );
+ }
+ else
+ {
+ p->setPen( colorGroup().light() );
+ QRect wr = tr;
+ wr.moveBy( 1, 1 );
+ p->drawText( wr, AlignCenter | ShowPrefix, t->label );
+ p->setPen( palette().disabled().foreground() );
+ p->drawText( tr, AlignCenter | ShowPrefix, t->label );
+ }
+}
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 @@
+/*
+                This file is part of the Opie Project
+
+              Copyright (c) 2002 Dan Williams <williamsdr@acm.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OTABBAR_H
+#define OTABBAR_H
+
+#include <qtabbar.h>
+
+/**
+ * @class OTabBar
+ * @brief The OTabBar class is a derivative of QTabBar.
+ *
+ * OTabBar is a derivation of TrollTech's QTabBar which provides
+ * a row of tabs for selection. The only difference between this
+ * class and QTabBar is that there is no dotted line box around
+ * the label of the tab with the current focus.
+ */
+class OTabBar : public QTabBar
+{
+ Q_OBJECT
+
+public:
+/**
+ * @fn OTabBar( QWidget *parent = 0, const char *name = 0 )
+ * @brief Object constructor.
+ *
+ * @param parent Pointer to parent of this control.
+ * @param name Name of control.
+ *
+ * Constructs a new OTabBar control with parent and name.
+ */
+ // FIXME Allow WFlags? -zecke
+ OTabBar( QWidget * = 0, const char * = 0 );
+
+protected:
+/**
+ * @fn paintLabel( QPainter* p, const QRect& br , QTab* t, bool has_focus)const
+ * @brief Internal function to draw a tab's label.
+ *
+ * @param p Pointer to QPainter used for drawing.
+ * @param br QRect providing region to draw label in.
+ * @param t Tab to draw label for.
+ * @param has_focus Boolean value not used, retained for compatibility reasons.
+ */
+ void paintLabel( QPainter *, const QRect &, QTab *, bool ) const;
+
+private:
+ class Private;
+ Private *d;
+};
+
+#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 @@
+/*
+                This file is part of the Opie Project
+
+              Copyright (c) 2002 Dan Williams <williamsdr@acm.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OTABINFO_H
+#define OTABINFO_H
+
+#include <qlist.h>
+#include <qstring.h>
+
+class QWidget;
+
+/**
+ * @class OTabInfo
+ * @brief The OTabInfo class is used internally by OTabWidget to keep track
+ * of widgets added to the control.
+ *
+ * OTabInfo provides the following information about a widget added to an
+ * OTabWidget control:
+ *
+ * ID - integer tab bar ID
+ * Control - QWidget pointer to child widget
+ * Label - QString text label for OTabWidget selection control
+ * Icon - QString name of icon file
+ */
+class OTabInfo
+{
+public:
+/**
+ * @fn OTabInfo()
+ * @brief Object constructor.
+ *
+ * @param parent Pointer to parent of this control.
+ * @param name Name of control.
+ * @param s Style of widget selection control.
+ * @param p Position of the widget selection control.
+ */
+ OTabInfo() : i( -1 ), c( 0 ), p( 0 ), l( QString::null ) {}
+
+/**
+ * @fn OTabInfo( int id, QWidget *control, const QString &icon, const QString &label )
+ * @brief Object constructor.
+ *
+ * @param id TabBar identifier for widget.
+ * @param control QWidget pointer to widget.
+ * @param icon QString name of icon file.
+ * @param label QString text label for OTabWidget selection control.
+ */
+ OTabInfo( int id, QWidget *control, const QString &icon, const QString &label )
+ : i( id ), c( control ), p( icon ), l( label ) {}
+
+/**
+ * @fn id()const
+ * @brief Returns TabBar ID.
+ */
+ int id() const { return i; }
+
+/**
+ * @fn label()const
+ * @brief Returns text label for widget.
+ */
+ const QString &label() const { return l; }
+
+/**
+ * @fn setLabel( const QString &label )
+ * @brief Set label for tab.
+ *
+ * @param label QString text label for OTabWidget selection control.
+ */
+ void setLabel( const QString &label ) { l = label; }
+
+/**
+ * @fn control()const
+ * @brief Returns pointer to widget.
+ */
+ QWidget *control() const { return c; }
+
+/**
+ * @fn icon()const
+ * @brief Returns name of icon file.
+ */
+ const QString &icon() const { return p; }
+
+/**
+ * @fn setIcon( const QString &icon )
+ * @brief Set icon for tab.
+ *
+ * @param icon QString name of icon file.
+ */
+ void setIcon( const QString &icon ) { p = icon; }
+
+private:
+ int i;
+ QWidget *c;
+ QString p;
+ QString l;
+ class Private;
+ Private *d;
+};
+
+/**
+ * @class OTabInfoList
+ * @brief A list of OTabInfo objects used by OTabWidget.
+ */
+typedef QList<OTabInfo> OTabInfoList;
+
+#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 @@
+/*
+                This file is part of the Opie Project
+
+              Copyright (c) 2002 Dan Williams <williamsdr@acm.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include "otabwidget.h"
+
+#include <qpe/applnk.h>
+#include <qpe/config.h>
+#include <qpe/resource.h>
+#include <opie/otabbar.h>
+
+#include <qcombobox.h>
+#include <qwidgetstack.h>
+
+OTabWidget::OTabWidget( QWidget *parent, const char *name, TabStyle s, TabPosition p )
+ : QWidget( parent, name )
+{
+ if ( s == Global )
+ {
+ Config config( "qpe" );
+ config.setGroup( "Appearance" );
+ s = ( TabStyle ) config.readNumEntry( "TabStyle", (int) IconTab );
+ if ( s <= Global || s > IconList)
+ {
+ s = IconTab;
+ }
+ QString pos = config.readEntry( "TabPosition", "Top");
+ if ( pos == "Bottom" )
+ {
+ p = Bottom;
+ }
+ else
+ {
+ p = Top;
+ }
+ }
+
+ widgetStack = new QWidgetStack( this, "widgetstack" );
+ widgetStack->setFrameStyle( QFrame::NoFrame );
+ widgetStack->setLineWidth( style().defaultFrameWidth() );
+
+ tabBarStack = new QWidgetStack( this, "tabbarstack" );
+
+ tabBar = new OTabBar( tabBarStack, "tabbar" );
+ tabBarStack->addWidget( tabBar, 0 );
+ connect( tabBar, SIGNAL( selected(int) ), this, SLOT( slotTabBarSelected(int) ) );
+
+ tabList = new QComboBox( false, tabBarStack, "tablist" );
+ tabBarStack->addWidget( tabList, 1 );
+ connect( tabList, SIGNAL( activated(int) ), this, SLOT( slotTabListSelected(int) ) );
+
+ tabBarPosition = p;
+ setTabStyle( s );
+ setTabPosition( p );
+
+ currTab= 0x0;
+}
+
+OTabWidget::~OTabWidget()
+{
+}
+
+void OTabWidget::addTab( QWidget *child, const QString &icon, const QString &label )
+{
+ QPixmap iconset = loadSmooth( icon );
+
+ QTab *tab = new QTab();
+ if ( tabBarStyle == IconTab )
+ {
+ tab->label = QString::null;
+ }
+ else
+ {
+ tab->label = label;
+ }
+ if ( tabBarStyle == IconTab || tabBarStyle == IconList )
+ {
+ tab->iconset = new QIconSet( iconset );
+ }
+ int tabid = tabBar->addTab( tab );
+
+ if ( tabBarStyle == IconTab || tabBarStyle == IconList )
+ {
+ tabList->insertItem( iconset, label, -1 );
+ }
+ else
+ {
+ tabList->insertItem( label );
+ }
+
+ widgetStack->addWidget( child, tabid );
+ widgetStack->raiseWidget( child );
+ widgetStack->setFrameStyle( QFrame::StyledPanel | QFrame::Raised );
+
+ OTabInfo *tabinfo = new OTabInfo( tabid, child, icon, label );
+ tabs.append( tabinfo );
+ selectTab( tabinfo );
+}
+
+void OTabWidget::removePage( QWidget *childwidget )
+{
+ if ( childwidget )
+ {
+ OTabInfo *tab = tabs.first();
+ while ( tab && tab->control() != childwidget )
+ {
+ tab = tabs.next();
+ }
+ if ( tab && tab->control() == childwidget )
+ {
+ tabBar->setTabEnabled( tab->id(), FALSE );
+ tabBar->removeTab( tabBar->tab( tab->id() ) );
+ int i = 0;
+ while ( i < tabList->count() && tabList->text( i ) != tab->label() )
+ {
+ i++;
+ }
+ if ( tabList->text( i ) == tab->label() )
+ {
+ tabList->removeItem( i );
+ }
+ widgetStack->removeWidget( childwidget );
+ tabs.remove( tab );
+ delete tab;
+ currTab = tabs.current();
+ if ( !currTab )
+ {
+ widgetStack->setFrameStyle( QFrame::NoFrame );
+ }
+
+ setUpLayout();
+ }
+ }
+}
+
+void OTabWidget::changeTab( QWidget *widget, const QString &iconset, const QString &label)
+{
+ OTabInfo *currtab = tabs.first();
+ while ( currtab && currtab->control() != widget )
+ {
+ currtab = tabs.next();
+ }
+ if ( currtab && currtab->control() == widget )
+ {
+ QTab *tab = tabBar->tab( currtab->id() );
+ QPixmap icon( loadSmooth( iconset ) );
+ tab->setText( label );
+ if ( tabBarStyle == IconTab )
+ tab->setIconSet( icon );
+ int i = 0;
+ while ( i < tabList->count() && tabList->text( i ) != currtab->label() )
+ {
+ i++;
+ }
+ if ( i < tabList->count() && tabList->text( i ) == currtab->label() )
+ {
+ if ( tabBarStyle == IconTab || tabBarStyle == IconList )
+ {
+ tabList->changeItem( icon, label, i );
+ }
+ else
+ {
+ tabList->changeItem( label, i );
+ }
+ }
+ currtab->setLabel( label );
+ currtab->setIcon( iconset );
+ }
+ setUpLayout();
+}
+
+void OTabWidget::setCurrentTab( QWidget *childwidget )
+{
+ OTabInfo *currtab = tabs.first();
+ while ( currtab && currtab->control() != childwidget )
+ {
+ currtab = tabs.next();
+ }
+ if ( currtab && currtab->control() == childwidget )
+ {
+ selectTab( currtab );
+ }
+}
+
+void OTabWidget::setCurrentTab( const QString &tabname )
+{
+ OTabInfo *newtab = tabs.first();
+ while ( newtab && newtab->label() != tabname )
+ {
+ newtab = tabs.next();
+ }
+ if ( newtab && newtab->label() == tabname )
+ {
+ selectTab( newtab );
+ }
+}
+
+void OTabWidget::setCurrentTab(int tabindex) {
+ OTabInfo *newtab = tabs.first();
+ while ( newtab && newtab->id() != tabindex )
+ {
+ newtab = tabs.next();
+ }
+ if ( newtab && newtab->id() == tabindex )
+ {
+ selectTab( newtab );
+ }
+}
+
+
+OTabWidget::TabStyle OTabWidget::tabStyle() const
+{
+ return tabBarStyle;
+}
+
+void OTabWidget::setTabStyle( TabStyle s )
+{
+ tabBarStyle = s;
+ if ( tabBarStyle == TextTab || tabBarStyle == IconTab )
+ {
+ QTab *currtab;
+ for ( OTabInfo *tabinfo = tabs.first(); tabinfo; tabinfo = tabs.next() )
+ {
+ currtab = tabBar->tab( tabinfo->id() );
+ if ( tabBarStyle == IconTab )
+ {
+ currtab->iconset = new QIconSet( loadSmooth( tabinfo->icon() ) );
+ if ( tabinfo == currTab )
+ currtab->setText( tabinfo->label() );
+ else
+ currtab->setText( QString::null );
+ }
+ else
+ {
+ currtab->iconset = 0x0;
+ currtab->setText( tabinfo->label() );
+ }
+ }
+ tabBarStack->raiseWidget( tabBar );
+ }
+ else if ( tabBarStyle == TextList || tabBarStyle == IconList )
+ {
+ tabList->clear();
+ for ( OTabInfo *tabinfo = tabs.first(); tabinfo; tabinfo = tabs.next() )
+ {
+ if ( tabBarStyle == IconList )
+ {
+ tabList->insertItem( loadSmooth( tabinfo->icon() ), tabinfo->label() );
+ }
+ else
+ {
+ tabList->insertItem( tabinfo->label() );
+ }
+ }
+ tabBarStack->raiseWidget( tabList );
+ }
+ setUpLayout();
+}
+
+OTabWidget::TabPosition OTabWidget::tabPosition() const
+{
+ return tabBarPosition;
+}
+
+void OTabWidget::setTabPosition( TabPosition p )
+{
+ tabBarPosition = p;
+ if ( tabBarPosition == Top )
+ {
+ tabBar->setShape( QTabBar::RoundedAbove );
+ }
+ else
+ {
+ tabBar->setShape( QTabBar::RoundedBelow );
+ }
+ setUpLayout();
+}
+
+void OTabWidget::slotTabBarSelected( int id )
+{
+ OTabInfo *newtab = tabs.first();
+ while ( newtab && newtab->id() != id )
+ {
+ newtab = tabs.next();
+ }
+ if ( newtab && newtab->id() == id )
+ {
+ selectTab( newtab );
+ }
+}
+
+void OTabWidget::slotTabListSelected( int index )
+{
+ OTabInfo *newtab = tabs.at( index );
+ if ( newtab )
+ {
+ selectTab( newtab );
+ }
+}
+
+QPixmap OTabWidget::loadSmooth( const QString &name )
+{
+ QPixmap p;
+ p.convertFromImage( Resource::loadImage( name ).smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ) );
+ return p;
+}
+
+void OTabWidget::selectTab( OTabInfo *tab )
+{
+ if ( tabBarStyle == IconTab )
+ {
+ if ( currTab )
+ {
+ tabBar->tab( currTab->id() )->setText( QString::null );
+ setUpLayout();
+ }
+ tabBar->tab( tab->id() )->setText( tab->label() );
+ tabBar->setCurrentTab( tab->id() );
+ setUpLayout();
+ tabBar->update();
+ }
+ else
+ {
+ tabBar->setCurrentTab( tab->id() );
+ }
+
+ widgetStack->raiseWidget( tab->control() );
+
+ emit currentChanged( tab->control() );
+
+ currTab = tab;
+}
+
+void OTabWidget::setUpLayout()
+{
+ tabBar->layoutTabs();
+ QSize t( tabBarStack->sizeHint() );
+ if ( tabBarStyle == IconTab )
+ {
+ if ( t.width() > width() )
+ t.setWidth( width() );
+ }
+ else
+ {
+ t.setWidth( width() );
+ }
+ int lw = widgetStack->lineWidth();
+ if ( tabBarPosition == Bottom )
+ {
+ tabBarStack->setGeometry( QMAX(0, lw-2), height() - t.height() - lw, t.width(), t.height() );
+ widgetStack->setGeometry( 0, 0, width(), height()-t.height()+QMAX(0, lw-2) );
+ }
+ else
+ {
+ tabBarStack->setGeometry( QMAX(0, lw-2), 0, t.width(), t.height() );
+ widgetStack->setGeometry( 0, t.height()-lw, width(), height()-t.height()+QMAX( 0, lw-2 ) );
+ }
+
+ if ( autoMask() )
+ updateMask();
+}
+
+QSize OTabWidget::sizeHint() const
+{
+ QSize s( widgetStack->sizeHint() );
+ QSize t( tabBarStack->sizeHint() );
+ return QSize( QMAX( s.width(), t.width() ), s.height() + t.height() );
+}
+
+void OTabWidget::resizeEvent( QResizeEvent * )
+{
+ setUpLayout();
+}
+
+int OTabWidget::currentTab()
+{
+ if ( currTab )
+ {
+ return currTab->id();
+ }
+ return -1;
+}
+
+QWidget* OTabWidget::currentWidget()const
+{
+ if ( currTab )
+ {
+ return currTab->control();
+ }
+
+ return 0;
+}
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 @@
+/*
+                This file is part of the Opie Project
+
+              Copyright (c) 2002 Dan Williams <williamsdr@acm.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OTABWIDGET_H
+#define OTABWIDGET_H
+
+#include "otabinfo.h"
+
+#include <qwidget.h>
+#include <qlist.h>
+
+class OTabBar;
+class QComboBox;
+class QPixmap;
+class QTabBar;
+class QWidgetStack;
+
+/**
+ * @class OTabWidget
+ * @brief The OTabWidget class provides a stack of widgets.
+ *
+ * OTabWidget is a derivation of TrollTech's QTabWidget which provides
+ * a stack of widgets. Widgets can be selected using either a tab bar or
+ * drop down list box.
+ *
+ * The normal way to use OTabWidget is to do the following in the
+ * constructor:
+ * - Create a OTabWidget.
+ * - Create a QWidget for each of the pages in the control, insert
+ * children into it, set up geometry management for it, and use addTab()
+ * to add the widget.
+ */
+class OTabWidget : public QWidget
+{
+ Q_OBJECT
+public:
+
+/**
+ * @enum TabStyle
+ * @brief Defines how the widget selection control is displayed.
+ *
+ * Valid values:
+ * - Global: use globally selected options (qpe.conf - TabStyle & TabPosition)
+ * - TextTab: Tabbed widget selection with text labels
+ * - IconTab: Tabbed widget selection with icon labels, text label for active widget
+ * (similar to Opie launcher)
+ * - TextList: Drop down list widget selection with text labels
+ * - IconList: Drop down list widget selection with icon & text labels
+ */
+ enum TabStyle { Global, TextTab, IconTab, TextList, IconList };
+
+/**
+ * @enum TabPosition
+ * @brief Defines where the widget selection control is drawn.
+ *
+ * Valid values:
+ * - Top: Widget selection control is drawn above widgets
+ * - Bottom: Widget selection control is drawn below widgets
+ */
+ enum TabPosition { Top, Bottom };
+
+/**
+ * @fn OTabWidget( QWidget *parent = 0, const char *name = 0, TabStyle s = Global, TabPosition p = Top )
+ * @brief Object constructor.
+ *
+ * @param parent Pointer to parent of this control.
+ * @param name Name of control.
+ * @param s Style of widget selection control.
+ * @param p Position of the widget selection control.
+ *
+ * Constructs a new OTabWidget control with parent and name. The style and position parameters
+ * determine how the widget selection control will be displayed.
+ */
+ // FIXME WFlags? -zecke
+ OTabWidget( QWidget * = 0, const char * = 0, TabStyle = Global, TabPosition = Top );
+
+/**
+ * @fn ~OTabWidget()
+ * @brief Object destructor.
+ */
+ ~OTabWidget();
+
+/**
+ * @fn addTab( QWidget *child, const QString &icon, const QString &label )
+ * @brief Add new widget to control.
+ *
+ * @param child Widget control.
+ * @param icon Path to icon.
+ * @param label Text label.
+ */
+ void addTab( QWidget *, const QString &, const QString & );
+
+/**
+ * @fn removePage( QWidget *widget )
+ * @brief Remove widget from control. Does not delete widget.
+ *
+ * @param widget Widget control to be removed.
+ */
+ /* ### Page vs. Tab.. yes the widget is a Page but then is addTab wrong -zecke */
+ void removePage( QWidget * );
+
+/**
+ * @fn changeTab( QWidget *widget, const QString &icon, const QString &label )
+ * @brief Change text and/or icon for existing tab
+ *
+ * @param child Widget control.
+ * @param icon Path to icon.
+ * @param label Text label.
+ */
+ void changeTab( QWidget *, const QString &, const QString & );
+
+/**
+ * @fn tabStyle()const
+ * @brief Returns current widget selection control style.
+ */
+ TabStyle tabStyle() const;
+
+/**
+ * @fn setTabStyle( TabStyle s )
+ * @brief Set the current widget selection control style.
+ *
+ * @param s New style to be used.
+ */
+ void setTabStyle( TabStyle );
+
+/**
+ * @fn tabPosition()const
+ * @brief Returns current widget selection control position.
+ */
+ TabPosition tabPosition() const;
+
+/**
+ * @fn setTabPosition( TabPosition p )
+ * @brief Set the current widget selection control position.
+ *
+ * @param p New position of widget selection control.
+ */
+ void setTabPosition( TabPosition );
+
+/**
+ * @fn setCurrentTab( QWidget *childwidget )
+ * @brief Selects and brings to top the desired widget by using widget pointer.
+ *
+ * @param childwidget Widget to select.
+ */
+ void setCurrentTab( QWidget * );
+
+/**
+ * @fn setCurrentTab( const QString &tabname )
+ * @brief Selects and brings to top the desired widget, by using label.
+ *
+ * @param tabname Text label for widget to select.
+ */
+ void setCurrentTab( const QString & );
+
+/**
+ * @fn setCurrentTab( int )
+ * @brief Selects and brings to top the desired widget, by using id.
+ *
+ * @param tab id for widget to select.
+ */
+ void setCurrentTab(int);
+
+/**
+ * @fn sizeHint()const
+ * @brief Reimplemented for internal purposes.
+ */
+ QSize sizeHint() const;
+
+/**
+ * @fn currentTab( )
+ * @brief returns current tab id.
+ */
+ // ### make const
+ int currentTab()/* const */;
+/**
+ * @brief returns the current page of the active tab
+ *
+ * @since 1.2
+ */
+ QWidget* currentWidget()const;
+
+protected:
+
+/**
+ * @fn resizeEvent( QResizeEvent * )
+ * @brief Reimplemented for internal purposes.
+ */
+ void resizeEvent( QResizeEvent * );
+
+private:
+ OTabInfoList tabs;
+ OTabInfo *currTab;
+
+ TabStyle tabBarStyle;
+ TabPosition tabBarPosition;
+
+ QWidgetStack *tabBarStack;
+ OTabBar *tabBar;
+ QComboBox *tabList;
+
+ QWidgetStack *widgetStack;
+ class Private;
+ Private* d;
+
+/**
+ * @fn loadSmooth( const QString &name )
+ * @brief Loads icon for widget.
+ *
+ * @param name Name of icon image file.
+ */
+ QPixmap loadSmooth( const QString & );
+
+/**
+ * @fn selectTab( OTabInfo *tab )
+ * @brief Internal function to select desired widget.
+ *
+ * @param tab Pointer to data for widget.
+ */
+ void selectTab( OTabInfo * );
+
+/**
+ * @fn setUpLayout()
+ * @brief Internal function to adjust layout.
+ */
+ void setUpLayout();
+
+
+signals:
+/**
+ * @fn currentChanged( QWidget *widget )
+ * @brief This signal is emitted whenever the widget has changed.
+ *
+ * @param widget Pointer to new current widget.
+ */
+ void currentChanged( QWidget * );
+
+private slots:
+
+/**
+ * @fn slotTabBarSelected( int id )
+ * @brief Slot which is called when a tab is selected.
+ *
+ * @param id ID of widget selected.
+ */
+ void slotTabBarSelected( int );
+
+/**
+ * @fn slotTabListSelected( int index )
+ * @brief Slot which is called when a drop down selection is made.
+ *
+ * @param id Index of widget selected.
+ */
+ void slotTabListSelected( int );
+};
+
+#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 @@
+/*
+                This file is part of the Opie Project
+ Copyright (c) 2002 L. Potter <ljp@llornkcor.com>
+ Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = General Public License along with
+    --        :-=` this; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include <qpe/config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "oticker.h"
+
+OTicker::OTicker( QWidget* parent )
+ : QLabel( parent ) {
+ // : QFrame( parent ) {
+ setTextFormat(Qt::RichText);
+ Config cfg("qpe");
+ cfg.setGroup("Appearance");
+ backgroundcolor = QColor( cfg.readEntry( "Background", "#E5E1D5" ) );
+ foregroundcolor= Qt::black;
+ updateTimerTime = 50;
+ scrollLength = 1;
+}
+
+OTicker::~OTicker() {
+}
+
+void OTicker::setBackgroundColor(const QColor& backcolor) {
+ backgroundcolor = backcolor;
+ update();
+}
+
+void OTicker::setForegroundColor(const QColor& backcolor) {
+ foregroundcolor = backcolor;
+ update();
+}
+
+void OTicker::setFrame(int frameStyle) {
+ setFrameStyle( frameStyle/*WinPanel | Sunken */);
+ update();
+}
+
+void OTicker::setText( const QString& text ) {
+ pos = 0; // reset it everytime the text is changed
+ scrollText = text;
+qDebug(scrollText);
+
+ int pixelLen = 0;
+ bool bigger = false;
+ int contWidth = contentsRect().width();
+ int contHeight = contentsRect().height();
+ int pixelTextLen = fontMetrics().width( text );
+ printf("<<<<<<<height %d, width %d, text width %d %d\n", contHeight, contWidth, pixelTextLen, scrollText.length());
+ if( pixelTextLen < contWidth)
+ {
+ pixelLen = contWidth;
+ }
+ else
+ {
+ bigger = true;
+ pixelLen = pixelTextLen;
+ }
+ QPixmap pm( pixelLen, contHeight);
+// pm.fill( QColor( 167, 212, 167 ));
+
+ pm.fill(backgroundcolor);
+ QPainter pmp( &pm );
+ pmp.setPen(foregroundcolor );
+ pmp.drawText( 0, 0, pixelTextLen, contHeight, AlignVCenter, scrollText );
+ pmp.end();
+ scrollTextPixmap = pm;
+
+ killTimers();
+ // qDebug("Scrollupdate %d", updateTimerTime);
+ if ( bigger /*pixelTextLen > contWidth*/ )
+ startTimer( updateTimerTime);
+ update();
+}
+
+
+void OTicker::timerEvent( QTimerEvent * ) {
+ pos = ( pos <= 0 ) ? scrollTextPixmap.width() : pos - scrollLength;//1;
+ repaint( FALSE );
+}
+
+void OTicker::drawContents( QPainter *p ) {
+ int pixelLen = scrollTextPixmap.width();
+ p->drawPixmap( pos, contentsRect().y(), scrollTextPixmap );
+ if ( pixelLen > contentsRect().width() ) // Scrolling
+ p->drawPixmap( pos - pixelLen, contentsRect().y(), scrollTextPixmap );
+}
+
+void OTicker::mouseReleaseEvent( QMouseEvent * ) {
+// qDebug("<<<<<<<>>>>>>>>>");
+ emit mousePressed();
+}
+
+void OTicker::setUpdateTime(int time) {
+ updateTimerTime=time;
+}
+
+void OTicker::setScrollLength(int len) {
+scrollLength=len;
+}
+
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 @@
+/*
+                This file is part of the Opie Project
+ Copyright (c) 2002 L. Potter <ljp@llornkcor.com>
+ Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = General Public License along with
+    --        :-=` this; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef OTICKER_H
+#define OTICKER_H
+
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include <qpixmap.h>
+#include <qstring.h>
+#include <qslider.h>
+#include <qlabel.h>
+#include <qframe.h>
+#include <qcolor.h>
+
+/**
+ * @class OTicker
+ * @brief The OTicker class provides a QLabel widget that scroll its contents
+ *
+ */
+class OTicker : public QLabel {
+ Q_OBJECT
+
+public:
+
+/*!
+ * @fn OTicker( QWidget* parent = 0 )
+ * @brief Object constructor.
+ *
+ * @param parent Pointer to parent of this control.
+
+ * Constructs a new OTicker control with parent
+ */
+ OTicker( QWidget* parent=0 );
+/*!
+ * @fn ~OTicker()
+ * @brief Object destructor.
+ */
+ ~OTicker();
+/*!
+ * @fn setText(const QString& )
+ * @brief sets text to be displayed
+ * @param text QString text to be displayed.
+ *
+ */
+ void setText( const QString& text ) ;
+/*!
+ * @fn setBackgroundColor(const QColor& color)
+ * @brief sets color of the ticker's background
+ * @param color QColor color to be set.
+ *
+ */
+ void setBackgroundColor(const QColor& color);
+/*!
+ * @fn setForegroundColor(const QColor& color)
+ * @brief sets color of text
+ * @param color QColor color of text
+ *
+ */
+ void setForegroundColor(const QColor& color);
+/*!
+ * @fn setFrame(int style)
+ * @brief sets frame style
+ * @param style int Frame style to be see. See Qt::WidgetFlags.
+ *
+ */
+ void setFrame(int style);
+/*!
+ * @fn setUpdateTime(int timeout)
+ * @brief sets time of update
+ * @param timeout int time in milliseconds between updates.
+ *
+ */
+ void setUpdateTime(int timeout);
+/*!
+ * @fn setScrollLength(int length)
+ * @brief sets amount of scrolling default is 1
+ * @param length int scroll length.
+ *
+ */
+ void setScrollLength(int length);
+signals:
+/*!
+ * @fn mousePressed()
+ * @brief signal mouse press event
+ *
+ */
+ void mousePressed();
+protected:
+/*!
+ * @fn timerEvent( QTimerEvent * e)
+ * @brief timer timeout event
+ * @param e QEvent see QEvent.
+ *
+ */
+ void timerEvent( QTimerEvent * e);
+/*!
+ * @fn drawContents( QPainter *p )
+ * @brief draws widget contents
+ * @param p QPainter. see QPainter
+ *
+ */
+ void drawContents( QPainter *p );
+/*!
+ * @fn mouseReleaseEvent( QMouseEvent *e)
+ * @brief mouse release event
+ * @param e QMouseEvent. see QMouseEvent.
+ *
+ */
+ void mouseReleaseEvent( QMouseEvent *e);
+private:
+ QColor backgroundcolor, foregroundcolor;
+ QString scrollText;
+ QPixmap scrollTextPixmap;
+ int pos, updateTimerTime, scrollLength;
+};
+
+#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 @@
+#include "otimepicker.h"
+
+#include <qlayout.h>
+#include <stdio.h>
+#include <qlineedit.h>
+
+
+/**
+ * Constructs the widget
+ * @param parent The parent of the OTimePicker
+ * @param name The name of the object
+ * @param fl Window Flags
+ */
+OTimePicker::OTimePicker(QWidget* parent, const char* name,
+ WFlags fl) :
+ QWidget(parent,name,fl)
+{
+
+ QVBoxLayout *vbox=new QVBoxLayout(this);
+
+ OClickableLabel *r;
+ QString s;
+
+ // Hour Row
+ QWidget *row=new QWidget(this);
+ QHBoxLayout *l=new QHBoxLayout(row);
+ vbox->addWidget(row);
+
+
+ for (int i=0; i<24; i++) {
+ r=new OClickableLabel(row);
+ hourLst.append(r);
+ s.sprintf("%.2d",i);
+ r->setText(s);
+ r->setToggleButton(true);
+ r->setAlignment(AlignHCenter | AlignVCenter);
+ l->addWidget(r);
+ connect(r, SIGNAL(toggled(bool)),
+ this, SLOT(slotHour(bool)));
+
+ if (i==11) { // Second row
+ row=new QWidget(this);
+ l=new QHBoxLayout(row);
+ vbox->addWidget(row);
+ }
+ }
+
+ // Minute Row
+ row=new QWidget(this);
+ l=new QHBoxLayout(row);
+ vbox->addWidget(row);
+
+ for (int i=0; i<60; i+=5) {
+ r=new OClickableLabel(row);
+ minuteLst.append(r);
+ s.sprintf("%.2d",i);
+ r->setText(s);
+ r->setToggleButton(true);
+ r->setAlignment(AlignHCenter | AlignVCenter);
+ l->addWidget(r);
+ connect(r, SIGNAL(toggled(bool)),
+ this, SLOT(slotMinute(bool)));
+ }
+}
+
+/**
+ * This method return the current time
+ * @return the time
+ */
+QTime OTimePicker::time()const {
+ return tm;
+}
+
+void OTimePicker::slotHour(bool b) {
+
+ OClickableLabel *r = (OClickableLabel *) sender();
+
+ if (b) {
+ QValueListIterator<OClickableLabel *> it;
+ for (it=hourLst.begin(); it!=hourLst.end(); it++) {
+ if (*it != r) (*it)->setOn(false);
+ else tm.setHMS((*it)->text().toInt(), tm.minute(), 0);
+ }
+ emit timeChanged(tm);
+ } else {
+ r->setOn(true);
+ }
+
+}
+
+void OTimePicker::slotMinute(bool b) {
+
+ OClickableLabel *r = (OClickableLabel *) sender();
+
+ if (b) {
+ QValueListIterator<OClickableLabel *> it;
+ for (it=minuteLst.begin(); it!=minuteLst.end(); it++) {
+ if (*it != r) (*it)->setOn(false);
+ else tm.setHMS(tm.hour(),(*it)->text().toInt(), 0);
+ }
+ emit timeChanged(tm);
+ } else {
+ r->setOn(true);
+ }
+
+}
+
+/**
+ * Method to set the time. No signal gets emitted during this method call
+ * Minutes must be within 5 minutes step starting at 0 ( 0,5,10,15,20... )
+ * @param t The time to be set
+ */
+void OTimePicker::setTime( const QTime& t) {
+ setTime( t.hour(), t.minute() );
+}
+
+/**
+ * Method to set the time. No signal gets emitted during this method call
+ * @param h The hour
+ * @param m The minute. Minutes need to set by 5 minute steps
+ */
+void OTimePicker::setTime( int h, int m ) {
+ setHour(h);
+ setMinute(m);
+}
+
+/*
+ * FIXME round minutes to the 5 minute arrangement -zecke
+ */
+/**
+ * Method to set the minutes
+ * @param m minutes
+ */
+void OTimePicker::setMinute(int m) {
+
+ QString minute;
+ minute.sprintf("%.2d",m);
+
+ QValueListIterator<OClickableLabel *> it;
+ for (it=minuteLst.begin(); it!=minuteLst.end(); it++) {
+ if ((*it)->text() == minute) (*it)->setOn(true);
+ else (*it)->setOn(false);
+ }
+
+ tm.setHMS(tm.hour(),m,0);
+}
+
+/**
+ * Method to set the hour
+ */
+void OTimePicker::setHour(int h) {
+
+ QString hour;
+ hour.sprintf("%.2d",h);
+
+ QValueListIterator<OClickableLabel *> it;
+ for (it=hourLst.begin(); it!=hourLst.end(); it++) {
+ if ((*it)->text() == hour) (*it)->setOn(true);
+ else (*it)->setOn(false);
+ }
+ tm.setHMS(h,tm.minute(),0);
+}
+
+
+/**
+ * This is a modal Dialog.
+ *
+ * @param parent The parent widget
+ * @param name The name of the object
+ * @param fl Possible window flags
+ */
+OTimePickerDialog::OTimePickerDialog ( QWidget* parent, const char* name, WFlags fl )
+ : OTimePickerDialogBase (parent , name, true , fl)
+{
+
+ connect ( m_timePicker, SIGNAL( timeChanged(const QTime&) ),
+ this, SLOT( setTime(const QTime&) ) );
+ connect ( minuteField, SIGNAL( textChanged(const QString&) ),
+ this, SLOT ( setMinute(const QString&) ) );
+ connect ( hourField, SIGNAL( textChanged(const QString&) ),
+ this, SLOT ( setHour(const QString&) ) );
+
+}
+
+/**
+ * @return the time
+ */
+QTime OTimePickerDialog::time()const
+{
+ return m_time;
+}
+
+/**
+ * Set the time to time
+ * @param time The time to be set
+ */
+void OTimePickerDialog::setTime( const QTime& time )
+{
+ m_time = time;
+
+ m_timePicker->setHour ( time.hour() );
+ m_timePicker->setMinute( time.minute() );
+
+ // Set Textfields
+ if ( time.hour() < 10 )
+ hourField->setText( "0" + QString::number( time.hour() ) );
+ else
+ hourField->setText( QString::number( time.hour() ) );
+
+ if ( time.minute() < 10 )
+ minuteField->setText( "0" + QString::number( time.minute() ) );
+ else
+ minuteField->setText( QString::number( time.minute() ) );
+
+}
+
+/**
+ * This method takes the current minute and tries to set hour
+ * to hour. This succeeds if the resulting date is valid
+ * @param hour The hour as a string
+ */
+void OTimePickerDialog::setHour ( const QString& hour )
+{
+ if ( QTime::isValid ( hour.toInt(), m_time.minute() , 00 ) ){
+ m_time.setHMS ( hour.toInt(), m_time.minute() , 00 );
+ setTime ( m_time );
+ }
+
+}
+
+/**
+ * Method to set a new minute. It tries to convert the string to int and
+ * if the resulting date is valid a new date is set.
+ * @see setHour
+ */
+void OTimePickerDialog::setMinute ( const QString& minute )
+{
+ if ( QTime::isValid ( m_time.hour(), minute.toInt(), 00 ) ){
+ m_time.setHMS ( m_time.hour(), minute.toInt(), 00 );
+ setTime ( m_time );
+ }
+}
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 @@
+#ifndef OTIMEPICKER_H
+#define OTIMEPICKER_H
+
+#include <qwidget.h>
+#include <qvaluelist.h>
+#include <qdatetime.h>
+#include <qdialog.h>
+
+#include <opie/oclickablelabel.h>
+#include "otimepickerbase.h"
+
+/**
+ * A class to pick time. It uses clickable labels
+ * internally to allow a quick selection of a time.
+ * A time can be selected by two clicks of a user
+ *
+ * @short A widget to quickly pick a QTime
+ * @version 1.0
+ * @see QWidget
+ * @see QTime
+ * @author Hakan Ardo, Stefan Eilers
+ */
+class OTimePicker: public QWidget {
+ Q_OBJECT
+
+ public:
+ OTimePicker(QWidget* parent = 0, const char* name = 0,
+ WFlags fl = 0);
+
+ public slots:
+ void setHour(int h);
+ void setMinute(int m);
+ void setTime( const QTime& );
+ void setTime( int h, int m );
+
+ public:
+ QTime time()const;
+
+ private:
+ QValueList<OClickableLabel *> hourLst;
+ QValueList<OClickableLabel *> minuteLst;
+ QTime tm;
+ struct Private;
+ Private *d;
+
+ private slots:
+ void slotHour(bool b);
+ void slotMinute(bool b);
+
+ signals:
+ /**
+ * gets emitted when the time got changed by the user
+ */
+ void timeChanged(const QTime &);
+};
+
+/**
+ *
+ * @short A small dialog to pick a time
+ * @version 1.0
+ * @author Stefan Eilers
+ */
+
+class OTimePickerDialog: public OTimePickerDialogBase {
+ Q_OBJECT
+
+ public:
+ OTimePickerDialog ( QWidget* parent = 0, const char* name = NULL, WFlags fl = 0 );
+ /**
+ * @todo make it non line! See KDE guide for BC
+ */
+ ~OTimePickerDialog() { };
+
+ QTime time()const;
+
+ public slots:
+ void setTime( const QTime& time );
+ void setHour( const QString& hour );
+ void setMinute( const QString& minute );
+
+ private:
+ QTime m_time;
+ class Private;
+ Private* d;
+};
+#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 @@
+<!DOCTYPE UI><UI>
+<class>OTimePickerDialogBase</class>
+<widget>
+ <class>QDialog</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>OTimePickerDialogBase</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>210</width>
+ <height>137</height>
+ </rect>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>1</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>caption</name>
+ <string>OTimePickerDialogBase</string>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>5</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>4</number>
+ </property>
+ <widget>
+ <class>QFrame</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Frame10</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>7</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>frameShape</name>
+ <enum>NoFrame</enum>
+ </property>
+ <property stdset="1">
+ <name>frameShadow</name>
+ <enum>Raised</enum>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>2</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer4</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Horizontal</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>MinimumExpanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget>
+ <class>QFrame</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Frame4</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>4</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>frameShape</name>
+ <enum>Box</enum>
+ </property>
+ <property stdset="1">
+ <name>frameShadow</name>
+ <enum>Sunken</enum>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>4</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Time:</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QLineEdit</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>hourField</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>0</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>alignment</name>
+ <set>AlignHCenter</set>
+ </property>
+ <property>
+ <name>hAlign</name>
+ </property>
+ </widget>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property stdset="1">
+ <name>font</name>
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>:</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QLineEdit</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>minuteField</cstring>
+ </property>
+ <property stdset="1">
+ <name>alignment</name>
+ <set>AlignHCenter</set>
+ </property>
+ <property>
+ <name>hAlign</name>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer5</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Horizontal</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>MinimumExpanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget>
+ <class>QGroupBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>title</name>
+ <string>Pick Time:</string>
+ </property>
+ <grid>
+ <property stdset="1">
+ <name>margin</name>
+ <number>11</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget row="0" column="0" >
+ <class>OTimePicker</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>m_timePicker</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ </sizepolicy>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>OTimePicker</class>
+ <header location="local">otimepicker.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>7</hordata>
+ <verdata>1</verdata>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image>
+ <name>image0</name>
+ <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1ddec44f503c0ae2a154410f53d0ed20e2bf6bdb656dd6861dd23d9a66591b0587fd1654235ebded6f0edcd53e419d87ae7b1f4f9b8f906d0bfe012317426a70b07bdc2f3ec77f8ed6b89559061a0343d06a124cc105596482585094bc0ae599b04646c9018926491b2205e140c485cace25755c175d0a967b622ff900b8cc9c7d29af594ea722d589167f813aa852ba07d94b9dce296e883fe7bb163f23896753</data>
+ </image>
+</images>
+</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 @@
+/* This file is part of the OPIE libraries
+ Copyright (C) 2003 Maximilian Reiss (harlekin@handhelds.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <qlayout.h>
+#include <qpe/qpeapplication.h>
+#include <qpainter.h>
+
+#include "owait.h"
+
+#include <qpe/resource.h>
+
+static int frame = 0;
+
+/**
+ * This will construct a modal dialog.
+ *
+ * The default timer length is 10.
+ *
+ * @param parent The parent of the widget
+ * @param msg The name of the object
+ * @param dispIcon Display Icon?
+ */
+OWait::OWait(QWidget *parent, const char* msg, bool dispIcon )
+ :QDialog(parent, msg, TRUE,WStyle_Customize) {
+
+
+ QHBoxLayout *hbox = new QHBoxLayout( this );
+
+ m_lb = new QLabel( this );
+ m_lb->setBackgroundMode ( NoBackground );
+
+ hbox->addWidget( m_lb );
+ hbox->activate();
+
+ m_pix = Resource::loadPixmap( "BigBusy" );
+ m_aniSize = m_pix.height();
+ resize( m_aniSize, m_aniSize );
+
+ m_timerLength = 10;
+
+ m_waitTimer = new QTimer( this );
+ connect( m_waitTimer, SIGNAL( timeout() ), this, SLOT( hide() ) );
+}
+
+void OWait::timerEvent( QTimerEvent * ) {
+ frame = (++frame) % 4;
+ repaint();
+}
+
+void OWait::paintEvent( QPaintEvent * ) {
+ QPainter p( m_lb );
+ p.drawPixmap( 0, 0, m_pix, m_aniSize * frame, 0, m_aniSize, m_aniSize );
+}
+
+void OWait::show() {
+
+ move( ( ( qApp->desktop()->width() ) / 2 ) - ( m_aniSize / 2 ), ( ( qApp->desktop()->height() ) / 2 ) - ( m_aniSize / 2 ) );
+ startTimer( 300 );
+ m_waitTimer->start( m_timerLength * 1000, true );
+ QDialog::show();
+}
+
+void OWait::hide() {
+ killTimers();
+ m_waitTimer->stop();
+ frame = 0;
+ QDialog::hide();
+}
+
+void OWait::setTimerLength( int length ) {
+ m_timerLength = length;
+}
+
+OWait::~OWait() {
+}
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 @@
+/* This file is part of the OPIE libraries
+ Copyright (C) 2003 Maximilian Reiss (harlekin@handhelds.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+
+
+#ifndef WAITPOPUP_H
+#define WAITPOPUP_H
+
+#include <qdialog.h>
+#include <qpixmap.h>
+#include <qlabel.h>
+#include <qtimer.h>
+
+/**
+ * This class displays a animated waiting icon in the middle of the screen.
+ *
+ * @short modal hour glass dialog
+ * @see QDialog
+ * @author Maximilian Reiß
+ */
+class OWait : public QDialog {
+
+ Q_OBJECT
+
+public:
+ // FIXME Wflags -zecke?
+ OWait(QWidget *parent=0,const char* name=0, bool dispIcon=TRUE);
+ ~OWait();
+
+ /**
+ * reimplemented for control reasons
+ */
+ void show();
+
+ /**
+ * Set the time before the icon will be automaticly hidden
+ * The timer will be started once the widget will be shown.
+ * @param length - time in seconds
+ */
+ void setTimerLength( int length );
+
+ public slots:
+ /**
+ * reimplemented for control reasons
+ */
+ void hide();
+
+ private:
+ void timerEvent( QTimerEvent * ) ;
+ void paintEvent( QPaintEvent * );
+
+ QPixmap m_pix;
+ QLabel *m_lb;
+ QTimer *m_waitTimer;
+ int m_timerLength;
+ int m_aniSize;
+ class Private;
+ Private *d;
+};
+
+#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 @@
+config.in
+moc*
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 @@
+menu "Pim"
+endmenu
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 @@
+TEMPLATE = lib
+CONFIG += qte warn_on release
+HEADERS = ofontmenu.h \
+ tododb.h \
+ todoevent.h todoresource.h \
+ todovcalresource.h xmltree.h \
+ colordialog.h colorpopupmenu.h \
+ oclickablelabel.h oprocctrl.h \
+ oprocess.h odevice.h \
+ otimepicker.h otabwidget.h \
+ otabbar.h otabinfo.h \
+ ofileselector/ofiledialog.h \
+ ofileselector/ofilelistview.h \
+ ofileselector/ofileselector.h \
+ ofileselector/ofileselectoritem.h \
+ ofileselector/ofileview.h \
+ ofileselector/olister.h \
+ ofileselector/olocallister.h \
+ ofileselector/ofileselectormain.h \
+ pim/opimrecord.h \
+ pim/otodo.h \
+ pim/orecordlist.h \
+ pim/opimaccesstemplate.h \
+ pim/opimaccessbackend.h \
+ pim/otodoaccess.h \
+ pim/otodacessbackend.h \
+ pim/ocontact.h \
+ pim/ocontactaccess.h \
+ pim/ocontactaccessbackend.h \
+ pim/ocontactaccessbackend_xml.h \
+ pim/orecord.h
+
+SOURCES = ofontmenu.cc \
+ xmltree.cc \
+ tododb.cpp todoevent.cpp \
+ todovcalresource.cpp colordialog.cpp \
+ colorpopupmenu.cpp oclickablelabel.cpp \
+ oprocctrl.cpp oprocess.cpp \
+ odevice.cpp otimepicker.cpp \
+ otabwidget.cpp otabbar.cpp \
+ ofileselector/ofiledialog.cpp \
+ ofileselector/ofilelistview.cpp \
+ ofileselector/ofileselector.cpp \
+ ofileselector/ofileselectoritem.cpp \
+ ofileselector/ofileview.cpp \
+ ofileselector/olister.cpp \
+ ofileselector/olocallister.cpp \
+ ofileselector/ofileselectormain.cpp \
+ pim/otodo.cpp \
+ pim/opimrecord.cpp \
+ pim/otodoaccess.cpp \
+ pim/otodoaccessbackend.cpp \
+ pim/ocontact.cpp \
+ pim/ocontactaccess.cpp \
+ pim/orecord.cpp
+
+TARGET = opie
+INCLUDEPATH += $(OPIEDIR)/include
+DESTDIR = $(OPIEDIR)/lib$(PROJMAK)
+#VERSION = 1.0.0
+
+INTERFACES = otimepickerbase.ui
+
+include ( $(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 @@
+/*
+ * Class to manage Backends.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later
+ * version.
+ * =====================================================================
+ * ToDo: Use plugins
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2004/11/16 21:46:07 mickeyl
+ * libopie1 goes into unsupported
+ *
+ * Revision 1.9 2003/12/22 10:19:26 eilers
+ * Finishing implementation of sql-backend for datebook. But I have to
+ * port the PIM datebook application to use it, before I could debug the
+ * whole stuff.
+ * Thus, PIM-Database backend is finished, but highly experimental. And some
+ * parts are still generic. For instance, the "queryByExample()" methods are
+ * not (or not fully) implemented. Todo: custom-entries not stored.
+ * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
+ * expression search in the database, which is not supported by sqlite !
+ * Therefore we need either an extended sqlite or a workaround which would
+ * be very slow and memory consuming..
+ *
+ * Revision 1.8 2003/09/22 14:31:16 eilers
+ * Added first experimental incarnation of sql-backend for addressbook.
+ * Some modifications to be able to compile the todo sql-backend.
+ * A lot of changes fill follow...
+ *
+ * Revision 1.7 2003/08/01 12:30:16 eilers
+ * Merging changes from BRANCH_1_0 to HEAD
+ *
+ * Revision 1.6.4.1 2003/06/30 14:34:19 eilers
+ * Patches from Zecke:
+ * Fixing and cleaning up extraMap handling
+ * Adding d_ptr for binary compatibility in the future
+ *
+ * Revision 1.6 2003/04/13 18:07:10 zecke
+ * More API doc
+ * QString -> const QString&
+ * QString = 0l -> QString::null
+ *
+ * Revision 1.5 2003/02/21 23:31:52 zecke
+ * Add XML datebookresource
+ * -clean up todoaccessxml header
+ * -implement some more stuff in the oeven tester
+ * -extend DefaultFactory to not crash and to use datebook
+ *
+ * -reading of OEvents is working nicely.. saving will be added
+ * tomorrow
+ * -fix spelling in ODateBookAcces
+ *
+ * Revision 1.4 2002/10/14 15:55:18 eilers
+ * Redeactivate SQL.. ;)
+ *
+ * Revision 1.3 2002/10/10 17:08:58 zecke
+ * The Cache is finally in place
+ * I tested it with my todolist and it 'works' for 10.000 todos the hits are awesome ;)
+ * 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....
+ * I still have to fully implement read ahead
+ * This change is bic but sc
+ *
+ * Revision 1.2 2002/10/08 09:27:36 eilers
+ * Fixed libopie.pro to include the new pim-API.
+ * The SQL-Stuff is currently deactivated. Otherwise everyone who wants to
+ * compile itself would need to install libsqlite, libopiesql...
+ * Therefore, the backend currently uses XML only..
+ *
+ * Revision 1.1 2002/10/07 17:35:01 eilers
+ * added OBackendFactory for advanced backend access
+ *
+ *
+ * =====================================================================
+ */
+#ifndef OPIE_BACKENDFACTORY_H_
+#define OPIE_BACKENDFACTORY_H_
+
+#include <qstring.h>
+#include <qasciidict.h>
+#include <qpe/config.h>
+
+#include "otodoaccessxml.h"
+#include "ocontactaccessbackend_xml.h"
+#include "odatebookaccessbackend_xml.h"
+
+#ifdef __USE_SQL
+#include "otodoaccesssql.h"
+#include "ocontactaccessbackend_sql.h"
+#include "odatebookaccessbackend_sql.h"
+#endif
+
+class OBackendPrivate;
+
+/**
+ * This class is our factory. It will give us the default implementations
+ * of at least Todolist, Contacts and Datebook. In the future this class will
+ * allow users to switch the backend with ( XML->SQLite ) without the need
+ * to recompile.#
+ * This class as the whole PIM Api is making use of templates
+ *
+ * <pre>
+ * OTodoAccessBackend* backend = OBackEndFactory<OTodoAccessBackend>::Default("todo", QString::null );
+ * backend->load();
+ * </pre>
+ *
+ * @author Stefan Eilers
+ * @version 0.1
+ */
+template<class T>
+class OBackendFactory
+{
+ public:
+ OBackendFactory() {};
+
+ enum BACKENDS {
+ TODO,
+ CONTACT,
+ DATE
+ };
+
+ /**
+ * Returns a backend implementation for backendName
+ * @param backendName the type of the backend
+ * @param appName will be passed on to the backend
+ */
+ static T* Default( const QString backendName, const QString& appName ){
+
+ // __asm__("int3");
+
+ Config config( "pimaccess" );
+ config.setGroup ( backendName );
+ QString backend = config.readEntry( "usebackend" );
+
+ qWarning("Selected backend for %s is: %s", backendName.latin1(), backend.latin1() );
+
+ QAsciiDict<int> dict ( 3 );
+ dict.setAutoDelete ( TRUE );
+
+ dict.insert( "todo", new int (TODO) );
+ dict.insert( "contact", new int (CONTACT) );
+ dict.insert( "datebook", new int(DATE) );
+
+ int *find = dict[ backendName ];
+ if (!find ) return 0;
+
+ switch ( *find ){
+ case TODO:
+#ifdef __USE_SQL
+ if ( backend == "sql" )
+ return (T*) new OTodoAccessBackendSQL("");
+#else
+ if ( backend == "sql" )
+ qWarning ("OBackendFactory:: sql Backend for TODO not implemented! Using XML instead!");
+#endif
+
+ return (T*) new OTodoAccessXML( appName );
+ case CONTACT:
+#ifdef __USE_SQL
+ if ( backend == "sql" )
+ return (T*) new OContactAccessBackend_SQL("");
+#else
+ if ( backend == "sql" )
+ qWarning ("OBackendFactory:: sql Backend for CONTACT not implemented! Using XML instead!");
+#endif
+
+ return (T*) new OContactAccessBackend_XML( appName );
+ case DATE:
+#ifdef __USE_SQL
+ if ( backend == "sql" )
+ return (T*) new ODateBookAccessBackend_SQL("");
+#else
+ if ( backend == "sql" )
+ qWarning("OBackendFactory:: sql Backend for DATEBOOK not implemented! Using XML instead!");
+#endif
+
+ return (T*) new ODateBookAccessBackend_XML( appName );
+ default:
+ return NULL;
+ }
+
+
+ }
+ private:
+ OBackendPrivate* d;
+};
+
+
+#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 @@
+/**********************************************************************
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+** Copyright (C) 2002-2003 by Stefan Eilers (eilers.stefan@epost.de)
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#define QTOPIA_INTERNAL_CONTACT_MRE
+
+#include "ocontact.h"
+#include "opimresolver.h"
+#include "oconversion.h"
+
+#include <qpe/stringutil.h>
+#include <qpe/timestring.h>
+#include <qpe/config.h>
+
+#include <qobject.h>
+#include <qregexp.h>
+#include <qstylesheet.h>
+#include <qfileinfo.h>
+#include <qmap.h>
+
+#include <stdio.h>
+
+/*!
+ \class Contact contact.h
+ \brief The Contact class holds the data of an address book entry.
+
+ This data includes information the name of the person, contact
+ information, and business information such as deparment and job title.
+
+ \ingroup qtopiaemb
+ \ingroup qtopiadesktop
+*/
+
+
+/*!
+ Creates a new, empty contact.
+*/
+OContact::OContact()
+ : OPimRecord(), mMap(), d( 0 )
+{
+}
+
+/*!
+ \internal
+ Creates a new contact. The properties of the contact are
+ set from \a fromMap.
+*/
+OContact::OContact( const QMap<int, QString> &fromMap ) :
+ OPimRecord(), mMap( fromMap ), d( 0 )
+{
+ QString cats = mMap[ Qtopia::AddressCategory ];
+ if ( !cats.isEmpty() )
+ setCategories( idsFromString( cats ) );
+
+ QString uidStr = find( Qtopia::AddressUid );
+
+ if ( uidStr.isEmpty() || (uidStr.toInt() == 0) ){
+ qWarning( "Invalid UID found. Generate new one.." );
+ setUid( uidGen().generate() );
+ }else
+ setUid( uidStr.toInt() );
+
+// if ( !uidStr.isEmpty() )
+// setUid( uidStr.toInt() );
+}
+
+/*!
+ Destroys a contact.
+*/
+OContact::~OContact()
+{
+}
+
+/*! \fn void OContact::setTitle( const QString &str )
+ Sets the title of the contact to \a str.
+*/
+
+/*! \fn void OContact::setFirstName( const QString &str )
+ Sets the first name of the contact to \a str.
+*/
+
+/*! \fn void OContact::setMiddleName( const QString &str )
+ Sets the middle name of the contact to \a str.
+*/
+
+/*! \fn void OContact::setLastName( const QString &str )
+ Sets the last name of the contact to \a str.
+*/
+
+/*! \fn void OContact::setSuffix( const QString &str )
+ Sets the suffix of the contact to \a str.
+*/
+
+/*! \fn void OContact::setFileAs( const QString &str )
+ Sets the contact to filed as \a str.
+*/
+
+/*! \fn void OContact::setDefaultEmail( const QString &str )
+ Sets the default email of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeStreet( const QString &str )
+ Sets the home street address of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeCity( const QString &str )
+ Sets the home city of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeState( const QString &str )
+ Sets the home state of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeZip( const QString &str )
+ Sets the home zip code of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeCountry( const QString &str )
+ Sets the home country of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomePhone( const QString &str )
+ Sets the home phone number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeFax( const QString &str )
+ Sets the home fax number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeMobile( const QString &str )
+ Sets the home mobile phone number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeWebpage( const QString &str )
+ Sets the home webpage of the contact to \a str.
+*/
+
+/*! \fn void OContact::setCompany( const QString &str )
+ Sets the company for contact to \a str.
+*/
+
+/*! \fn void OContact::setJobTitle( const QString &str )
+ Sets the job title of the contact to \a str.
+*/
+
+/*! \fn void OContact::setDepartment( const QString &str )
+ Sets the department for contact to \a str.
+*/
+
+/*! \fn void OContact::setOffice( const QString &str )
+ Sets the office for contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessStreet( const QString &str )
+ Sets the business street address of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessCity( const QString &str )
+ Sets the business city of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessState( const QString &str )
+ Sets the business state of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessZip( const QString &str )
+ Sets the business zip code of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessCountry( const QString &str )
+ Sets the business country of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessPhone( const QString &str )
+ Sets the business phone number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessFax( const QString &str )
+ Sets the business fax number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessMobile( const QString &str )
+ Sets the business mobile phone number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessPager( const QString &str )
+ Sets the business pager number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessWebpage( const QString &str )
+ Sets the business webpage of the contact to \a str.
+*/
+
+/*! \fn void OContact::setProfession( const QString &str )
+ Sets the profession of the contact to \a str.
+*/
+
+/*! \fn void OContact::setAssistant( const QString &str )
+ Sets the assistant of the contact to \a str.
+*/
+
+/*! \fn void OContact::setManager( const QString &str )
+ Sets the manager of the contact to \a str.
+*/
+
+/*! \fn void OContact::setSpouse( const QString &str )
+ Sets the spouse of the contact to \a str.
+*/
+
+/*! \fn void OContact::setGender( const QString &str )
+ Sets the gender of the contact to \a str.
+*/
+
+/*! \fn void OContact::setNickname( const QString &str )
+ Sets the nickname of the contact to \a str.
+*/
+
+/*! \fn void OContact::setNotes( const QString &str )
+ Sets the notes about the contact to \a str.
+*/
+
+/*! \fn QString OContact::title() const
+ Returns the title of the contact.
+*/
+
+/*! \fn QString OContact::firstName() const
+ Returns the first name of the contact.
+*/
+
+/*! \fn QString OContact::middleName() const
+ Returns the middle name of the contact.
+*/
+
+/*! \fn QString OContact::lastName() const
+ Returns the last name of the contact.
+*/
+
+/*! \fn QString OContact::suffix() const
+ Returns the suffix of the contact.
+*/
+
+/*! \fn QString OContact::fileAs() const
+ Returns the string the contact is filed as.
+*/
+
+/*! \fn QString OContact::defaultEmail() const
+ Returns the default email address of the contact.
+*/
+
+/*! \fn QString OContact::emails() const
+ Returns the list of email address for a contact separated by ';'s in a single
+ string.
+*/
+
+/*! \fn QString OContact::homeStreet() const
+ Returns the home street address of the contact.
+*/
+
+/*! \fn QString OContact::homeCity() const
+ Returns the home city of the contact.
+*/
+
+/*! \fn QString OContact::homeState() const
+ Returns the home state of the contact.
+*/
+
+/*! \fn QString OContact::homeZip() const
+ Returns the home zip of the contact.
+*/
+
+/*! \fn QString OContact::homeCountry() const
+ Returns the home country of the contact.
+*/
+
+/*! \fn QString OContact::homePhone() const
+ Returns the home phone number of the contact.
+*/
+
+/*! \fn QString OContact::homeFax() const
+ Returns the home fax number of the contact.
+*/
+
+/*! \fn QString OContact::homeMobile() const
+ Returns the home mobile number of the contact.
+*/
+
+/*! \fn QString OContact::homeWebpage() const
+ Returns the home webpage of the contact.
+*/
+
+/*! \fn QString OContact::company() const
+ Returns the company for the contact.
+*/
+
+/*! \fn QString OContact::department() const
+ Returns the department for the contact.
+*/
+
+/*! \fn QString OContact::office() const
+ Returns the office for the contact.
+*/
+
+/*! \fn QString OContact::jobTitle() const
+ Returns the job title of the contact.
+*/
+
+/*! \fn QString OContact::profession() const
+ Returns the profession of the contact.
+*/
+
+/*! \fn QString OContact::assistant() const
+ Returns the assistant of the contact.
+*/
+
+/*! \fn QString OContact::manager() const
+ Returns the manager of the contact.
+*/
+
+/*! \fn QString OContact::businessStreet() const
+ Returns the business street address of the contact.
+*/
+
+/*! \fn QString OContact::businessCity() const
+ Returns the business city of the contact.
+*/
+
+/*! \fn QString OContact::businessState() const
+ Returns the business state of the contact.
+*/
+
+/*! \fn QString OContact::businessZip() const
+ Returns the business zip of the contact.
+*/
+
+/*! \fn QString OContact::businessCountry() const
+ Returns the business country of the contact.
+*/
+
+/*! \fn QString OContact::businessPhone() const
+ Returns the business phone number of the contact.
+*/
+
+/*! \fn QString OContact::businessFax() const
+ Returns the business fax number of the contact.
+*/
+
+/*! \fn QString OContact::businessMobile() const
+ Returns the business mobile number of the contact.
+*/
+
+/*! \fn QString OContact::businessPager() const
+ Returns the business pager number of the contact.
+*/
+
+/*! \fn QString OContact::businessWebpage() const
+ Returns the business webpage of the contact.
+*/
+
+/*! \fn QString OContact::spouse() const
+ Returns the spouse of the contact.
+*/
+
+/*! \fn QString OContact::gender() const
+ Returns the gender of the contact.
+*/
+
+/*! \fn QString OContact::nickname() const
+ Returns the nickname of the contact.
+*/
+
+/*! \fn QString OContact::children() const
+ Returns the children of the contact.
+*/
+
+/*! \fn QString OContact::notes() const
+ Returns the notes relating to the the contact.
+*/
+
+/*! \fn QString OContact::groups() const
+ \internal
+ Returns the groups for the contact.
+*/
+
+/*! \fn QStringList OContact::groupList() const
+ \internal
+*/
+
+/*! \fn QString OContact::field(int) const
+ \internal
+*/
+
+/*! \fn void OContact::saveJournal( journal_action, const QString & = QString::null )
+ \internal
+*/
+
+/*! \fn void OContact::setUid( int id )
+ \internal
+ Sets the uid for this record to \a id.
+*/
+
+/*! \enum OContact::journal_action
+ \internal
+*/
+
+/*!
+ \internal
+*/
+QMap<int, QString> OContact::toMap() const
+{
+ QMap<int, QString> map = mMap;
+ QString cats = idsToString( categories() );
+ if ( !cats.isEmpty() )
+ map.insert( Qtopia::AddressCategory, cats );
+ return map;
+}
+
+/*!
+ Returns a rich text formatted QString representing the contents the contact.
+*/
+QString OContact::toRichText() const
+{
+ QString text;
+ QString value, comp, state;
+ QString str;
+ bool marker = false;
+
+ Config cfg("qpe");
+ cfg.setGroup("Appearance");
+ int addressformat = cfg.readNumEntry( "AddressFormat", Zip_City_State );
+
+ // name, jobtitle and company
+ if ( !(value = fullName()).isEmpty() )
+ text += "<b><h3><img src=\"addressbook/AddressBook\"> " + Qtopia::escapeString(value) + "</h3></b>";
+
+ if ( !(value = jobTitle()).isEmpty() )
+ text += Qtopia::escapeString(value) + " ";
+
+ comp = company();
+ if ( !(value = department()).isEmpty() ) {
+ text += Qtopia::escapeString(value);
+ if ( comp )
+ text += ", " + Qtopia::escapeString(comp);
+ }else if ( comp )
+ text += "<br>" + Qtopia::escapeString(comp);
+ text += "<br><hr>";
+
+ // defailt email
+ QString defEmail = defaultEmail();
+ if ( !defEmail.isEmpty() ){
+ text += "<b><img src=\"addressbook/email\"> " + QObject::tr("Default Email: ") + "</b>"
+ + Qtopia::escapeString(defEmail);
+ marker = true;
+ }
+
+ // business address
+ if ( !businessStreet().isEmpty() || !businessCity().isEmpty() ||
+ !businessZip().isEmpty() || !businessCountry().isEmpty() ) {
+ text += QObject::tr( "<br><b>Work Address:</b>" );
+ marker = true;
+ }
+
+ if ( !(value = businessStreet()).isEmpty() ){
+ text += "<br>" + Qtopia::escapeString(value);
+ marker = true;
+ }
+
+ switch( addressformat ){
+ case Zip_City_State:{ // Zip_Code City, State
+ state = businessState();
+ if ( !(value = businessZip()).isEmpty() ){
+ text += "<br>" + Qtopia::escapeString(value) + " ";
+ marker = true;
+
+ }
+ if ( !(value = businessCity()).isEmpty() ) {
+ marker = true;
+ if ( businessZip().isEmpty() && !businessStreet().isEmpty() )
+ text += "<br>";
+ text += Qtopia::escapeString(value);
+ if ( state )
+ text += ", " + Qtopia::escapeString(state);
+ } else if ( !state.isEmpty() ){
+ text += "<br>" + Qtopia::escapeString(state);
+ marker = true;
+ }
+ break;
+ }
+ case City_State_Zip:{ // City, State Zip_Code
+ state = businessState();
+ if ( !(value = businessCity()).isEmpty() ) {
+ marker = true;
+ text += "<br>" + Qtopia::escapeString(value);
+ if ( state )
+ text += ", " + Qtopia::escapeString(state);
+ } else if ( !state.isEmpty() ){
+ text += "<br>" + Qtopia::escapeString(state);
+ marker = true;
+ }
+ if ( !(value = businessZip()).isEmpty() ){
+ text += " " + Qtopia::escapeString(value);
+ marker = true;
+ }
+ break;
+ }
+ }
+
+ if ( !(value = businessCountry()).isEmpty() ){
+ text += "<br>" + Qtopia::escapeString(value);
+ marker = true;
+ }
+
+ // rest of Business data
+ str = office();
+ if ( !str.isEmpty() ){
+ text += "<br><b>" + QObject::tr("Office: ") + "</b>"
+ + Qtopia::escapeString(str);
+ marker = true;
+ }
+ str = businessWebpage();
+ if ( !str.isEmpty() ){
+ text += "<br><b><img src=\"addressbook/webpagework\"> " + QObject::tr("Business Web Page: ") + "</b>"
+ + Qtopia::escapeString(str);
+ marker = true;
+ }
+ str = businessPhone();
+ if ( !str.isEmpty() ){
+ text += "<br><b><img src=\"addressbook/phonework\"> " + QObject::tr("Business Phone: ") + "</b>"
+ + Qtopia::escapeString(str);
+ marker = true;
+ }
+ str = businessFax();
+ if ( !str.isEmpty() ){
+ text += "<br><b><img src=\"addressbook/faxwork\"> " + QObject::tr("Business Fax: ") + "</b>"
+ + Qtopia::escapeString(str);
+ marker = true;
+ }
+ str = businessMobile();
+ if ( !str.isEmpty() ){
+ text += "<br><b><img src=\"addressbook/mobilework\"> " + QObject::tr("Business Mobile: ") + "</b>"
+ + Qtopia::escapeString(str);
+ marker = true;
+ }
+ str = businessPager();
+ if ( !str.isEmpty() ){
+ text += "<br><b>" + QObject::tr("Business Pager: ") + "</b>"
+ + Qtopia::escapeString(str);
+ marker = true;
+ }
+
+ // text += "<br>";
+
+ // home address
+ if ( !homeStreet().isEmpty() || !homeCity().isEmpty() ||
+ !homeZip().isEmpty() || !homeCountry().isEmpty() ) {
+ text += QObject::tr( "<br><b>Home Address:</b>" );
+ marker = true;
+ }
+
+ if ( !(value = homeStreet()).isEmpty() ){
+ text += "<br>" + Qtopia::escapeString(value);
+ marker = true;
+ }
+
+ switch( addressformat ){
+ case Zip_City_State:{ // Zip_Code City, State
+ state = homeState();
+ if ( !(value = homeZip()).isEmpty() ){
+ text += "<br>" + Qtopia::escapeString(value) + " ";
+ marker = true;
+ }
+ if ( !(value = homeCity()).isEmpty() ) {
+ marker = true;
+ if ( homeZip().isEmpty() && !homeStreet().isEmpty() )
+ text += "<br>";
+ text += Qtopia::escapeString(value);
+ if ( !state.isEmpty() )
+ text += ", " + Qtopia::escapeString(state);
+ } else if (!state.isEmpty()) {
+ text += "<br>" + Qtopia::escapeString(state);
+ marker = true;
+ }
+ break;
+ }
+ case City_State_Zip:{ // City, State Zip_Code
+ state = homeState();
+ if ( !(value = homeCity()).isEmpty() ) {
+ marker = true;
+ text += "<br>" + Qtopia::escapeString(value);
+ if ( state )
+ text += ", " + Qtopia::escapeString(state);
+ } else if ( !state.isEmpty() ){
+ text += "<br>" + Qtopia::escapeString(state);
+ marker = true;
+ }
+ if ( !(value = homeZip()).isEmpty() ){
+ text += " " + Qtopia::escapeString(value);
+ marker = true;
+ }
+ break;
+ }
+ }
+
+ if ( !(value = homeCountry()).isEmpty() ){
+ text += "<br>" + Qtopia::escapeString(value);
+ marker = true;
+ }
+
+ // rest of Home data
+ str = homeWebpage();
+ if ( !str.isEmpty() ){
+ text += "<br><b><img src=\"addressbook/webpagehome\"> " + QObject::tr("Home Web Page: ") + "</b>"
+ + Qtopia::escapeString(str);
+ marker = true;
+ }
+ str = homePhone();
+ if ( !str.isEmpty() ){
+ text += "<br><b><img src=\"addressbook/phonehome\"> " + QObject::tr("Home Phone: ") + "</b>"
+ + Qtopia::escapeString(str);
+ marker = true;
+ }
+ str = homeFax();
+ if ( !str.isEmpty() ){
+ text += "<br><b><img src=\"addressbook/faxhome\"> " + QObject::tr("Home Fax: ") + "</b>"
+ + Qtopia::escapeString(str);
+ marker = true;
+ }
+ str = homeMobile();
+ if ( !str.isEmpty() ){
+ text += "<br><b><img src=\"addressbook/mobilehome\"> " + QObject::tr("Home Mobile: ") + "</b>"
+ + Qtopia::escapeString(str);
+ marker = true;
+ }
+
+ if ( marker )
+ text += "<br><hr>";
+
+ // the rest...
+ str = emails();
+ if ( !str.isEmpty() && ( str != defEmail ) )
+ text += "<br><b>" + QObject::tr("All Emails: ") + "</b>"
+ + Qtopia::escapeString(str);
+ str = profession();
+ if ( !str.isEmpty() )
+ text += "<br><b>" + QObject::tr("Profession: ") + "</b>"
+ + Qtopia::escapeString(str);
+ str = assistant();
+ if ( !str.isEmpty() )
+ text += "<br><b>" + QObject::tr("Assistant: ") + "</b>"
+ + Qtopia::escapeString(str);
+ str = manager();
+ if ( !str.isEmpty() )
+ text += "<br><b>" + QObject::tr("Manager: ") + "</b>"
+ + Qtopia::escapeString(str);
+ str = gender();
+ if ( !str.isEmpty() && str.toInt() != 0 ) {
+ text += "<br>";
+ if ( str.toInt() == 1 )
+ str = QObject::tr( "Male" );
+ else if ( str.toInt() == 2 )
+ str = QObject::tr( "Female" );
+ text += "<b>" + QObject::tr("Gender: ") + "</b>" + str;
+ }
+ str = spouse();
+ if ( !str.isEmpty() )
+ text += "<br><b>" + QObject::tr("Spouse: ") + "</b>"
+ + Qtopia::escapeString(str);
+ if ( birthday().isValid() ){
+ str = TimeString::numberDateString( birthday() );
+ text += "<br><b>" + QObject::tr("Birthday: ") + "</b>"
+ + Qtopia::escapeString(str);
+ }
+ if ( anniversary().isValid() ){
+ str = TimeString::numberDateString( anniversary() );
+ text += "<br><b>" + QObject::tr("Anniversary: ") + "</b>"
+ + Qtopia::escapeString(str);
+ }
+ str = children();
+ if ( !str.isEmpty() )
+ text += "<br><b>" + QObject::tr("Children: ") + "</b>"
+ + Qtopia::escapeString(str);
+
+ str = nickname();
+ if ( !str.isEmpty() )
+ text += "<br><b>" + QObject::tr("Nickname: ") + "</b>"
+ + Qtopia::escapeString(str);
+
+ // categories
+ if ( categoryNames("Contacts").count() ){
+ text += "<br><b>" + QObject::tr( "Category:") + "</b> ";
+ text += categoryNames("Contacts").join(", ");
+ }
+
+ // notes last
+ if ( !(value = notes()).isEmpty() ) {
+ text += "<br><hr><b>" + QObject::tr( "Notes:") + "</b> ";
+ QRegExp reg("\n");
+
+ //QString tmp = Qtopia::escapeString(value);
+ QString tmp = QStyleSheet::convertFromPlainText(value);
+ //tmp.replace( reg, "<br>" );
+ text += "<br>" + tmp + "<br>";
+ }
+ return text;
+}
+
+/*!
+ \internal
+*/
+void OContact::insert( int key, const QString &v )
+{
+ QString value = v.stripWhiteSpace();
+ if ( value.isEmpty() )
+ mMap.remove( key );
+ else
+ mMap.insert( key, value );
+}
+
+/*!
+ \internal
+*/
+void OContact::replace( int key, const QString & v )
+{
+ QString value = v.stripWhiteSpace();
+ if ( value.isEmpty() )
+ mMap.remove( key );
+ else
+ mMap.replace( key, value );
+}
+
+/*!
+ \internal
+*/
+QString OContact::find( int key ) const
+{
+ return mMap[key];
+}
+
+/*!
+ \internal
+*/
+QString OContact::displayAddress( const QString &street,
+ const QString &city,
+ const QString &state,
+ const QString &zip,
+ const QString &country ) const
+{
+ QString s = street;
+ if ( !street.isEmpty() )
+ s+= "\n";
+ s += city;
+ if ( !city.isEmpty() && !state.isEmpty() )
+ s += ", ";
+ s += state;
+ if ( !state.isEmpty() && !zip.isEmpty() )
+ s += " ";
+ s += zip;
+ if ( !country.isEmpty() && !s.isEmpty() )
+ s += "\n";
+ s += country;
+ return s;
+}
+
+/*!
+ \internal
+*/
+QString OContact::displayBusinessAddress() const
+{
+ return displayAddress( businessStreet(), businessCity(),
+ businessState(), businessZip(),
+ businessCountry() );
+}
+
+/*!
+ \internal
+*/
+QString OContact::displayHomeAddress() const
+{
+ return displayAddress( homeStreet(), homeCity(),
+ homeState(), homeZip(),
+ homeCountry() );
+}
+
+/*!
+ Returns the full name of the contact
+*/
+QString OContact::fullName() const
+{
+ QString title = find( Qtopia::Title );
+ QString firstName = find( Qtopia::FirstName );
+ QString middleName = find( Qtopia::MiddleName );
+ QString lastName = find( Qtopia::LastName );
+ QString suffix = find( Qtopia::Suffix );
+
+ QString name = title;
+ if ( !firstName.isEmpty() ) {
+ if ( !name.isEmpty() )
+ name += " ";
+ name += firstName;
+ }
+ if ( !middleName.isEmpty() ) {
+ if ( !name.isEmpty() )
+ name += " ";
+ name += middleName;
+ }
+ if ( !lastName.isEmpty() ) {
+ if ( !name.isEmpty() )
+ name += " ";
+ name += lastName;
+ }
+ if ( !suffix.isEmpty() ) {
+ if ( !name.isEmpty() )
+ name += " ";
+ name += suffix;
+ }
+ return name.simplifyWhiteSpace();
+}
+
+/*!
+ Returns a list of the names of the children of the contact.
+*/
+QStringList OContact::childrenList() const
+{
+ return QStringList::split( " ", find( Qtopia::Children ) );
+}
+
+/*! \fn void OContact::insertEmail( const QString &email )
+
+ Insert \a email into the email list. Ensures \a email can only be added
+ once. If there is no default email address set, it sets it to the \a email.
+*/
+
+/*! \fn void OContact::removeEmail( const QString &email )
+
+ Removes the \a email from the email list. If the default email was \a email,
+ then the default email address is assigned to the first email in the
+ email list
+*/
+
+/*! \fn void OContact::clearEmails()
+
+ Clears the email list.
+ */
+
+/*! \fn void OContact::insertEmails( const QStringList &emailList )
+
+ Appends the \a emailList to the exiting email list
+ */
+
+/*!
+ Returns a list of email addresses belonging to the contact, including
+ the default email address.
+*/
+QStringList OContact::emailList() const
+{
+ QString emailStr = emails();
+
+ QStringList r;
+ if ( !emailStr.isEmpty() ) {
+ qDebug(" emailstr ");
+ QStringList l = QStringList::split( emailSeparator(), emailStr );
+ for ( QStringList::ConstIterator it = l.begin();it != l.end();++it )
+ r += (*it).simplifyWhiteSpace();
+ }
+
+ return r;
+}
+
+/*!
+ \overload
+
+ Generates the string for the contact to be filed as from the first,
+ middle and last name of the contact.
+*/
+void OContact::setFileAs()
+{
+ QString lastName, firstName, middleName, fileas;
+
+ lastName = find( Qtopia::LastName );
+ firstName = find( Qtopia::FirstName );
+ middleName = find( Qtopia::MiddleName );
+ if ( !lastName.isEmpty() && !firstName.isEmpty()
+ && !middleName.isEmpty() )
+ fileas = lastName + ", " + firstName + " " + middleName;
+ else if ( !lastName.isEmpty() && !firstName.isEmpty() )
+ fileas = lastName + ", " + firstName;
+ else if ( !lastName.isEmpty() || !firstName.isEmpty() ||
+ !middleName.isEmpty() )
+ fileas = firstName + ( firstName.isEmpty() ? "" : " " )
+ + middleName + ( middleName.isEmpty() ? "" : " " )
+ + lastName;
+
+ replace( Qtopia::FileAs, fileas );
+}
+
+/*!
+ \internal
+ Appends the contact information to \a buf.
+*/
+void OContact::save( QString &buf ) const
+{
+ static const QStringList SLFIELDS = fields();
+ // I'm expecting "<Contact " in front of this...
+ for ( QMap<int, QString>::ConstIterator it = mMap.begin();
+ it != mMap.end(); ++it ) {
+ const QString &value = it.data();
+ int key = it.key();
+ if ( !value.isEmpty() ) {
+ if ( key == Qtopia::AddressCategory || key == Qtopia::AddressUid)
+ continue;
+
+ key -= Qtopia::AddressCategory+1;
+ buf += SLFIELDS[key];
+ buf += "=\"" + Qtopia::escapeString(value) + "\" ";
+ }
+ }
+ buf += customToXml();
+ if ( categories().count() > 0 )
+ buf += "Categories=\"" + idsToString( categories() ) + "\" ";
+ buf += "Uid=\"" + QString::number( uid() ) + "\" ";
+ // You need to close this yourself
+}
+
+
+/*!
+ \internal
+ Returns the list of fields belonging to a contact
+ Never change order of this list ! It has to be regarding
+ enum AddressBookFields !!
+*/
+QStringList OContact::fields()
+{
+ QStringList list;
+
+ list.append( "Title" ); // Not Used!
+ list.append( "FirstName" );
+ list.append( "MiddleName" );
+ list.append( "LastName" );
+ list.append( "Suffix" );
+ list.append( "FileAs" );
+
+ list.append( "JobTitle" );
+ list.append( "Department" );
+ list.append( "Company" );
+ list.append( "BusinessPhone" );
+ list.append( "BusinessFax" );
+ list.append( "BusinessMobile" );
+
+ list.append( "DefaultEmail" );
+ list.append( "Emails" );
+
+ list.append( "HomePhone" );
+ list.append( "HomeFax" );
+ list.append( "HomeMobile" );
+
+ list.append( "BusinessStreet" );
+ list.append( "BusinessCity" );
+ list.append( "BusinessState" );
+ list.append( "BusinessZip" );
+ list.append( "BusinessCountry" );
+ list.append( "BusinessPager" );
+ list.append( "BusinessWebPage" );
+
+ list.append( "Office" );
+ list.append( "Profession" );
+ list.append( "Assistant" );
+ list.append( "Manager" );
+
+ list.append( "HomeStreet" );
+ list.append( "HomeCity" );
+ list.append( "HomeState" );
+ list.append( "HomeZip" );
+ list.append( "HomeCountry" );
+ list.append( "HomeWebPage" );
+
+ list.append( "Spouse" );
+ list.append( "Gender" );
+ list.append( "Birthday" );
+ list.append( "Anniversary" );
+ list.append( "Nickname" );
+ list.append( "Children" );
+
+ list.append( "Notes" );
+ list.append( "Groups" );
+
+ return list;
+}
+
+
+/*!
+ Sets the list of email address for contact to those contained in \a str.
+ Email address should be separated by ';'s.
+*/
+void OContact::setEmails( const QString &str )
+{
+ replace( Qtopia::Emails, str );
+ if ( str.isEmpty() )
+ setDefaultEmail( QString::null );
+}
+
+/*!
+ Sets the list of children for the contact to those contained in \a str.
+*/
+void OContact::setChildren( const QString &str )
+{
+ replace( Qtopia::Children, str );
+}
+
+/*!
+ \overload
+ Returns TRUE if the contact matches the regular expression \a regexp.
+ Otherwise returns FALSE.
+*/
+bool OContact::match( const QRegExp &r ) const
+{
+ setLastHitField( -1 );
+ bool match;
+ match = false;
+ QMap<int, QString>::ConstIterator it;
+ for ( it = mMap.begin(); it != mMap.end(); ++it ) {
+ if ( (*it).find( r ) > -1 ) {
+ setLastHitField( it.key() );
+ match = true;
+ break;
+ }
+ }
+ return match;
+}
+
+
+QString OContact::toShortText() const
+{
+ return ( fullName() );
+}
+QString OContact::type() const
+{
+ return QString::fromLatin1( "OContact" );
+}
+
+
+
+class QString OContact::recordField( int pos ) const
+{
+ QStringList SLFIELDS = fields(); // ?? why this ? (se)
+ return SLFIELDS[pos];
+}
+
+// In future releases, we should store birthday and anniversary
+// internally as QDate instead of QString !
+// QString is always too complicate to interprete (DD.MM.YY, DD/MM/YY, MM/DD/YY, etc..)(se)
+
+/*! \fn void OContact::setBirthday( const QDate& date )
+ Sets the birthday for the contact to \a date. If date is null
+ the current stored date will be removed.
+*/
+void OContact::setBirthday( const QDate &v )
+{
+ if ( v.isNull() ){
+ qWarning( "Remove Birthday");
+ replace( Qtopia::Birthday, QString::null );
+ return;
+ }
+
+ if ( v.isValid() )
+ replace( Qtopia::Birthday, OConversion::dateToString( v ) );
+
+}
+
+
+/*! \fn void OContact::setAnniversary( const QDate &date )
+ Sets the anniversary of the contact to \a date. If date is
+ null, the current stored date will be removed.
+*/
+void OContact::setAnniversary( const QDate &v )
+{
+ if ( v.isNull() ){
+ qWarning( "Remove Anniversary");
+ replace( Qtopia::Anniversary, QString::null );
+ return;
+ }
+
+ if ( v.isValid() )
+ replace( Qtopia::Anniversary, OConversion::dateToString( v ) );
+}
+
+/*! \fn QDate OContact::birthday() const
+ Returns the birthday of the contact.
+*/
+QDate OContact::birthday() const
+{
+ QString str = find( Qtopia::Birthday );
+ // qWarning ("Birthday %s", str.latin1() );
+ if ( !str.isEmpty() )
+ return OConversion::dateFromString ( str );
+ else
+ return QDate();
+}
+
+
+/*! \fn QDate OContact::anniversary() const
+ Returns the anniversary of the contact.
+*/
+QDate OContact::anniversary() const
+{
+ QDate empty;
+ QString str = find( Qtopia::Anniversary );
+ // qWarning ("Anniversary %s", str.latin1() );
+ if ( !str.isEmpty() )
+ return OConversion::dateFromString ( str );
+ else
+ return empty;
+}
+
+
+void OContact::insertEmail( const QString &v )
+{
+ //qDebug("insertEmail %s", v.latin1());
+ QString e = v.simplifyWhiteSpace();
+ QString def = defaultEmail();
+
+ // if no default, set it as the default email and don't insert
+ if ( def.isEmpty() ) {
+ setDefaultEmail( e ); // will insert into the list for us
+ return;
+ }
+
+ // otherwise, insert assuming doesn't already exist
+ QString emailsStr = find( Qtopia::Emails );
+ if ( emailsStr.contains( e ))
+ return;
+ if ( !emailsStr.isEmpty() )
+ emailsStr += emailSeparator();
+ emailsStr += e;
+ replace( Qtopia::Emails, emailsStr );
+}
+
+void OContact::removeEmail( const QString &v )
+{
+ QString e = v.simplifyWhiteSpace();
+ QString def = defaultEmail();
+ QString emailsStr = find( Qtopia::Emails );
+ QStringList emails = emailList();
+
+ // otherwise, must first contain it
+ if ( !emailsStr.contains( e ) )
+ return;
+
+ // remove it
+ //qDebug(" removing email from list %s", e.latin1());
+ emails.remove( e );
+ // reset the string
+ emailsStr = emails.join(emailSeparator()); // Sharp's brain dead separator
+ replace( Qtopia::Emails, emailsStr );
+
+ // if default, then replace the default email with the first one
+ if ( def == e ) {
+ //qDebug("removeEmail is default; setting new default");
+ if ( !emails.count() )
+ clearEmails();
+ else // setDefaultEmail will remove e from the list
+ setDefaultEmail( emails.first() );
+ }
+}
+void OContact::clearEmails()
+{
+ mMap.remove( Qtopia::DefaultEmail );
+ mMap.remove( Qtopia::Emails );
+}
+void OContact::setDefaultEmail( const QString &v )
+{
+ QString e = v.simplifyWhiteSpace();
+
+ //qDebug("OContact::setDefaultEmail %s", e.latin1());
+ replace( Qtopia::DefaultEmail, e );
+
+ if ( !e.isEmpty() )
+ insertEmail( e );
+
+}
+
+void OContact::insertEmails( const QStringList &v )
+{
+ for ( QStringList::ConstIterator it = v.begin(); it != v.end(); ++it )
+ insertEmail( *it );
+}
+int OContact::rtti() {
+ return OPimResolver::AddressBook;
+}
+void OContact::setUid( int i )
+{
+ OPimRecord::setUid(i);
+ replace( Qtopia::AddressUid , QString::number(i));
+}
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 @@
+/**********************************************************************
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+** Copyright (C) 2002-2003 by Stefan Eilers (eilers.stefan@epost.de)
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef __OCONTACT_H__
+#define __OCONTACT_H__
+
+#include <opie/opimrecord.h>
+#include <qpe/recordfields.h>
+
+#include <qdatetime.h>
+#include <qstringlist.h>
+
+#if defined(QPC_TEMPLATEDLL)
+// MOC_SKIP_BEGIN
+QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<int, QString>;
+// MOC_SKIP_END
+#endif
+
+class OContactPrivate;
+
+/**
+ * OContact class represents a specialised PIM Record for contacts.
+ * It does store all kind of persopn related information.
+ *
+ * @short Contact Container
+ * @author TT, Stefan Eiler, Holger Freyther
+ */
+class QPC_EXPORT OContact : public OPimRecord
+{
+ friend class DataSet;
+public:
+ OContact();
+ OContact( const QMap<int, QString> &fromMap );
+ virtual ~OContact();
+
+ enum DateFormat{
+ Zip_City_State = 0,
+ City_State_Zip
+ };
+
+ /*
+ * do we need to inline them
+ * if yes do we need to inline them this way?
+ * -zecke
+ */
+ void setTitle( const QString &v ) { replace( Qtopia::Title, v ); }
+ void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); }
+ void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); }
+ void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); }
+ void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); }
+ void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); }
+ void setFileAs();
+
+ // default email address
+ void setDefaultEmail( const QString &v );
+ // inserts email to list and ensure's doesn't already exist
+ void insertEmail( const QString &v );
+ void removeEmail( const QString &v );
+ void clearEmails();
+ void insertEmails( const QStringList &v );
+
+ // home
+ void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); }
+ void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); }
+ void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); }
+ void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); }
+ void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); }
+ void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); }
+ void setHomeFax( const QString &v ) { replace( Qtopia::HomeFax, v ); }
+ void setHomeMobile( const QString &v ) { replace( Qtopia::HomeMobile, v ); }
+ void setHomeWebpage( const QString &v ) { replace( Qtopia::HomeWebPage, v ); }
+
+ // business
+ void setCompany( const QString &v ) { replace( Qtopia::Company, v ); }
+ void setBusinessStreet( const QString &v ) { replace( Qtopia::BusinessStreet, v ); }
+ void setBusinessCity( const QString &v ) { replace( Qtopia::BusinessCity, v ); }
+ void setBusinessState( const QString &v ) { replace( Qtopia::BusinessState, v ); }
+ void setBusinessZip( const QString &v ) { replace( Qtopia::BusinessZip, v ); }
+ void setBusinessCountry( const QString &v ) { replace( Qtopia::BusinessCountry, v ); }
+ void setBusinessWebpage( const QString &v ) { replace( Qtopia::BusinessWebPage, v ); }
+ void setJobTitle( const QString &v ) { replace( Qtopia::JobTitle, v ); }
+ void setDepartment( const QString &v ) { replace( Qtopia::Department, v ); }
+ void setOffice( const QString &v ) { replace( Qtopia::Office, v ); }
+ void setBusinessPhone( const QString &v ) { replace( Qtopia::BusinessPhone, v ); }
+ void setBusinessFax( const QString &v ) { replace( Qtopia::BusinessFax, v ); }
+ void setBusinessMobile( const QString &v ) { replace( Qtopia::BusinessMobile, v ); }
+ void setBusinessPager( const QString &v ) { replace( Qtopia::BusinessPager, v ); }
+ void setProfession( const QString &v ) { replace( Qtopia::Profession, v ); }
+ void setAssistant( const QString &v ) { replace( Qtopia::Assistant, v ); }
+ void setManager( const QString &v ) { replace( Qtopia::Manager, v ); }
+
+ // personal
+ void setSpouse( const QString &v ) { replace( Qtopia::Spouse, v ); }
+ void setGender( const QString &v ) { replace( Qtopia::Gender, v ); }
+ void setBirthday( const QDate &v );
+ void setAnniversary( const QDate &v );
+ void setNickname( const QString &v ) { replace( Qtopia::Nickname, v ); }
+ void setChildren( const QString &v );
+
+ // other
+ void setNotes( const QString &v ) { replace( Qtopia::Notes, v); }
+
+ virtual bool match( const QRegExp &regexp ) const;
+
+// // custom
+// void setCustomField( const QString &key, const QString &v )
+// { replace(Custom- + key, v ); }
+
+ // name
+ QString fullName() const;
+ QString title() const { return find( Qtopia::Title ); }
+ QString firstName() const { return find( Qtopia::FirstName ); }
+ QString middleName() const { return find( Qtopia::MiddleName ); }
+ QString lastName() const { return find( Qtopia::LastName ); }
+ QString suffix() const { return find( Qtopia::Suffix ); }
+ QString fileAs() const { return find( Qtopia::FileAs ); }
+
+ // email
+ QString defaultEmail() const { return find( Qtopia::DefaultEmail ); }
+ QStringList emailList() const;
+
+ // home
+ /*
+ * OPimAddress address(enum Location)const;
+ * would be some how nicer...
+ * -zecke
+ */
+ QString homeStreet() const { return find( Qtopia::HomeStreet ); }
+ QString homeCity() const { return find( Qtopia::HomeCity ); }
+ QString homeState() const { return find( Qtopia::HomeState ); }
+ QString homeZip() const { return find( Qtopia::HomeZip ); }
+ QString homeCountry() const { return find( Qtopia::HomeCountry ); }
+ QString homePhone() const { return find( Qtopia::HomePhone ); }
+ QString homeFax() const { return find( Qtopia::HomeFax ); }
+ QString homeMobile() const { return find( Qtopia::HomeMobile ); }
+ QString homeWebpage() const { return find( Qtopia::HomeWebPage ); }
+ /** Multi line string containing all non-empty address info in the form
+ * Street
+ * City, State Zip
+ * Country
+ */
+ QString displayHomeAddress() const;
+
+ // business
+ QString company() const { return find( Qtopia::Company ); }
+ QString businessStreet() const { return find( Qtopia::BusinessStreet ); }
+ QString businessCity() const { return find( Qtopia::BusinessCity ); }
+ QString businessState() const { return find( Qtopia::BusinessState ); }
+ QString businessZip() const { return find( Qtopia::BusinessZip ); }
+ QString businessCountry() const { return find( Qtopia::BusinessCountry ); }
+ QString businessWebpage() const { return find( Qtopia::BusinessWebPage ); }
+ QString jobTitle() const { return find( Qtopia::JobTitle ); }
+ QString department() const { return find( Qtopia::Department ); }
+ QString office() const { return find( Qtopia::Office ); }
+ QString businessPhone() const { return find( Qtopia::BusinessPhone ); }
+ QString businessFax() const { return find( Qtopia::BusinessFax ); }
+ QString businessMobile() const { return find( Qtopia::BusinessMobile ); }
+ QString businessPager() const { return find( Qtopia::BusinessPager ); }
+ QString profession() const { return find( Qtopia::Profession ); }
+ QString assistant() const { return find( Qtopia::Assistant ); }
+ QString manager() const { return find( Qtopia::Manager ); }
+ /** Multi line string containing all non-empty address info in the form
+ * Street
+ * City, State Zip
+ * Country
+ */
+ QString displayBusinessAddress() const;
+
+ //personal
+ QString spouse() const { return find( Qtopia::Spouse ); }
+ QString gender() const { return find( Qtopia::Gender ); }
+ QDate birthday() const;
+ QDate anniversary() const;
+ QString nickname() const { return find( Qtopia::Nickname ); }
+ QString children() const { return find( Qtopia::Children ); }
+ QStringList childrenList() const;
+
+ // other
+ QString notes() const { return find( Qtopia::Notes ); }
+ QString groups() const { return find( Qtopia::Groups ); }
+ QStringList groupList() const;
+
+ QString toRichText() const;
+ QMap<int, QString> toMap() const;
+ QString field( int key ) const { return find( key ); }
+
+
+ void setUid( int i );
+
+ QString toShortText()const;
+ QString type()const;
+ class QString recordField(int) const;
+
+ // Why private ? (eilers,se)
+ QString emailSeparator() const { return " "; }
+
+ // the emails should be seperated by a comma
+ void setEmails( const QString &v );
+ QString emails() const { return find( Qtopia::Emails ); }
+ static int rtti();
+
+private:
+ // The XML Backend needs some access to the private functions
+ friend class OContactAccessBackend_XML;
+
+ void insert( int key, const QString &value );
+ void replace( int key, const QString &value );
+ QString find( int key ) const;
+ static QStringList fields();
+
+ void save( QString &buf ) const;
+
+ QString displayAddress( const QString &street,
+ const QString &city,
+ const QString &state,
+ const QString &zip,
+ const QString &country ) const;
+
+ QMap<int, QString> mMap;
+ OContactPrivate *d;
+};
+
+
+#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 @@
+/*
+ * Class to manage the Contacts.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * =====================================================================
+ * Info: This class could just work with a change in the header-file
+ * of the Contact class ! Therefore our libopie only compiles
+ * with our version of libqpe
+ * =====================================================================
+ * ToDo: XML-Backend: Automatic reload if something was changed...
+ *
+ *
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2004/11/16 21:46:07 mickeyl
+ * libopie1 goes into unsupported
+ *
+ * Revision 1.9 2004/03/02 12:14:22 alwin
+ * run the optimize_connect script
+ * the whole cvs is tagged with "before_optimize_connect" if there are problems you
+ * can check the diff (but it had compiled and run here)
+ *
+ * Revision 1.8 2003/05/08 13:55:09 tille
+ * search stuff
+ * and match, toRichText & toShortText in oevent
+ *
+ * Revision 1.7 2002/11/13 14:14:51 eilers
+ * Added sorted for Contacts..
+ *
+ * Revision 1.6 2002/11/01 15:10:42 eilers
+ * Added regExp-search in database for all fields in a contact.
+ *
+ * Revision 1.5 2002/10/16 10:52:40 eilers
+ * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
+ *
+ * Revision 1.4 2002/10/14 16:21:54 eilers
+ * Some minor interface updates
+ *
+ * Revision 1.3 2002/10/07 17:34:24 eilers
+ * added OBackendFactory for advanced backend access
+ *
+ * Revision 1.2 2002/10/02 16:18:11 eilers
+ * debugged and seems to work almost perfectly ..
+ *
+ * Revision 1.1 2002/09/27 17:11:44 eilers
+ * Added API for accessing the Contact-Database ! It is compiling, but
+ * please do not expect that anything is working !
+ * I will debug that stuff in the next time ..
+ * Please read README_COMPILE for compiling !
+ *
+ *
+ */
+
+#include "ocontactaccess.h"
+#include "obackendfactory.h"
+
+#include <qasciidict.h>
+#include <qdatetime.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qlist.h>
+#include <qcopchannel_qws.h>
+
+//#include <qpe/qcopenvelope_qws.h>
+#include <qpe/global.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ocontactaccessbackend_xml.h"
+
+
+OContactAccess::OContactAccess ( const QString appname, const QString ,
+ OContactAccessBackend* end, bool autosync ):
+ OPimAccessTemplate<OContact>( end )
+{
+ /* take care of the backend. If there is no one defined, we
+ * will use the XML-Backend as default (until we have a cute SQL-Backend..).
+ */
+ if( end == 0 ) {
+ qWarning ("Using BackendFactory !");
+ end = OBackendFactory<OContactAccessBackend>::Default( "contact", appname );
+ }
+ // Set backend locally and in template
+ m_backEnd = end;
+ OPimAccessTemplate<OContact>::setBackEnd (end);
+
+
+ /* Connect signal of external db change to function */
+ QCopChannel *dbchannel = new QCopChannel( "QPE/PIM", this );
+ connect( dbchannel, SIGNAL(received(const QCString&,const QByteArray&)),
+ this, SLOT(copMessage(const QCString&,const QByteArray&)) );
+ if ( autosync ){
+ QCopChannel *syncchannel = new QCopChannel( "QPE/Sync", this );
+ connect( syncchannel, SIGNAL(received(const QCString&,const QByteArray&)),
+ this, SLOT(copMessage(const QCString&,const QByteArray&)) );
+ }
+
+
+}
+OContactAccess::~OContactAccess ()
+{
+ /* The user may forget to save the changed database, therefore try to
+ * do it for him..
+ */
+ save();
+ // delete m_backEnd; is done by template..
+}
+
+
+bool OContactAccess::save ()
+{
+ /* If the database was changed externally, we could not save the
+ * Data. This will remove added items which is unacceptable !
+ * Therefore: Reload database and merge the data...
+ */
+ if ( OPimAccessTemplate<OContact>::wasChangedExternally() )
+ reload();
+
+ bool status = OPimAccessTemplate<OContact>::save();
+ if ( !status ) return false;
+
+ /* Now tell everyone that new data is available.
+ */
+ QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" );
+
+ return true;
+}
+
+const uint OContactAccess::querySettings()
+{
+ return ( m_backEnd->querySettings() );
+}
+
+bool OContactAccess::hasQuerySettings ( int querySettings ) const
+{
+ return ( m_backEnd->hasQuerySettings ( querySettings ) );
+}
+ORecordList<OContact> OContactAccess::sorted( bool ascending, int sortOrder, int sortFilter, int cat ) const
+{
+ QArray<int> matchingContacts = m_backEnd -> sorted( ascending, sortOrder, sortFilter, cat );
+ return ( ORecordList<OContact>(matchingContacts, this) );
+}
+
+
+bool OContactAccess::wasChangedExternally()const
+{
+ return ( m_backEnd->wasChangedExternally() );
+}
+
+
+void OContactAccess::copMessage( const QCString &msg, const QByteArray & )
+{
+ if ( msg == "addressbookUpdated()" ){
+ qWarning ("OContactAccess: Received addressbokUpdated()");
+ emit signalChanged ( this );
+ } else if ( msg == "flush()" ) {
+ qWarning ("OContactAccess: Received flush()");
+ save ();
+ } else if ( msg == "reload()" ) {
+ qWarning ("OContactAccess: Received reload()");
+ reload ();
+ emit signalChanged ( this );
+ }
+}
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 @@
+/*
+ * Class to manage the Contacts.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later
+ * version.
+ * =====================================================================
+ * ToDo: Define enum for query settings
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2004/11/16 21:46:07 mickeyl
+ * libopie1 goes into unsupported
+ *
+ * Revision 1.10 2003/12/22 10:19:26 eilers
+ * Finishing implementation of sql-backend for datebook. But I have to
+ * port the PIM datebook application to use it, before I could debug the
+ * whole stuff.
+ * Thus, PIM-Database backend is finished, but highly experimental. And some
+ * parts are still generic. For instance, the "queryByExample()" methods are
+ * not (or not fully) implemented. Todo: custom-entries not stored.
+ * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
+ * expression search in the database, which is not supported by sqlite !
+ * Therefore we need either an extended sqlite or a workaround which would
+ * be very slow and memory consuming..
+ *
+ * Revision 1.9 2003/08/01 12:30:16 eilers
+ * Merging changes from BRANCH_1_0 to HEAD
+ *
+ * Revision 1.8.2.1 2003/06/30 14:34:19 eilers
+ * Patches from Zecke:
+ * Fixing and cleaning up extraMap handling
+ * Adding d_ptr for binary compatibility in the future
+ *
+ * Revision 1.8 2003/05/08 13:55:09 tille
+ * search stuff
+ * and match, toRichText & toShortText in oevent
+ *
+ * Revision 1.7 2003/04/13 18:07:10 zecke
+ * More API doc
+ * QString -> const QString&
+ * QString = 0l -> QString::null
+ *
+ * Revision 1.6 2003/01/02 14:27:12 eilers
+ * Improved query by example: Search by date is possible.. First step
+ * for a today plugin for birthdays..
+ *
+ * Revision 1.5 2002/11/13 14:14:51 eilers
+ * Added sorted for Contacts..
+ *
+ * Revision 1.4 2002/11/01 15:10:42 eilers
+ * Added regExp-search in database for all fields in a contact.
+ *
+ * Revision 1.3 2002/10/16 10:52:40 eilers
+ * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
+ *
+ * Revision 1.2 2002/10/14 16:21:54 eilers
+ * Some minor interface updates
+ *
+ * Revision 1.1 2002/09/27 17:11:44 eilers
+ * Added API for accessing the Contact-Database ! It is compiling, but
+ * please do not expect that anything is working !
+ * I will debug that stuff in the next time ..
+ * Please read README_COMPILE for compiling !
+ *
+ * =====================================================================
+ */
+#ifndef _OCONTACTACCESS_H
+#define _OCONTACTACCESS_H
+
+#include <qobject.h>
+
+#include <qpe/qcopenvelope_qws.h>
+
+#include <qvaluelist.h>
+#include <qfileinfo.h>
+
+#include "ocontact.h"
+#include "ocontactaccessbackend.h"
+#include "opimaccesstemplate.h"
+
+/**
+ * Class to access the contacts database.
+ * This is just a frontend for the real database handling which is
+ * done by the backend.
+ * This class is used to access the Contacts on a system. This class as any OPIE PIM
+ * class is backend independent.
+ * @author Stefan Eilers, Holger Freyther
+ * @see OPimAccessTemplate
+ */
+class OContactAccess: public QObject, public OPimAccessTemplate<OContact>
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Create Database with contacts (addressbook).
+ * @param appname Name of application which wants access to the database
+ * (i.e. "todolist")
+ * @param filename The name of the database file. If not set, the default one
+ * is used.
+ * @param backend Pointer to an alternative Backend. If not set, we will use
+ * the default backend.
+ * @param handlesync If <b>true</b> the database stores the current state
+ * automatically if it receives the signals <i>flush()</i> and <i>reload()</i>
+ * which are used before and after synchronisation. If the application wants
+ * to react itself, it should be disabled by setting it to <b>false</b>
+ * @see OContactAccessBackend
+ */
+ OContactAccess (const QString appname, const QString filename = 0l,
+ OContactAccessBackend* backend = 0l, bool handlesync = true);
+ ~OContactAccess ();
+
+ /** Constants for query.
+ * Use this constants to set the query parameters.
+ * Note: <i>query_IgnoreCase</i> just make sense with one of the other attributes !
+ * @see queryByExample()
+ */
+ enum QuerySettings {
+ WildCards = 0x0001,
+ IgnoreCase = 0x0002,
+ RegExp = 0x0004,
+ ExactMatch = 0x0008,
+ MatchOne = 0x0010, // Only one Entry must match
+ DateDiff = 0x0020, // Find all entries from today until given date
+ DateYear = 0x0040, // The year matches
+ DateMonth = 0x0080, // The month matches
+ DateDay = 0x0100, // The day matches
+ };
+
+
+ /** Return all Contacts in a sorted manner.
+ * @param ascending true: Sorted in acending order.
+ * @param sortOrder Currently not implemented. Just defined to stay compatible to otodoaccess
+ * @param sortFilter Currently not implemented. Just defined to stay compatible to otodoaccess
+ * @param cat Currently not implemented. Just defined to stay compatible to otodoaccess
+ */
+ List sorted( bool ascending, int sortOrder, int sortFilter, int cat ) const;
+
+ /** Return all possible settings.
+ * @return All settings provided by the current backend
+ * (i.e.: query_WildCards & query_IgnoreCase)
+ */
+ const uint querySettings();
+
+ /** Check whether settings are correct.
+ * @return <i>true</i> if the given settings are correct and possible.
+ */
+ bool hasQuerySettings ( int querySettings ) const;
+
+ /**
+ * if the resource was changed externally.
+ * You should use the signal instead of polling possible changes !
+ */
+ bool wasChangedExternally()const;
+
+
+ /** Save contacts database.
+ * Save is more a "commit". After calling this function, all changes are public available.
+ * @return true if successful
+ */
+ bool save();
+
+ signals:
+ /* Signal is emitted if the database was changed. Therefore
+ * we may need to reload to stay consistent.
+ * @param which Pointer to the database who created this event. This pointer
+ * is useful if an application has to handle multiple databases at the same time.
+ * @see reload()
+ */
+ void signalChanged ( const OContactAccess *which );
+
+
+ private:
+ // class OContactAccessPrivate;
+ // OContactAccessPrivate* d;
+ OContactAccessBackend *m_backEnd;
+ bool m_loading:1;
+
+ private slots:
+ void copMessage( const QCString &msg, const QByteArray &data );
+
+ private:
+ class Private;
+ Private *d;
+
+};
+#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 @@
+/**
+ * The class responsible for managing a backend.
+ * The implementation of this abstract class contains
+ * the complete database handling.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later
+ * version.
+ * =====================================================================
+ * ToDo: Define enum for query settings
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2004/11/16 21:46:07 mickeyl
+ * libopie1 goes into unsupported
+ *
+ * Revision 1.7 2004/02/19 02:05:37 zecke
+ * Add notes for API fixes and BC stuff
+ *
+ * Revision 1.6 2003/08/01 12:30:16 eilers
+ * Merging changes from BRANCH_1_0 to HEAD
+ *
+ * Revision 1.5.4.1 2003/06/30 14:34:19 eilers
+ * Patches from Zecke:
+ * Fixing and cleaning up extraMap handling
+ * Adding d_ptr for binary compatibility in the future
+ *
+ * Revision 1.5 2003/04/13 18:07:10 zecke
+ * More API doc
+ * QString -> const QString&
+ * QString = 0l -> QString::null
+ *
+ * Revision 1.4 2002/11/13 14:14:51 eilers
+ * Added sorted for Contacts..
+ *
+ * Revision 1.3 2002/11/01 15:10:42 eilers
+ * Added regExp-search in database for all fields in a contact.
+ *
+ * Revision 1.2 2002/10/07 17:34:24 eilers
+ * added OBackendFactory for advanced backend access
+ *
+ * Revision 1.1 2002/09/27 17:11:44 eilers
+ * Added API for accessing the Contact-Database ! It is compiling, but
+ * please do not expect that anything is working !
+ * I will debug that stuff in the next time ..
+ * Please read README_COMPILE for compiling !
+ *
+ * =====================================================================
+ *
+ */
+
+#ifndef _OCONTACTACCESSBACKEND_H_
+#define _OCONTACTACCESSBACKEND_H_
+
+#include "ocontact.h"
+#include "opimaccessbackend.h"
+
+#include <qregexp.h>
+
+/**
+ * This class represents the interface of all Contact Backends.
+ * Derivates of this class will be used to access the contacts.
+ * As implementation currently XML and vCard exist. This class needs to be implemented
+ * if you want to provide your own storage.
+ * In all queries a list of uids is passed on instead of loading the actual record!
+ *
+ * @see OContactAccessBackend_VCard
+ * @see OContactAccessBackend_XML
+ */
+class OContactAccessBackend: public OPimAccessBackend<OContact> {
+ public:
+ /**
+ * @todo make non line in regard to BC guide of KDE
+ */
+ OContactAccessBackend() {}
+ /**
+ * @todo make non inline in regard to the BC guide of KDE
+ */
+ virtual ~OContactAccessBackend() {}
+
+
+ /**
+ * Return if database was changed externally.
+ * This may just make sense on file based databases like a XML-File.
+ * It is used to prevent to overwrite the current database content
+ * if the file was already changed by something else !
+ * If this happens, we have to reload before save our data.
+ * If we use real databases, this should be handled by the database
+ * management system themselve, therefore this function should always return false in
+ * this case. It is not our problem to handle this conflict ...
+ * @return <i>true</i> if the database was changed and if save without reload will
+ * be dangerous. <i>false</i> if the database was not changed or it is save to write
+ * in this situation.
+ */
+ virtual bool wasChangedExternally() = 0;
+
+ virtual QArray<int> matchRegexp( const QRegExp &r ) const = 0;
+
+ /**
+ * Return all possible settings.
+ * @return All settings provided by the current backend
+ * (i.e.: query_WildCards & query_IgnoreCase)
+ */
+ virtual const uint querySettings() = 0;
+
+ /**
+ * Check whether settings are correct.
+ * @return <i>true</i> if the given settings are correct and possible.
+ */
+ virtual bool hasQuerySettings (uint querySettings) const = 0;
+
+ /**
+ * FIXME!!!
+ * Returns a sorted list of records either ascendinf or descending for a giving criteria and category
+ */
+ virtual QArray<int> sorted( bool ascending, int sortOrder, int sortFilter, int cat ) = 0;
+
+
+private:
+ class Private;
+ Private *d;
+};
+#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 @@
+/*
+ * SQL Backend for the OPIE-Contact Database.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * =====================================================================
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2004/11/16 21:46:07 mickeyl
+ * libopie1 goes into unsupported
+ *
+ * Revision 1.5 2004/03/14 13:50:35 alwin
+ * namespace correction
+ *
+ * Revision 1.4 2003/12/22 10:19:26 eilers
+ * Finishing implementation of sql-backend for datebook. But I have to
+ * port the PIM datebook application to use it, before I could debug the
+ * whole stuff.
+ * Thus, PIM-Database backend is finished, but highly experimental. And some
+ * parts are still generic. For instance, the "queryByExample()" methods are
+ * not (or not fully) implemented. Todo: custom-entries not stored.
+ * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
+ * expression search in the database, which is not supported by sqlite !
+ * Therefore we need either an extended sqlite or a workaround which would
+ * be very slow and memory consuming..
+ *
+ * Revision 1.3 2003/12/08 15:18:10 eilers
+ * Committing unfinished sql implementation before merging to libopie2 starts..
+ *
+ * Revision 1.2 2003/09/29 07:44:26 eilers
+ * Improvement of PIM-SQL Databases, but search queries are still limited.
+ * Addressbook: Changed table layout. Now, we just need 1/3 of disk-space.
+ * Todo: Started to add new attributes. Some type conversions missing.
+ *
+ * Revision 1.1 2003/09/22 14:31:16 eilers
+ * Added first experimental incarnation of sql-backend for addressbook.
+ * Some modifications to be able to compile the todo sql-backend.
+ * A lot of changes fill follow...
+ *
+ */
+
+#include "ocontactaccessbackend_sql.h"
+
+#include <qarray.h>
+#include <qdatetime.h>
+#include <qstringlist.h>
+
+#include <qpe/global.h>
+#include <qpe/recordfields.h>
+
+#include <opie/ocontactfields.h>
+#include <opie/oconversion.h>
+#include <opie2/osqldriver.h>
+#include <opie2/osqlresult.h>
+#include <opie2/osqlmanager.h>
+#include <opie2/osqlquery.h>
+
+using namespace Opie::DB;
+
+
+// If defined, we use a horizontal table ( uid, attr1, attr2, attr3, ..., attrn ) instead
+// vertical like "uid, type, value".
+// DON'T DEACTIVATE THIS DEFINE IN PRODUCTIVE ENVIRONMENTS !!
+#define __STORE_HORIZONTAL_
+
+// Distinct loading is not very fast. If I expect that every person has just
+// one (and always one) 'Last Name', I can request all uid's for existing lastnames,
+// which is faster..
+// But this may not be true for all entries, like company contacts..
+// The current AddressBook application handles this problem, but other may not.. (eilers)
+#define __USE_SUPERFAST_LOADQUERY
+
+
+/*
+ * Implementation of used query types
+ * CREATE query
+ * LOAD query
+ * INSERT
+ * REMOVE
+ * CLEAR
+ */
+namespace {
+ /**
+ * CreateQuery for the Todolist Table
+ */
+ class CreateQuery : public OSQLQuery {
+ public:
+ CreateQuery();
+ ~CreateQuery();
+ QString query()const;
+ };
+
+ /**
+ * Clears (delete) a Table
+ */
+ class ClearQuery : public OSQLQuery {
+ public:
+ ClearQuery();
+ ~ClearQuery();
+ QString query()const;
+
+ };
+
+
+ /**
+ * LoadQuery
+ * this one queries for all uids
+ */
+ class LoadQuery : public OSQLQuery {
+ public:
+ LoadQuery();
+ ~LoadQuery();
+ QString query()const;
+ };
+
+ /**
+ * inserts/adds a OContact to the table
+ */
+ class InsertQuery : public OSQLQuery {
+ public:
+ InsertQuery(const OContact& );
+ ~InsertQuery();
+ QString query()const;
+ private:
+ OContact m_contact;
+ };
+
+
+ /**
+ * removes one from the table
+ */
+ class RemoveQuery : public OSQLQuery {
+ public:
+ RemoveQuery(int uid );
+ ~RemoveQuery();
+ QString query()const;
+ private:
+ int m_uid;
+ };
+
+ /**
+ * a find query for noncustom elements
+ */
+ class FindQuery : public OSQLQuery {
+ public:
+ FindQuery(int uid);
+ FindQuery(const QArray<int>& );
+ ~FindQuery();
+ QString query()const;
+ private:
+ QString single()const;
+ QString multi()const;
+ QArray<int> m_uids;
+ int m_uid;
+ };
+
+ /**
+ * a find query for custom elements
+ */
+ class FindCustomQuery : public OSQLQuery {
+ public:
+ FindCustomQuery(int uid);
+ FindCustomQuery(const QArray<int>& );
+ ~FindCustomQuery();
+ QString query()const;
+ private:
+ QString single()const;
+ QString multi()const;
+ QArray<int> m_uids;
+ int m_uid;
+ };
+
+
+
+ // We using three tables to store the information:
+ // 1. addressbook : It contains General information about the contact (non custom)
+ // 2. custom_data : Not official supported entries
+ // All tables are connected by the uid of the contact.
+ // Maybe I should add a table for meta-information ?
+ CreateQuery::CreateQuery() : OSQLQuery() {}
+ CreateQuery::~CreateQuery() {}
+ QString CreateQuery::query()const {
+ QString qu;
+#ifdef __STORE_HORIZONTAL_
+
+ qu += "create table addressbook( uid PRIMARY KEY ";
+
+ QStringList fieldList = OContactFields::untrfields( false );
+ for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
+ qu += QString( ",\"%1\" VARCHAR(10)" ).arg( *it );
+ }
+ qu += " );";
+
+ qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
+
+#else
+
+ qu += "create table addressbook( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id));";
+ qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
+// qu += "create table dates( uid PRIMARY KEY, type, day, month, year, hour, minute, second );";
+
+#endif // __STORE_HORIZONTAL_
+ return qu;
+ }
+
+ ClearQuery::ClearQuery()
+ : OSQLQuery() {}
+ ClearQuery::~ClearQuery() {}
+ QString ClearQuery::query()const {
+ QString qu = "drop table addressbook;";
+ qu += "drop table custom_data;";
+// qu += "drop table dates;";
+ return qu;
+ }
+
+
+ LoadQuery::LoadQuery() : OSQLQuery() {}
+ LoadQuery::~LoadQuery() {}
+ QString LoadQuery::query()const {
+ QString qu;
+#ifdef __STORE_HORIZONTAL_
+ qu += "select uid from addressbook";
+#else
+# ifndef __USE_SUPERFAST_LOADQUERY
+ qu += "select distinct uid from addressbook";
+# else
+ qu += "select uid from addressbook where type = 'Last Name'";
+# endif // __USE_SUPERFAST_LOADQUERY
+#endif // __STORE_HORIZONTAL_
+
+ return qu;
+ }
+
+
+ InsertQuery::InsertQuery( const OContact& contact )
+ : OSQLQuery(), m_contact( contact ) {
+ }
+
+ InsertQuery::~InsertQuery() {
+ }
+
+ /*
+ * converts from a OContact to a query
+ */
+ QString InsertQuery::query()const{
+
+#ifdef __STORE_HORIZONTAL_
+ QString qu;
+ qu += "insert into addressbook VALUES( " +
+ QString::number( m_contact.uid() );
+
+ // Get all information out of the contact-class
+ // Remember: The category is stored in contactMap, too !
+ QMap<int, QString> contactMap = m_contact.toMap();
+
+ QStringList fieldList = OContactFields::untrfields( false );
+ QMap<QString, int> translate = OContactFields::untrFieldsToId();
+ for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
+ // Convert Column-String to Id and get value for this id..
+ // Hmmm.. Maybe not very cute solution..
+ int id = translate[*it];
+ switch ( id ){
+ case Qtopia::Birthday:{
+ // These entries should stored in a special format
+ // year-month-day
+ QDate day = m_contact.birthday();
+ if ( day.isValid() ){
+ qu += QString(",\"%1-%2-%3\"")
+ .arg( day.year() )
+ .arg( day.month() )
+ .arg( day.day() );
+ } else {
+ qu += ",\"\"";
+ }
+ }
+ break;
+ case Qtopia::Anniversary:{
+ // These entries should stored in a special format
+ // year-month-day
+ QDate day = m_contact.anniversary();
+ if ( day.isValid() ){
+ qu += QString(",\"%1-%2-%3\"")
+ .arg( day.year() )
+ .arg( day.month() )
+ .arg( day.day() );
+ } else {
+ qu += ",\"\"";
+ }
+ }
+ break;
+
+ default:
+ qu += QString( ",\"%1\"" ).arg( contactMap[id] );
+ }
+ }
+ qu += " );";
+
+
+#else
+ // Get all information out of the contact-class
+ // Remember: The category is stored in contactMap, too !
+ QMap<int, QString> contactMap = m_contact.toMap();
+
+ QMap<QString, QString> addressbook_db;
+
+ // Get the translation from the ID to the String
+ QMap<int, QString> transMap = OContactFields::idToUntrFields();
+
+ for( QMap<int, QString>::Iterator it = contactMap.begin();
+ it != contactMap.end(); ++it ){
+ switch ( it.key() ){
+ case Qtopia::Birthday:{
+ // These entries should stored in a special format
+ // year-month-day
+ QDate day = m_contact.birthday();
+ addressbook_db.insert( transMap[it.key()],
+ QString("%1-%2-%3")
+ .arg( day.year() )
+ .arg( day.month() )
+ .arg( day.day() ) );
+ }
+ break;
+ case Qtopia::Anniversary:{
+ // These entries should stored in a special format
+ // year-month-day
+ QDate day = m_contact.anniversary();
+ addressbook_db.insert( transMap[it.key()],
+ QString("%1-%2-%3")
+ .arg( day.year() )
+ .arg( day.month() )
+ .arg( day.day() ) );
+ }
+ break;
+ case Qtopia::AddressUid: // Ignore UID
+ break;
+ default: // Translate id to String
+ addressbook_db.insert( transMap[it.key()], it.data() );
+ break;
+ }
+
+ }
+
+ // Now convert this whole stuff into a SQL String, beginning with
+ // the addressbook table..
+ QString qu;
+ // qu += "begin transaction;";
+ int id = 0;
+ for( QMap<QString, QString>::Iterator it = addressbook_db.begin();
+ it != addressbook_db.end(); ++it ){
+ qu += "insert into addressbook VALUES("
+ + QString::number( m_contact.uid() )
+ + ","
+ + QString::number( id++ )
+ + ",'"
+ + it.key() //.latin1()
+ + "',"
+ + "0" // Priority for future enhancements
+ + ",'"
+ + it.data() //.latin1()
+ + "');";
+ }
+
+#endif //__STORE_HORIZONTAL_
+ // Now add custom data..
+#ifdef __STORE_HORIZONTAL_
+ int id = 0;
+#endif
+ id = 0;
+ QMap<QString, QString> customMap = m_contact.toExtraMap();
+ for( QMap<QString, QString>::Iterator it = customMap.begin();
+ it != customMap.end(); ++it ){
+ qu += "insert into custom_data VALUES("
+ + QString::number( m_contact.uid() )
+ + ","
+ + QString::number( id++ )
+ + ",'"
+ + it.key() //.latin1()
+ + "',"
+ + "0" // Priority for future enhancements
+ + ",'"
+ + it.data() //.latin1()
+ + "');";
+ }
+ // qu += "commit;";
+ qWarning("add %s", qu.latin1() );
+ return qu;
+ }
+
+
+ RemoveQuery::RemoveQuery(int uid )
+ : OSQLQuery(), m_uid( uid ) {}
+ RemoveQuery::~RemoveQuery() {}
+ QString RemoveQuery::query()const {
+ QString qu = "DELETE from addressbook where uid = "
+ + QString::number(m_uid) + ";";
+ qu += "DELETE from custom_data where uid = "
+ + QString::number(m_uid) + ";";
+ return qu;
+ }
+
+
+
+
+ FindQuery::FindQuery(int uid)
+ : OSQLQuery(), m_uid( uid ) {
+ }
+ FindQuery::FindQuery(const QArray<int>& ints)
+ : OSQLQuery(), m_uids( ints ){
+ }
+ FindQuery::~FindQuery() {
+ }
+ QString FindQuery::query()const{
+// if ( m_uids.count() == 0 )
+ return single();
+ }
+ /*
+ else
+ return multi();
+ }
+ QString FindQuery::multi()const {
+ QString qu = "select uid, type, value from addressbook where";
+ for (uint i = 0; i < m_uids.count(); i++ ) {
+ qu += " UID = " + QString::number( m_uids[i] ) + " OR";
+ }
+ qu.remove( qu.length()-2, 2 ); // Hmmmm..
+ return qu;
+ }
+ */
+#ifdef __STORE_HORIZONTAL_
+ QString FindQuery::single()const{
+ QString qu = "select *";
+ qu += " from addressbook where uid = " + QString::number(m_uid);
+
+ // qWarning("find query: %s", qu.latin1() );
+ return qu;
+ }
+#else
+ QString FindQuery::single()const{
+ QString qu = "select uid, type, value from addressbook where uid = ";
+ qu += QString::number(m_uid);
+ return qu;
+ }
+#endif
+
+
+ FindCustomQuery::FindCustomQuery(int uid)
+ : OSQLQuery(), m_uid( uid ) {
+ }
+ FindCustomQuery::FindCustomQuery(const QArray<int>& ints)
+ : OSQLQuery(), m_uids( ints ){
+ }
+ FindCustomQuery::~FindCustomQuery() {
+ }
+ QString FindCustomQuery::query()const{
+// if ( m_uids.count() == 0 )
+ return single();
+ }
+ QString FindCustomQuery::single()const{
+ QString qu = "select uid, type, value from custom_data where uid = ";
+ qu += QString::number(m_uid);
+ return qu;
+ }
+
+};
+
+
+/* --------------------------------------------------------------------------- */
+
+OContactAccessBackend_SQL::OContactAccessBackend_SQL ( const QString& /* appname */,
+ const QString& filename ):
+ OContactAccessBackend(), m_changed(false), m_driver( NULL )
+{
+ qWarning("C'tor OContactAccessBackend_SQL starts");
+ QTime t;
+ t.start();
+
+ /* Expecting to access the default filename if nothing else is set */
+ if ( filename.isEmpty() ){
+ m_fileName = Global::applicationFileName( "addressbook","addressbook.db" );
+ } else
+ m_fileName = filename;
+
+ // Get the standart sql-driver from the OSQLManager..
+ OSQLManager man;
+ m_driver = man.standard();
+ m_driver->setUrl( m_fileName );
+
+ load();
+
+ qWarning("C'tor OContactAccessBackend_SQL ends: %d ms", t.elapsed() );
+}
+
+OContactAccessBackend_SQL::~OContactAccessBackend_SQL ()
+{
+ if( m_driver )
+ delete m_driver;
+}
+
+bool OContactAccessBackend_SQL::load ()
+{
+ if (!m_driver->open() )
+ return false;
+
+ // Don't expect that the database exists.
+ // It is save here to create the table, even if it
+ // do exist. ( Is that correct for all databases ?? )
+ CreateQuery creat;
+ OSQLResult res = m_driver->query( &creat );
+
+ update();
+
+ return true;
+
+}
+
+bool OContactAccessBackend_SQL::reload()
+{
+ return load();
+}
+
+bool OContactAccessBackend_SQL::save()
+{
+ return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
+}
+
+
+void OContactAccessBackend_SQL::clear ()
+{
+ ClearQuery cle;
+ OSQLResult res = m_driver->query( &cle );
+
+ reload();
+}
+
+bool OContactAccessBackend_SQL::wasChangedExternally()
+{
+ return false;
+}
+
+QArray<int> OContactAccessBackend_SQL::allRecords() const
+{
+
+ // FIXME: Think about cute handling of changed tables..
+ // Thus, we don't have to call update here...
+ if ( m_changed )
+ ((OContactAccessBackend_SQL*)this)->update();
+
+ return m_uids;
+}
+
+bool OContactAccessBackend_SQL::add ( const OContact &newcontact )
+{
+ InsertQuery ins( newcontact );
+ OSQLResult res = m_driver->query( &ins );
+
+ if ( res.state() == OSQLResult::Failure )
+ return false;
+
+ int c = m_uids.count();
+ m_uids.resize( c+1 );
+ m_uids[c] = newcontact.uid();
+
+ return true;
+}
+
+
+bool OContactAccessBackend_SQL::remove ( int uid )
+{
+ RemoveQuery rem( uid );
+ OSQLResult res = m_driver->query(&rem );
+
+ if ( res.state() == OSQLResult::Failure )
+ return false;
+
+ m_changed = true;
+
+ return true;
+}
+
+bool OContactAccessBackend_SQL::replace ( const OContact &contact )
+{
+ if ( !remove( contact.uid() ) )
+ return false;
+
+ return add( contact );
+}
+
+
+OContact OContactAccessBackend_SQL::find ( int uid ) const
+{
+ qWarning("OContactAccessBackend_SQL::find()");
+ QTime t;
+ t.start();
+
+ OContact retContact( requestNonCustom( uid ) );
+ retContact.setExtraMap( requestCustom( uid ) );
+
+ qWarning("OContactAccessBackend_SQL::find() needed: %d ms", t.elapsed() );
+ return retContact;
+}
+
+
+
+QArray<int> OContactAccessBackend_SQL::queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() )
+{
+ QString qu = "SELECT uid FROM addressbook WHERE";
+
+ QMap<int, QString> queryFields = query.toMap();
+ QStringList fieldList = OContactFields::untrfields( false );
+ QMap<QString, int> translate = OContactFields::untrFieldsToId();
+
+ // Convert every filled field to a SQL-Query
+ bool isAnyFieldSelected = false;
+ for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
+ int id = translate[*it];
+ QString queryStr = queryFields[id];
+ if ( !queryStr.isEmpty() ){
+ isAnyFieldSelected = true;
+ switch( id ){
+ default:
+ // Switching between case sensitive and insensitive...
+ // LIKE is not case sensitive, GLOB is case sensitive
+ // Do exist a better solution to switch this ?
+ if ( settings & OContactAccess::IgnoreCase )
+ qu += "(\"" + *it + "\"" + " LIKE " + "'"
+ + queryStr.replace(QRegExp("\\*"),"%") + "'" + ") AND ";
+ else
+ qu += "(\"" + *it + "\"" + " GLOB " + "'"
+ + queryStr + "'" + ") AND ";
+
+ }
+ }
+ }
+ // Skip trailing "AND"
+ if ( isAnyFieldSelected )
+ qu = qu.left( qu.length() - 4 );
+
+ qWarning( "queryByExample query: %s", qu.latin1() );
+
+ // Execute query and return the received uid's
+ OSQLRawQuery raw( qu );
+ OSQLResult res = m_driver->query( &raw );
+ if ( res.state() != OSQLResult::Success ){
+ QArray<int> empty;
+ return empty;
+ }
+
+ QArray<int> list = extractUids( res );
+
+ return list;
+}
+
+QArray<int> OContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
+{
+ QArray<int> nix(0);
+ return nix;
+}
+
+const uint OContactAccessBackend_SQL::querySettings()
+{
+ return OContactAccess::IgnoreCase
+ || OContactAccess::WildCards;
+}
+
+bool OContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const
+{
+ /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
+ * may be added with any of the other settings. IgnoreCase should never used alone.
+ * Wildcards, RegExp, ExactMatch should never used at the same time...
+ */
+
+ // Step 1: Check whether the given settings are supported by this backend
+ if ( ( querySettings & (
+ OContactAccess::IgnoreCase
+ | OContactAccess::WildCards
+// | OContactAccess::DateDiff
+// | OContactAccess::DateYear
+// | OContactAccess::DateMonth
+// | OContactAccess::DateDay
+// | OContactAccess::RegExp
+// | OContactAccess::ExactMatch
+ ) ) != querySettings )
+ return false;
+
+ // Step 2: Check whether the given combinations are ok..
+
+ // IngoreCase alone is invalid
+ if ( querySettings == OContactAccess::IgnoreCase )
+ return false;
+
+ // WildCards, RegExp and ExactMatch should never used at the same time
+ switch ( querySettings & ~( OContactAccess::IgnoreCase
+ | OContactAccess::DateDiff
+ | OContactAccess::DateYear
+ | OContactAccess::DateMonth
+ | OContactAccess::DateDay
+ )
+ ){
+ case OContactAccess::RegExp:
+ return ( true );
+ case OContactAccess::WildCards:
+ return ( true );
+ case OContactAccess::ExactMatch:
+ return ( true );
+ case 0: // one of the upper removed bits were set..
+ return ( true );
+ default:
+ return ( false );
+ }
+
+}
+
+QArray<int> OContactAccessBackend_SQL::sorted( bool asc, int , int , int )
+{
+ QTime t;
+ t.start();
+
+#ifdef __STORE_HORIZONTAL_
+ QString query = "SELECT uid FROM addressbook ";
+ query += "ORDER BY \"Last Name\" ";
+#else
+ QString query = "SELECT uid FROM addressbook WHERE type = 'Last Name' ";
+ query += "ORDER BY upper( value )";
+#endif
+
+ if ( !asc )
+ query += "DESC";
+
+ // qWarning("sorted query is: %s", query.latin1() );
+
+ OSQLRawQuery raw( query );
+ OSQLResult res = m_driver->query( &raw );
+ if ( res.state() != OSQLResult::Success ){
+ QArray<int> empty;
+ return empty;
+ }
+
+ QArray<int> list = extractUids( res );
+
+ qWarning("sorted needed %d ms!", t.elapsed() );
+ return list;
+}
+
+
+void OContactAccessBackend_SQL::update()
+{
+ qWarning("Update starts");
+ QTime t;
+ t.start();
+
+ // Now load the database set and extract the uid's
+ // which will be held locally
+
+ LoadQuery lo;
+ OSQLResult res = m_driver->query(&lo);
+ if ( res.state() != OSQLResult::Success )
+ return;
+
+ m_uids = extractUids( res );
+
+ m_changed = false;
+
+ qWarning("Update ends %d ms", t.elapsed() );
+}
+
+QArray<int> OContactAccessBackend_SQL::extractUids( OSQLResult& res ) const
+{
+ qWarning("extractUids");
+ QTime t;
+ t.start();
+ OSQLResultItem::ValueList list = res.results();
+ OSQLResultItem::ValueList::Iterator it;
+ QArray<int> ints(list.count() );
+ qWarning(" count = %d", list.count() );
+
+ int i = 0;
+ for (it = list.begin(); it != list.end(); ++it ) {
+ ints[i] = (*it).data("uid").toInt();
+ i++;
+ }
+ qWarning("extractUids ready: count2 = %d needs %d ms", i, t.elapsed() );
+
+ return ints;
+
+}
+
+#ifdef __STORE_HORIZONTAL_
+QMap<int, QString> OContactAccessBackend_SQL::requestNonCustom( int uid ) const
+{
+ QTime t;
+ t.start();
+
+ QMap<int, QString> nonCustomMap;
+
+ int t2needed = 0;
+ int t3needed = 0;
+ QTime t2;
+ t2.start();
+ FindQuery query( uid );
+ OSQLResult res_noncustom = m_driver->query( &query );
+ t2needed = t2.elapsed();
+
+ OSQLResultItem resItem = res_noncustom.first();
+
+ QTime t3;
+ t3.start();
+ // Now loop through all columns
+ QStringList fieldList = OContactFields::untrfields( false );
+ QMap<QString, int> translate = OContactFields::untrFieldsToId();
+ for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
+ // Get data for the selected column and store it with the
+ // corresponding id into the map..
+
+ int id = translate[*it];
+ QString value = resItem.data( (*it) );
+
+ // qWarning("Reading %s... found: %s", (*it).latin1(), value.latin1() );
+
+ switch( id ){
+ case Qtopia::Birthday:
+ case Qtopia::Anniversary:{
+ // Birthday and Anniversary are encoded special ( yyyy-mm-dd )
+ QStringList list = QStringList::split( '-', value );
+ QStringList::Iterator lit = list.begin();
+ int year = (*lit).toInt();
+ int month = (*(++lit)).toInt();
+ int day = (*(++lit)).toInt();
+ if ( ( day != 0 ) && ( month != 0 ) && ( year != 0 ) ){
+ QDate date( year, month, day );
+ nonCustomMap.insert( id, OConversion::dateToString( date ) );
+ }
+ }
+ break;
+ case Qtopia::AddressCategory:
+ qWarning("Category is: %s", value.latin1() );
+ default:
+ nonCustomMap.insert( id, value );
+ }
+ }
+
+ // First insert uid
+ nonCustomMap.insert( Qtopia::AddressUid, resItem.data( "uid" ) );
+ t3needed = t3.elapsed();
+
+ // qWarning("Adding UID: %s", resItem.data( "uid" ).latin1() );
+ qWarning("RequestNonCustom needed: insg.:%d ms, query: %d ms, mapping: %d ms",
+ t.elapsed(), t2needed, t3needed );
+
+ return nonCustomMap;
+}
+#else
+
+QMap<int, QString> OContactAccessBackend_SQL::requestNonCustom( int uid ) const
+{
+ QTime t;
+ t.start();
+
+ QMap<int, QString> nonCustomMap;
+
+ int t2needed = 0;
+ QTime t2;
+ t2.start();
+ FindQuery query( uid );
+ OSQLResult res_noncustom = m_driver->query( &query );
+ t2needed = t2.elapsed();
+
+ if ( res_noncustom.state() == OSQLResult::Failure ) {
+ qWarning("OSQLResult::Failure in find query !!");
+ QMap<int, QString> empty;
+ return empty;
+ }
+
+ int t3needed = 0;
+ QTime t3;
+ t3.start();
+ QMap<QString, int> translateMap = OContactFields::untrFieldsToId();
+
+ OSQLResultItem::ValueList list = res_noncustom.results();
+ OSQLResultItem::ValueList::Iterator it = list.begin();
+ for ( ; it != list.end(); ++it ) {
+ if ( (*it).data("type") != "" ){
+ int typeId = translateMap[(*it).data( "type" )];
+ switch( typeId ){
+ case Qtopia::Birthday:
+ case Qtopia::Anniversary:{
+ // Birthday and Anniversary are encoded special ( yyyy-mm-dd )
+ QStringList list = QStringList::split( '-', (*it).data( "value" ) );
+ QStringList::Iterator lit = list.begin();
+ int year = (*lit).toInt();
+ qWarning("1. %s", (*lit).latin1());
+ int month = (*(++lit)).toInt();
+ qWarning("2. %s", (*lit).latin1());
+ int day = (*(++lit)).toInt();
+ qWarning("3. %s", (*lit).latin1());
+ qWarning( "RequestNonCustom->Converting:%s to Year: %d, Month: %d, Day: %d ", (*it).data( "value" ).latin1(), year, month, day );
+ QDate date( year, month, day );
+ nonCustomMap.insert( typeId, OConversion::dateToString( date ) );
+ }
+ break;
+ default:
+ nonCustomMap.insert( typeId,
+ (*it).data( "value" ) );
+ }
+ }
+ }
+ // Add UID to Map..
+ nonCustomMap.insert( Qtopia::AddressUid, QString::number( uid ) );
+ t3needed = t3.elapsed();
+
+ qWarning("RequestNonCustom needed: insg.:%d ms, query: %d ms, mapping: %d ms", t.elapsed(), t2needed, t3needed );
+ return nonCustomMap;
+}
+
+#endif // __STORE_HORIZONTAL_
+
+QMap<QString, QString> OContactAccessBackend_SQL::requestCustom( int uid ) const
+{
+ QTime t;
+ t.start();
+
+ QMap<QString, QString> customMap;
+
+ FindCustomQuery query( uid );
+ OSQLResult res_custom = m_driver->query( &query );
+
+ if ( res_custom.state() == OSQLResult::Failure ) {
+ qWarning("OSQLResult::Failure in find query !!");
+ QMap<QString, QString> empty;
+ return empty;
+ }
+
+ OSQLResultItem::ValueList list = res_custom.results();
+ OSQLResultItem::ValueList::Iterator it = list.begin();
+ for ( ; it != list.end(); ++it ) {
+ customMap.insert( (*it).data( "type" ), (*it).data( "value" ) );
+ }
+
+ qWarning("RequestCustom needed: %d ms", t.elapsed() );
+ return customMap;
+}
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 @@
+/*
+ * SQL Backend for the OPIE-Contact Database.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * =====================================================================
+ *
+ *
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2004/11/16 21:46:07 mickeyl
+ * libopie1 goes into unsupported
+ *
+ * Revision 1.3 2004/03/14 13:50:35 alwin
+ * namespace correction
+ *
+ * Revision 1.2 2003/12/08 15:18:11 eilers
+ * Committing unfinished sql implementation before merging to libopie2 starts..
+ *
+ * Revision 1.1 2003/09/22 14:31:16 eilers
+ * Added first experimental incarnation of sql-backend for addressbook.
+ * Some modifications to be able to compile the todo sql-backend.
+ * A lot of changes fill follow...
+ *
+ *
+ */
+
+#ifndef _OContactAccessBackend_SQL_
+#define _OContactAccessBackend_SQL_
+
+#include "ocontactaccessbackend.h"
+#include "ocontactaccess.h"
+
+#include <qlist.h>
+#include <qdict.h>
+
+namespace Opie { namespace DB {
+class OSQLDriver;
+class OSQLResult;
+class OSQLResultItem;
+
+}}
+
+/* the default xml implementation */
+/**
+ * This class is the SQL implementation of a Contact backend
+ * it does implement everything available for OContact.
+ * @see OPimAccessBackend for more information of available methods
+ */
+class OContactAccessBackend_SQL : public OContactAccessBackend {
+ public:
+ OContactAccessBackend_SQL ( const QString& appname, const QString& filename = QString::null );
+
+ ~OContactAccessBackend_SQL ();
+
+ bool save();
+
+ bool load ();
+
+ void clear ();
+
+ bool wasChangedExternally();
+
+ QArray<int> allRecords() const;
+
+ OContact find ( int uid ) const;
+ // FIXME: Add lookahead-cache support !
+ //OContact find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
+
+ QArray<int> queryByExample ( const OContact &query, int settings,
+ const QDateTime& d );
+
+ QArray<int> matchRegexp( const QRegExp &r ) const;
+
+ const uint querySettings();
+
+ bool hasQuerySettings (uint querySettings) const;
+
+ // Currently only asc implemented..
+ QArray<int> sorted( bool asc, int , int , int );
+ bool add ( const OContact &newcontact );
+
+ bool replace ( const OContact &contact );
+
+ bool remove ( int uid );
+ bool reload();
+
+ private:
+ QArray<int> extractUids( Opie::DB::OSQLResult& res ) const;
+ QMap<int, QString> requestNonCustom( int uid ) const;
+ QMap<QString, QString> requestCustom( int uid ) const;
+ void update();
+
+ protected:
+ bool m_changed;
+ QString m_fileName;
+ QArray<int> m_uids;
+
+ Opie::DB::OSQLDriver* m_driver;
+};
+
+#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 @@
+/*
+ * VCard Backend for the OPIE-Contact Database.
+ *
+ * Copyright (C) 2000 Trolltech AS. All rights reserved.
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * =====================================================================
+ * ToDo:
+ *
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2004/11/16 21:46:07 mickeyl
+ * libopie1 goes into unsupported
+ *
+ * Revision 1.11 2003/08/01 12:30:16 eilers
+ * Merging changes from BRANCH_1_0 to HEAD
+ *
+ * Revision 1.10.4.3 2003/07/23 08:54:37 eilers
+ * Default email was added to the list of all emails, which already contains
+ * the default email..
+ * This closes bug #1045
+ *
+ * Revision 1.10.4.2 2003/07/23 08:44:45 eilers
+ * Importing of Notes in vcard files wasn't implemented.
+ * Closes bug #1044
+ *
+ * Revision 1.10.4.1 2003/06/02 13:37:49 eilers
+ * Fixing memory leak
+ *
+ * Revision 1.10 2003/04/13 18:07:10 zecke
+ * More API doc
+ * QString -> const QString&
+ * QString = 0l -> QString::null
+ *
+ * Revision 1.9 2003/03/21 10:33:09 eilers
+ * Merged speed optimized xml backend for contacts to main.
+ * Added QDateTime to querybyexample. For instance, it is now possible to get
+ * all Birthdays/Anniversaries between two dates. This should be used
+ * to show all birthdays in the datebook..
+ * This change is sourcecode backward compatible but you have to upgrade
+ * the binaries for today-addressbook.
+ *
+ * Revision 1.8 2003/02/21 16:52:49 zecke
+ * -Remove old Todo classes they're deprecated and today I already using the
+ * new API
+ * -Guard against self assignment in OTodo
+ * -Add test apps for OPIM
+ * -Opiefied Event classes
+ * -Added TimeZone handling and pinning of TimeZones to OEvent
+ * -Adjust ORecur and the widget to better timezone behaviour
+ *
+ * Revision 1.7 2003/02/16 22:25:46 zecke
+ * 0000276 Fix for that bug.. or better temp workaround
+ * A Preferred Number is HOME|VOICE
+ * A CellPhone is HOME|VOICE|CELL the type & HOME|VOICE test
+ * triggers both
+ * and the cell phone number overrides the other entries..
+ *
+ * as a temp I check that it's not equal to HOME|VOICE|CELL before setting the
+ * number
+ *
+ * The right and final fix would be to reorder the if statement to make it
+ * if else based and the less common thing put to the bottom
+ *
+ * OTodoAccessVcal fix the date for beaming
+ *
+ * Revision 1.6 2003/01/13 15:49:31 eilers
+ * Fixing crash when businesscard.vcf is missing..
+ *
+ * Revision 1.5 2002/12/07 13:26:22 eilers
+ * Fixing bug in storing anniversary..
+ *
+ * Revision 1.4 2002/11/13 14:14:51 eilers
+ * Added sorted for Contacts..
+ *
+ * Revision 1.3 2002/11/11 16:41:09 kergoth
+ * no default arguments in implementation
+ *
+ * Revision 1.2 2002/11/10 15:41:53 eilers
+ * Bugfixes..
+ *
+ * Revision 1.1 2002/11/09 14:34:52 eilers
+ * Added VCard Backend.
+ *
+ */
+#include "ocontactaccessbackend_vcard.h"
+#include "../../library/backend/vobject_p.h"
+#include "../../library/backend/qfiledirect_p.h"
+
+#include <qpe/timeconversion.h>
+
+#include <qfile.h>
+
+OContactAccessBackend_VCard::OContactAccessBackend_VCard ( const QString& , const QString& filename ):
+ m_dirty( false ),
+ m_file( filename )
+{
+ load();
+}
+
+
+bool OContactAccessBackend_VCard::load ()
+{
+ m_map.clear();
+ m_dirty = false;
+
+ VObject* obj = 0l;
+
+ if ( QFile::exists(m_file) ){
+ obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
+ if ( !obj )
+ return false;
+ }else{
+ qWarning("File \"%s\" not found !", m_file.latin1() );
+ return false;
+ }
+
+ while ( obj ) {
+ OContact con = parseVObject( obj );
+ /*
+ * if uid is 0 assign a new one
+ * this at least happens on
+ * Nokia6210
+ */
+ if ( con.uid() == 0 ){
+ con.setUid( 1 );
+ qWarning("assigned new uid %d",con.uid() );
+ }
+
+ m_map.insert( con.uid(), con );
+
+ VObject *t = obj;
+ obj = nextVObjectInList(obj);
+ cleanVObject( t );
+ }
+
+ return true;
+
+}
+bool OContactAccessBackend_VCard::reload()
+{
+ return load();
+}
+bool OContactAccessBackend_VCard::save()
+{
+ if (!m_dirty )
+ return true;
+
+ QFileDirect file( m_file );
+ if (!file.open(IO_WriteOnly ) )
+ return false;
+
+ VObject *obj;
+ obj = newVObject( VCCalProp );
+ addPropValue( obj, VCVersionProp, "1.0" );
+
+ VObject *vo;
+ for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
+ vo = createVObject( *it );
+ writeVObject( file.directHandle() , vo );
+ cleanVObject( vo );
+ }
+ cleanStrTbl();
+ deleteVObject( obj );
+
+ m_dirty = false;
+ return true;
+
+
+}
+void OContactAccessBackend_VCard::clear ()
+{
+ m_map.clear();
+ m_dirty = true; // ??? sure ? (se)
+}
+
+bool OContactAccessBackend_VCard::add ( const OContact& newcontact )
+{
+ m_map.insert( newcontact.uid(), newcontact );
+ m_dirty = true;
+ return true;
+}
+
+bool OContactAccessBackend_VCard::remove ( int uid )
+{
+ m_map.remove( uid );
+ m_dirty = true;
+ return true;
+}
+
+bool OContactAccessBackend_VCard::replace ( const OContact &contact )
+{
+ m_map.replace( contact.uid(), contact );
+ m_dirty = true;
+ return true;
+}
+
+OContact OContactAccessBackend_VCard::find ( int uid ) const
+{
+ return m_map[uid];
+}
+
+QArray<int> OContactAccessBackend_VCard::allRecords() const
+{
+ QArray<int> ar( m_map.count() );
+ QMap<int, OContact>::ConstIterator it;
+ int i = 0;
+ for ( it = m_map.begin(); it != m_map.end(); ++it ) {
+ ar[i] = it.key();
+ i++;
+ }
+ return ar;
+}
+
+// Not implemented
+QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int, const QDateTime& )
+{
+ QArray<int> ar(0);
+ return ar;
+}
+
+// Not implemented
+QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const
+{
+ QArray<int> ar(0);
+ return ar;
+}
+
+const uint OContactAccessBackend_VCard::querySettings()
+{
+ return 0; // No search possible
+}
+
+bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const
+{
+ return false; // No search possible, therefore all settings invalid ;)
+}
+
+bool OContactAccessBackend_VCard::wasChangedExternally()
+{
+ return false; // Don't expect concurrent access
+}
+
+// Not implemented
+QArray<int> OContactAccessBackend_VCard::sorted( bool , int, int, int )
+{
+ QArray<int> ar(0);
+ return ar;
+}
+
+// *** Private stuff ***
+
+
+OContact OContactAccessBackend_VCard::parseVObject( VObject *obj )
+{
+ OContact c;
+
+ VObjectIterator it;
+ initPropIterator( &it, obj );
+ while( moreIteration( &it ) ) {
+ VObject *o = nextVObject( &it );
+ QCString name = vObjectName( o );
+ QCString value = vObjectStringZValue( o );
+ if ( name == VCNameProp ) {
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectTypeInfo( o );
+ QString value = vObjectStringZValue( o );
+ if ( name == VCNamePrefixesProp )
+ c.setTitle( value );
+ else if ( name == VCNameSuffixesProp )
+ c.setSuffix( value );
+ else if ( name == VCFamilyNameProp )
+ c.setLastName( value );
+ else if ( name == VCGivenNameProp )
+ c.setFirstName( value );
+ else if ( name == VCAdditionalNamesProp )
+ c.setMiddleName( value );
+ }
+ }
+ else if ( name == VCAdrProp ) {
+ bool work = TRUE; // default address is work address
+ QString street;
+ QString city;
+ QString region;
+ QString postal;
+ QString country;
+
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectName( o );
+ QString value = vObjectStringZValue( o );
+ if ( name == VCHomeProp )
+ work = FALSE;
+ else if ( name == VCWorkProp )
+ work = TRUE;
+ else if ( name == VCStreetAddressProp )
+ street = value;
+ else if ( name == VCCityProp )
+ city = value;
+ else if ( name == VCRegionProp )
+ region = value;
+ else if ( name == VCPostalCodeProp )
+ postal = value;
+ else if ( name == VCCountryNameProp )
+ country = value;
+ }
+ if ( work ) {
+ c.setBusinessStreet( street );
+ c.setBusinessCity( city );
+ c.setBusinessCountry( country );
+ c.setBusinessZip( postal );
+ c.setBusinessState( region );
+ } else {
+ c.setHomeStreet( street );
+ c.setHomeCity( city );
+ c.setHomeCountry( country );
+ c.setHomeZip( postal );
+ c.setHomeState( region );
+ }
+ }
+ else if ( name == VCTelephoneProp ) {
+ enum {
+ HOME = 0x01,
+ WORK = 0x02,
+ VOICE = 0x04,
+ CELL = 0x08,
+ FAX = 0x10,
+ PAGER = 0x20,
+ UNKNOWN = 0x80
+ };
+ int type = 0;
+
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectTypeInfo( o );
+ if ( name == VCHomeProp )
+ type |= HOME;
+ else if ( name == VCWorkProp )
+ type |= WORK;
+ else if ( name == VCVoiceProp )
+ type |= VOICE;
+ else if ( name == VCCellularProp )
+ type |= CELL;
+ else if ( name == VCFaxProp )
+ type |= FAX;
+ else if ( name == VCPagerProp )
+ type |= PAGER;
+ else if ( name == VCPreferredProp )
+ ;
+ else
+ type |= UNKNOWN;
+ }
+ if ( (type & UNKNOWN) != UNKNOWN ) {
+ if ( ( type & (HOME|WORK) ) == 0 ) // default
+ type |= HOME;
+ if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default
+ type |= VOICE;
+
+ qWarning("value %s %d", value.data(), type );
+ if ( (type & (VOICE|HOME) ) == (VOICE|HOME) && (type & (CELL|HOME) ) != (CELL|HOME) )
+ c.setHomePhone( value );
+ if ( ( type & (FAX|HOME) ) == (FAX|HOME) )
+ c.setHomeFax( value );
+ if ( ( type & (CELL|HOME) ) == (CELL|HOME) )
+ c.setHomeMobile( value );
+ if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) && (type & (CELL|WORK) ) != (CELL|WORK) )
+ c.setBusinessPhone( value );
+ if ( ( type & (FAX|WORK) ) == (FAX|WORK) )
+ c.setBusinessFax( value );
+ if ( ( type & (CELL|WORK) ) == (CELL|WORK) )
+ c.setBusinessMobile( value );
+ if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) )
+ c.setBusinessPager( value );
+ }
+ }
+ else if ( name == VCEmailAddressProp ) {
+ QString email = vObjectStringZValue( o );
+ bool valid = TRUE;
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectTypeInfo( o );
+ if ( name != VCInternetProp && name != VCHomeProp &&
+ name != VCWorkProp &&
+ name != VCPreferredProp )
+ // ### preffered should map to default email
+ valid = FALSE;
+ }
+ if ( valid ) {
+ c.insertEmail( email );
+ }
+ }
+ else if ( name == VCURLProp ) {
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectTypeInfo( o );
+ if ( name == VCHomeProp )
+ c.setHomeWebpage( value );
+ else if ( name == VCWorkProp )
+ c.setBusinessWebpage( value );
+ }
+ }
+ else if ( name == VCOrgProp ) {
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectName( o );
+ QString value = vObjectStringZValue( o );
+ if ( name == VCOrgNameProp )
+ c.setCompany( value );
+ else if ( name == VCOrgUnitProp )
+ c.setDepartment( value );
+ else if ( name == VCOrgUnit2Prop )
+ c.setOffice( value );
+ }
+ }
+ else if ( name == VCTitleProp ) {
+ c.setJobTitle( value );
+ }
+ else if ( name == "X-Qtopia-Profession" ) {
+ c.setProfession( value );
+ }
+ else if ( name == "X-Qtopia-Manager" ) {
+ c.setManager( value );
+ }
+ else if ( name == "X-Qtopia-Assistant" ) {
+ c.setAssistant( value );
+ }
+ else if ( name == "X-Qtopia-Spouse" ) {
+ c.setSpouse( value );
+ }
+ else if ( name == "X-Qtopia-Gender" ) {
+ c.setGender( value );
+ }
+ else if ( name == "X-Qtopia-Anniversary" ) {
+ c.setAnniversary( convVCardDateToDate( value ) );
+ }
+ else if ( name == "X-Qtopia-Nickname" ) {
+ c.setNickname( value );
+ }
+ else if ( name == "X-Qtopia-Children" ) {
+ c.setChildren( value );
+ }
+ else if ( name == VCBirthDateProp ) {
+ // Reading Birthdate regarding RFC 2425 (5.8.4)
+ c.setBirthday( convVCardDateToDate( value ) );
+
+ }
+ else if ( name == VCCommentProp ) {
+ c.setNotes( value );
+ }
+#if 0
+ else {
+ printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectName( o );
+ QString value = vObjectStringZValue( o );
+ printf(" subprop: %s = %s\n", name.data(), value.latin1() );
+ }
+ }
+#endif
+ }
+ c.setFileAs();
+ return c;
+}
+
+
+VObject* OContactAccessBackend_VCard::createVObject( const OContact &c )
+{
+ VObject *vcard = newVObject( VCCardProp );
+ safeAddPropValue( vcard, VCVersionProp, "2.1" );
+ safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) );
+ safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) );
+
+ // full name
+ safeAddPropValue( vcard, VCFullNameProp, c.fullName() );
+
+ // name properties
+ VObject *name = safeAddProp( vcard, VCNameProp );
+ safeAddPropValue( name, VCFamilyNameProp, c.lastName() );
+ safeAddPropValue( name, VCGivenNameProp, c.firstName() );
+ safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() );
+ safeAddPropValue( name, VCNamePrefixesProp, c.title() );
+ safeAddPropValue( name, VCNameSuffixesProp, c.suffix() );
+
+ // home properties
+ VObject *home_adr= safeAddProp( vcard, VCAdrProp );
+ safeAddProp( home_adr, VCHomeProp );
+ safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() );
+ safeAddPropValue( home_adr, VCCityProp, c.homeCity() );
+ safeAddPropValue( home_adr, VCRegionProp, c.homeState() );
+ safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() );
+ safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() );
+
+ VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() );
+ safeAddProp( home_phone, VCHomeProp );
+ home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() );
+ safeAddProp( home_phone, VCHomeProp );
+ safeAddProp( home_phone, VCCellularProp );
+ home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() );
+ safeAddProp( home_phone, VCHomeProp );
+ safeAddProp( home_phone, VCFaxProp );
+
+ VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() );
+ safeAddProp( url, VCHomeProp );
+
+ // work properties
+ VObject *work_adr= safeAddProp( vcard, VCAdrProp );
+ safeAddProp( work_adr, VCWorkProp );
+ safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() );
+ safeAddPropValue( work_adr, VCCityProp, c.businessCity() );
+ safeAddPropValue( work_adr, VCRegionProp, c.businessState() );
+ safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() );
+ safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() );
+
+ VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() );
+ safeAddProp( work_phone, VCWorkProp );
+ work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() );
+ safeAddProp( work_phone, VCWorkProp );
+ safeAddProp( work_phone, VCCellularProp );
+ work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() );
+ safeAddProp( work_phone, VCWorkProp );
+ safeAddProp( work_phone, VCFaxProp );
+ work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() );
+ safeAddProp( work_phone, VCWorkProp );
+ safeAddProp( work_phone, VCPagerProp );
+
+ url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() );
+ safeAddProp( url, VCWorkProp );
+
+ VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() );
+ safeAddProp( title, VCWorkProp );
+
+
+ QStringList emails = c.emailList();
+ // emails.prepend( c.defaultEmail() ); Fix for bugreport #1045
+ for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) {
+ VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it );
+ safeAddProp( email, VCInternetProp );
+ }
+
+ safeAddPropValue( vcard, VCNoteProp, c.notes() );
+
+ // Exporting Birthday regarding RFC 2425 (5.8.4)
+ if ( c.birthday().isValid() ){
+ qWarning("Exporting birthday as: %s", convDateToVCardDate( c.birthday() ).latin1() );
+ safeAddPropValue( vcard, VCBirthDateProp, convDateToVCardDate( c.birthday() ) );
+ }
+
+ if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) {
+ VObject *org = safeAddProp( vcard, VCOrgProp );
+ safeAddPropValue( org, VCOrgNameProp, c.company() );
+ safeAddPropValue( org, VCOrgUnitProp, c.department() );
+ safeAddPropValue( org, VCOrgUnit2Prop, c.office() );
+ }
+
+ // some values we have to export as custom fields
+ safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() );
+ safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() );
+ safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() );
+
+ safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() );
+ safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() );
+ if ( c.anniversary().isValid() ){
+ qWarning("Exporting anniversary as: %s", convDateToVCardDate( c.anniversary() ).latin1() );
+ safeAddPropValue( vcard, "X-Qtopia-Anniversary", convDateToVCardDate( c.anniversary() ) );
+ }
+ safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() );
+ safeAddPropValue( vcard, "X-Qtopia-Children", c.children() );
+
+ return vcard;
+}
+
+QString OContactAccessBackend_VCard::convDateToVCardDate( const QDate& d ) const
+{
+ QString str_rfc2425 = QString("%1-%2-%3")
+ .arg( d.year() )
+ .arg( d.month(), 2 )
+ .arg( d.day(), 2 );
+ // Now replace spaces with "0"...
+ int pos = 0;
+ while ( ( pos = str_rfc2425.find (' ') ) > 0 )
+ str_rfc2425.replace( pos, 1, "0" );
+
+ return str_rfc2425;
+}
+
+QDate OContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr )
+{
+ int monthPos = datestr.find('-');
+ int dayPos = datestr.find('-', monthPos+1 );
+ int sep_ignore = 1;
+ if ( monthPos == -1 || dayPos == -1 ) {
+ qDebug("fromString didn't find - in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
+ // Ok.. No "-" found, therefore we will try to read other format ( YYYYMMDD )
+ if ( datestr.length() == 8 ){
+ monthPos = 4;
+ dayPos = 6;
+ sep_ignore = 0;
+ qDebug("Try with follwing positions str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
+ } else {
+ return QDate();
+ }
+ }
+ int y = datestr.left( monthPos ).toInt();
+ int m = datestr.mid( monthPos + sep_ignore, dayPos - monthPos - sep_ignore ).toInt();
+ int d = datestr.mid( dayPos + sep_ignore ).toInt();
+ qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, dayPos);
+ QDate date ( y,m,d );
+ return date;
+}
+
+VObject* OContactAccessBackend_VCard::safeAddPropValue( VObject *o, const char *prop, const QString &value )
+{
+ VObject *ret = 0;
+ if ( o && !value.isEmpty() )
+ ret = addPropValue( o, prop, value.latin1() );
+ return ret;
+}
+
+VObject* OContactAccessBackend_VCard::safeAddProp( VObject *o, const char *prop)
+{
+ VObject *ret = 0;
+ if ( o )
+ ret = addProp( o, prop );
+ return ret;
+}
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 @@
+/*
+ * VCard Backend for the OPIE-Contact Database.
+ *
+ * Copyright (C) 2000 Trolltech AS. All rights reserved.
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * =====================================================================
+ * ToDo:
+ *
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2004/11/16 21:46:07 mickeyl
+ * libopie1 goes into unsupported
+ *
+ * Revision 1.6 2003/04/13 18:07:10 zecke
+ * More API doc
+ * QString -> const QString&
+ * QString = 0l -> QString::null
+ *
+ * Revision 1.5 2003/03/21 10:33:09 eilers
+ * Merged speed optimized xml backend for contacts to main.
+ * Added QDateTime to querybyexample. For instance, it is now possible to get
+ * all Birthdays/Anniversaries between two dates. This should be used
+ * to show all birthdays in the datebook..
+ * This change is sourcecode backward compatible but you have to upgrade
+ * the binaries for today-addressbook.
+ *
+ * Revision 1.4 2002/12/07 13:26:22 eilers
+ * Fixing bug in storing anniversary..
+ *
+ * Revision 1.3 2002/11/13 14:14:51 eilers
+ * Added sorted for Contacts..
+ *
+ * Revision 1.2 2002/11/10 15:41:53 eilers
+ * Bugfixes..
+ *
+ * Revision 1.1 2002/11/09 14:34:52 eilers
+ * Added VCard Backend.
+ *
+ */
+#ifndef __OCONTACTACCESSBACKEND_VCARD_H_
+#define __OCONTACTACCESSBACKEND_VCARD_H_
+
+#include <opie/ocontact.h>
+
+#include "ocontactaccessbackend.h"
+
+class VObject;
+
+/**
+ * This is the vCard 2.1 implementation of the Contact Storage
+ * @see OContactAccessBackend_XML
+ * @see OPimAccessBackend
+ */
+class OContactAccessBackend_VCard : public OContactAccessBackend {
+ public:
+ OContactAccessBackend_VCard ( const QString& appname, const QString& filename = QString::null );
+
+ bool load ();
+ bool reload();
+ bool save();
+ void clear ();
+
+ bool add ( const OContact& newcontact );
+ bool remove ( int uid );
+ bool replace ( const OContact& contact );
+
+ OContact find ( int uid ) const;
+ QArray<int> allRecords() const;
+ QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() );
+ QArray<int> matchRegexp( const QRegExp &r ) const;
+
+ const uint querySettings();
+ bool hasQuerySettings (uint querySettings) const;
+ QArray<int> sorted( bool ascending, int sortOrder, int sortFilter, int cat );
+ bool wasChangedExternally();
+
+private:
+ OContact parseVObject( VObject* obj );
+ VObject* createVObject( const OContact& c );
+ QString convDateToVCardDate( const QDate& c ) const;
+ QDate convVCardDateToDate( const QString& datestr );
+ VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value );
+ VObject *safeAddProp( VObject* o, const char* prop);
+
+ bool m_dirty : 1;
+ QString m_file;
+ QMap<int, OContact> m_map;
+};
+
+#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 @@
+/*
+ * XML Backend for the OPIE-Contact Database.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * =====================================================================
+ *
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2004/11/16 21:46:07 mickeyl
+ * libopie1 goes into unsupported
+ *
+ * Revision 1.10 2004/03/01 15:44:36 chicken
+ * fix includes
+ *
+ * Revision 1.9 2003/09/22 14:31:16 eilers
+ * Added first experimental incarnation of sql-backend for addressbook.
+ * Some modifications to be able to compile the todo sql-backend.
+ * A lot of changes fill follow...
+ *
+ * Revision 1.8 2003/08/30 15:28:26 eilers
+ * Removed some unimportant debug output which causes slow down..
+ *
+ * Revision 1.7 2003/08/01 12:30:16 eilers
+ * Merging changes from BRANCH_1_0 to HEAD
+ *
+ * Revision 1.6 2003/07/07 16:19:47 eilers
+ * Fixing serious bug in hasQuerySettings()
+ *
+ * Revision 1.5 2003/04/13 18:07:10 zecke
+ * More API doc
+ * QString -> const QString&
+ * QString = 0l -> QString::null
+ *
+ * Revision 1.4 2003/03/21 14:32:54 mickeyl
+ * g++ compliance fix: default arguments belong into the declaration, but not the definition
+ *
+ * Revision 1.3 2003/03/21 12:26:28 eilers
+ * Fixing small bug: If we search a birthday from today to today, it returned
+ * every contact ..
+ *
+ * Revision 1.2 2003/03/21 10:33:09 eilers
+ * Merged speed optimized xml backend for contacts to main.
+ * Added QDateTime to querybyexample. For instance, it is now possible to get
+ * all Birthdays/Anniversaries between two dates. This should be used
+ * to show all birthdays in the datebook..
+ * This change is sourcecode backward compatible but you have to upgrade
+ * the binaries for today-addressbook.
+ *
+ * Revision 1.1.2.2 2003/02/11 12:17:28 eilers
+ * Speed optimization. Removed the sequential search loops.
+ *
+ * Revision 1.1.2.1 2003/02/10 15:31:38 eilers
+ * Writing offsets to debug output..
+ *
+ * Revision 1.1 2003/02/09 15:05:01 eilers
+ * Nothing happened.. Just some cleanup before I will start..
+ *
+ * Revision 1.12 2003/01/03 16:58:03 eilers
+ * Reenable debug output
+ *
+ * Revision 1.11 2003/01/03 12:31:28 eilers
+ * Bugfix for calculating data diffs..
+ *
+ * Revision 1.10 2003/01/02 14:27:12 eilers
+ * Improved query by example: Search by date is possible.. First step
+ * for a today plugin for birthdays..
+ *
+ * Revision 1.9 2002/12/08 12:48:57 eilers
+ * Moved journal-enum from ocontact into i the xml-backend..
+ *
+ * Revision 1.8 2002/11/14 17:04:24 eilers
+ * Sorting will now work if fullname is identical on some entries
+ *
+ * Revision 1.7 2002/11/13 15:02:46 eilers
+ * Small Bug in sorted fixed
+ *
+ * Revision 1.6 2002/11/13 14:14:51 eilers
+ * Added sorted for Contacts..
+ *
+ * Revision 1.5 2002/11/01 15:10:42 eilers
+ * Added regExp-search in database for all fields in a contact.
+ *
+ * Revision 1.4 2002/10/16 10:52:40 eilers
+ * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
+ *
+ * Revision 1.3 2002/10/14 16:21:54 eilers
+ * Some minor interface updates
+ *
+ * Revision 1.2 2002/10/07 17:34:24 eilers
+ * added OBackendFactory for advanced backend access
+ *
+ * Revision 1.1 2002/09/27 17:11:44 eilers
+ * Added API for accessing the Contact-Database ! It is compiling, but
+ * please do not expect that anything is working !
+ * I will debug that stuff in the next time ..
+ * Please read README_COMPILE for compiling !
+ *
+ *
+ */
+
+#include "ocontactaccessbackend_xml.h"
+
+#include <qasciidict.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qarray.h>
+#include <qmap.h>
+
+#include <qpe/global.h>
+
+#include <opie/xmltree.h>
+#include "ocontactaccessbackend.h"
+#include "ocontactaccess.h"
+
+#include <stdlib.h>
+#include <errno.h>
+
+using namespace Opie;
+
+
+OContactAccessBackend_XML::OContactAccessBackend_XML ( const QString& appname, const QString& filename ):
+ m_changed( false )
+{
+ // Just m_contactlist should call delete if an entry
+ // is removed.
+ m_contactList.setAutoDelete( true );
+ m_uidToContact.setAutoDelete( false );
+
+ m_appName = appname;
+
+ /* Set journalfile name ... */
+ m_journalName = getenv("HOME");
+ m_journalName +="/.abjournal" + appname;
+
+ /* Expecting to access the default filename if nothing else is set */
+ if ( filename.isEmpty() ){
+ m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
+ } else
+ m_fileName = filename;
+
+ /* Load Database now */
+ load ();
+}
+
+bool OContactAccessBackend_XML::save()
+{
+
+ if ( !m_changed )
+ return true;
+
+ QString strNewFile = m_fileName + ".new";
+ QFile f( strNewFile );
+ if ( !f.open( IO_WriteOnly|IO_Raw ) )
+ return false;
+
+ int total_written;
+ int idx_offset = 0;
+ QString out;
+
+ // Write Header
+ out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
+ " <Groups>\n"
+ " </Groups>\n"
+ " <Contacts>\n";
+ QCString cstr = out.utf8();
+ f.writeBlock( cstr.data(), cstr.length() );
+ idx_offset += cstr.length();
+ out = "";
+
+ // Write all contacts
+ QListIterator<OContact> it( m_contactList );
+ for ( ; it.current(); ++it ) {
+ // qWarning(" Uid %d at Offset: %x", (*it)->uid(), idx_offset );
+ out += "<Contact ";
+ (*it)->save( out );
+ out += "/>\n";
+ cstr = out.utf8();
+ total_written = f.writeBlock( cstr.data(), cstr.length() );
+ idx_offset += cstr.length();
+ if ( total_written != int(cstr.length()) ) {
+ f.close();
+ QFile::remove( strNewFile );
+ return false;
+ }
+ out = "";
+ }
+ out += " </Contacts>\n</AddressBook>\n";
+
+ // Write Footer
+ cstr = out.utf8();
+ total_written = f.writeBlock( cstr.data(), cstr.length() );
+ if ( total_written != int( cstr.length() ) ) {
+ f.close();
+ QFile::remove( strNewFile );
+ return false;
+ }
+ f.close();
+
+ // move the file over, I'm just going to use the system call
+ // because, I don't feel like using QDir.
+ if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
+ qWarning( "problem renaming file %s to %s, errno: %d",
+ strNewFile.latin1(), m_journalName.latin1(), errno );
+ // remove the tmp file...
+ QFile::remove( strNewFile );
+ }
+
+ /* The journalfile should be removed now... */
+ removeJournal();
+
+ m_changed = false;
+ return true;
+}
+
+bool OContactAccessBackend_XML::load ()
+{
+ m_contactList.clear();
+ m_uidToContact.clear();
+
+ /* Load XML-File and journal if it exists */
+ if ( !load ( m_fileName, false ) )
+ return false;
+ /* The returncode of the journalfile is ignored due to the
+ * fact that it does not exist when this class is instantiated !
+ * But there may such a file exist, if the application crashed.
+ * Therefore we try to load it to get the changes before the #
+ * crash happened...
+ */
+ load (m_journalName, true);
+
+ return true;
+}
+
+void OContactAccessBackend_XML::clear ()
+{
+ m_contactList.clear();
+ m_uidToContact.clear();
+
+ m_changed = false;
+}
+
+bool OContactAccessBackend_XML::wasChangedExternally()
+{
+ QFileInfo fi( m_fileName );
+
+ QDateTime lastmod = fi.lastModified ();
+
+ return (lastmod != m_readtime);
+}
+
+QArray<int> OContactAccessBackend_XML::allRecords() const
+{
+ QArray<int> uid_list( m_contactList.count() );
+
+ uint counter = 0;
+ QListIterator<OContact> it( m_contactList );
+ for( ; it.current(); ++it ){
+ uid_list[counter++] = (*it)->uid();
+ }
+
+ return ( uid_list );
+}
+
+OContact OContactAccessBackend_XML::find ( int uid ) const
+{
+ OContact foundContact; //Create empty contact
+
+ OContact* found = m_uidToContact.find( QString().setNum( uid ) );
+
+ if ( found ){
+ foundContact = *found;
+ }
+
+ return ( foundContact );
+}
+
+QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, int settings,
+ const QDateTime& d )
+{
+
+ QArray<int> m_currentQuery( m_contactList.count() );
+ QListIterator<OContact> it( m_contactList );
+ uint arraycounter = 0;
+
+ for( ; it.current(); ++it ){
+ /* Search all fields and compare them with query object. Store them into list
+ * if all fields matches.
+ */
+ QDate* queryDate = 0l;
+ QDate* checkDate = 0l;
+ bool allcorrect = true;
+ for ( int i = 0; i < Qtopia::Groups; i++ ) {
+ // Birthday and anniversary are special nonstring fields and should
+ // be handled specially
+ switch ( i ){
+ case Qtopia::Birthday:
+ queryDate = new QDate( query.birthday() );
+ checkDate = new QDate( (*it)->birthday() );
+ case Qtopia::Anniversary:
+ if ( queryDate == 0l ){
+ queryDate = new QDate( query.anniversary() );
+ checkDate = new QDate( (*it)->anniversary() );
+ }
+
+ if ( queryDate->isValid() ){
+ if( checkDate->isValid() ){
+ if ( settings & OContactAccess::DateYear ){
+ if ( queryDate->year() != checkDate->year() )
+ allcorrect = false;
+ }
+ if ( settings & OContactAccess::DateMonth ){
+ if ( queryDate->month() != checkDate->month() )
+ allcorrect = false;
+ }
+ if ( settings & OContactAccess::DateDay ){
+ if ( queryDate->day() != checkDate->day() )
+ allcorrect = false;
+ }
+ if ( settings & OContactAccess::DateDiff ) {
+ QDate current;
+ // If we get an additional date, we
+ // will take this date instead of
+ // the current one..
+ if ( !d.date().isValid() )
+ current = QDate::currentDate();
+ else
+ current = d.date();
+
+ // We have to equalize the year, otherwise
+ // the search will fail..
+ checkDate->setYMD( current.year(),
+ checkDate->month(),
+ checkDate->day() );
+ if ( *checkDate < current )
+ checkDate->setYMD( current.year()+1,
+ checkDate->month(),
+ checkDate->day() );
+
+ // Check whether the birthday/anniversary date is between
+ // the current/given date and the maximum date
+ // ( maximum time range ) !
+ qWarning("Checking if %s is between %s and %s ! ",
+ checkDate->toString().latin1(),
+ current.toString().latin1(),
+ queryDate->toString().latin1() );
+ if ( current.daysTo( *queryDate ) >= 0 ){
+ if ( !( ( *checkDate >= current ) &&
+ ( *checkDate <= *queryDate ) ) ){
+ allcorrect = false;
+ qWarning (" Nope!..");
+ }
+ }
+ }
+ } else{
+ // checkDate is invalid. Therefore this entry is always rejected
+ allcorrect = false;
+ }
+ }
+
+ delete queryDate;
+ queryDate = 0l;
+ delete checkDate;
+ checkDate = 0l;
+ break;
+ default:
+ /* Just compare fields which are not empty in the query object */
+ if ( !query.field(i).isEmpty() ){
+ switch ( settings & ~( OContactAccess::IgnoreCase
+ | OContactAccess::DateDiff
+ | OContactAccess::DateYear
+ | OContactAccess::DateMonth
+ | OContactAccess::DateDay
+ | OContactAccess::MatchOne
+ ) ){
+
+ case OContactAccess::RegExp:{
+ QRegExp expr ( query.field(i),
+ !(settings & OContactAccess::IgnoreCase),
+ false );
+ if ( expr.find ( (*it)->field(i), 0 ) == -1 )
+ allcorrect = false;
+ }
+ break;
+ case OContactAccess::WildCards:{
+ QRegExp expr ( query.field(i),
+ !(settings & OContactAccess::IgnoreCase),
+ true );
+ if ( expr.find ( (*it)->field(i), 0 ) == -1 )
+ allcorrect = false;
+ }
+ break;
+ case OContactAccess::ExactMatch:{
+ if (settings & OContactAccess::IgnoreCase){
+ if ( query.field(i).upper() !=
+ (*it)->field(i).upper() )
+ allcorrect = false;
+ }else{
+ if ( query.field(i) != (*it)->field(i) )
+ allcorrect = false;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ if ( allcorrect ){
+ m_currentQuery[arraycounter++] = (*it)->uid();
+ }
+ }
+
+ // Shrink to fit..
+ m_currentQuery.resize(arraycounter);
+
+ return m_currentQuery;
+}
+
+QArray<int> OContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const
+{
+ QArray<int> m_currentQuery( m_contactList.count() );
+ QListIterator<OContact> it( m_contactList );
+ uint arraycounter = 0;
+
+ for( ; it.current(); ++it ){
+ if ( (*it)->match( r ) ){
+ m_currentQuery[arraycounter++] = (*it)->uid();
+ }
+
+ }
+ // Shrink to fit..
+ m_currentQuery.resize(arraycounter);
+
+ return m_currentQuery;
+}
+
+const uint OContactAccessBackend_XML::querySettings()
+{
+ return ( OContactAccess::WildCards
+ | OContactAccess::IgnoreCase
+ | OContactAccess::RegExp
+ | OContactAccess::ExactMatch
+ | OContactAccess::DateDiff
+ | OContactAccess::DateYear
+ | OContactAccess::DateMonth
+ | OContactAccess::DateDay
+ );
+}
+
+bool OContactAccessBackend_XML::hasQuerySettings (uint querySettings) const
+{
+ /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
+ * may be added with any of the other settings. IgnoreCase should never used alone.
+ * Wildcards, RegExp, ExactMatch should never used at the same time...
+ */
+
+ // Step 1: Check whether the given settings are supported by this backend
+ if ( ( querySettings & (
+ OContactAccess::IgnoreCase
+ | OContactAccess::WildCards
+ | OContactAccess::DateDiff
+ | OContactAccess::DateYear
+ | OContactAccess::DateMonth
+ | OContactAccess::DateDay
+ | OContactAccess::RegExp
+ | OContactAccess::ExactMatch
+ ) ) != querySettings )
+ return false;
+
+ // Step 2: Check whether the given combinations are ok..
+
+ // IngoreCase alone is invalid
+ if ( querySettings == OContactAccess::IgnoreCase )
+ return false;
+
+ // WildCards, RegExp and ExactMatch should never used at the same time
+ switch ( querySettings & ~( OContactAccess::IgnoreCase
+ | OContactAccess::DateDiff
+ | OContactAccess::DateYear
+ | OContactAccess::DateMonth
+ | OContactAccess::DateDay
+ )
+ ){
+ case OContactAccess::RegExp:
+ return ( true );
+ case OContactAccess::WildCards:
+ return ( true );
+ case OContactAccess::ExactMatch:
+ return ( true );
+ case 0: // one of the upper removed bits were set..
+ return ( true );
+ default:
+ return ( false );
+ }
+}
+
+// Currently only asc implemented..
+QArray<int> OContactAccessBackend_XML::sorted( bool asc, int , int , int )
+{
+ QMap<QString, int> nameToUid;
+ QStringList names;
+ QArray<int> m_currentQuery( m_contactList.count() );
+
+ // First fill map and StringList with all Names
+ // Afterwards sort namelist and use map to fill array to return..
+ QListIterator<OContact> it( m_contactList );
+ for( ; it.current(); ++it ){
+ names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) );
+ nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() );
+ }
+ names.sort();
+
+ int i = 0;
+ if ( asc ){
+ for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
+ m_currentQuery[i++] = nameToUid[ (*it) ];
+ }else{
+ for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
+ m_currentQuery[i++] = nameToUid[ (*it) ];
+ }
+
+ return m_currentQuery;
+
+}
+
+bool OContactAccessBackend_XML::add ( const OContact &newcontact )
+{
+ //qWarning("odefaultbackend: ACTION::ADD");
+ updateJournal (newcontact, ACTION_ADD);
+ addContact_p( newcontact );
+
+ m_changed = true;
+
+ return true;
+}
+
+bool OContactAccessBackend_XML::replace ( const OContact &contact )
+{
+ m_changed = true;
+
+ OContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) );
+
+ if ( found ) {
+ OContact* newCont = new OContact( contact );
+
+ updateJournal ( *newCont, ACTION_REPLACE);
+ m_contactList.removeRef ( found );
+ m_contactList.append ( newCont );
+ m_uidToContact.remove( QString().setNum( contact.uid() ) );
+ m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont );
+
+ qWarning("Nur zur Sicherheit: %d == %d ?",contact.uid(), newCont->uid());
+
+ return true;
+ } else
+ return false;
+}
+
+bool OContactAccessBackend_XML::remove ( int uid )
+{
+ m_changed = true;
+
+ OContact* found = m_uidToContact.find ( QString().setNum( uid ) );
+
+ if ( found ) {
+ updateJournal ( *found, ACTION_REMOVE);
+ m_contactList.removeRef ( found );
+ m_uidToContact.remove( QString().setNum( uid ) );
+
+ return true;
+ } else
+ return false;
+}
+
+bool OContactAccessBackend_XML::reload(){
+ /* Reload is the same as load in this implementation */
+ return ( load() );
+}
+
+void OContactAccessBackend_XML::addContact_p( const OContact &newcontact )
+{
+ OContact* contRef = new OContact( newcontact );
+
+ m_contactList.append ( contRef );
+ m_uidToContact.insert( QString().setNum( newcontact.uid() ), contRef );
+}
+
+/* This function loads the xml-database and the journalfile */
+bool OContactAccessBackend_XML::load( const QString filename, bool isJournal )
+{
+
+ /* We use the time of the last read to check if the file was
+ * changed externally.
+ */
+ if ( !isJournal ){
+ QFileInfo fi( filename );
+ m_readtime = fi.lastModified ();
+ }
+
+ const int JOURNALACTION = Qtopia::Notes + 1;
+ const int JOURNALROW = JOURNALACTION + 1;
+
+ bool foundAction = false;
+ journal_action action = ACTION_ADD;
+ int journalKey = 0;
+ QMap<int, QString> contactMap;
+ QMap<QString, QString> customMap;
+ QMap<QString, QString>::Iterator customIt;
+ QAsciiDict<int> dict( 47 );
+
+ dict.setAutoDelete( TRUE );
+ dict.insert( "Uid", new int(Qtopia::AddressUid) );
+ dict.insert( "Title", new int(Qtopia::Title) );
+ dict.insert( "FirstName", new int(Qtopia::FirstName) );
+ dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
+ dict.insert( "LastName", new int(Qtopia::LastName) );
+ dict.insert( "Suffix", new int(Qtopia::Suffix) );
+ dict.insert( "FileAs", new int(Qtopia::FileAs) );
+ dict.insert( "Categories", new int(Qtopia::AddressCategory) );
+ dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
+ dict.insert( "Emails", new int(Qtopia::Emails) );
+ dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
+ dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
+ dict.insert( "HomeState", new int(Qtopia::HomeState) );
+ dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
+ dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
+ dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
+ dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
+ dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
+ dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
+ dict.insert( "Company", new int(Qtopia::Company) );
+ dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
+ dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
+ dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
+ dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
+ dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
+ dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
+ dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
+ dict.insert( "Department", new int(Qtopia::Department) );
+ dict.insert( "Office", new int(Qtopia::Office) );
+ dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
+ dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
+ dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
+ dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
+ dict.insert( "Profession", new int(Qtopia::Profession) );
+ dict.insert( "Assistant", new int(Qtopia::Assistant) );
+ dict.insert( "Manager", new int(Qtopia::Manager) );
+ dict.insert( "Spouse", new int(Qtopia::Spouse) );
+ dict.insert( "Children", new int(Qtopia::Children) );
+ dict.insert( "Gender", new int(Qtopia::Gender) );
+ dict.insert( "Birthday", new int(Qtopia::Birthday) );
+ dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
+ dict.insert( "Nickname", new int(Qtopia::Nickname) );
+ dict.insert( "Notes", new int(Qtopia::Notes) );
+ dict.insert( "action", new int(JOURNALACTION) );
+ dict.insert( "actionrow", new int(JOURNALROW) );
+
+ //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
+
+ XMLElement *root = XMLElement::load( filename );
+ if(root != 0l ){ // start parsing
+ /* Parse all XML-Elements and put the data into the
+ * Contact-Class
+ */
+ XMLElement *element = root->firstChild();
+ //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() );
+ element = element->firstChild();
+
+ /* Search Tag "Contacts" which is the parent of all Contacts */
+ while( element && !isJournal ){
+ if( element->tagName() != QString::fromLatin1("Contacts") ){
+ //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s",
+ // element->tagName().latin1());
+ element = element->nextChild();
+ } else {
+ element = element->firstChild();
+ break;
+ }
+ }
+ /* Parse all Contacts and ignore unknown tags */
+ while( element ){
+ if( element->tagName() != QString::fromLatin1("Contact") ){
+ //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s",
+ // element->tagName().latin1());
+ element = element->nextChild();
+ continue;
+ }
+ /* Found alement with tagname "contact", now parse and store all
+ * attributes contained
+ */
+ //qWarning("OContactDefBack::load element tagName() : %s",
+ // element->tagName().latin1() );
+ QString dummy;
+ foundAction = false;
+
+ XMLElement::AttributeMap aMap = element->attributes();
+ XMLElement::AttributeMap::Iterator it;
+ contactMap.clear();
+ customMap.clear();
+ for( it = aMap.begin(); it != aMap.end(); ++it ){
+ // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1());
+
+ int *find = dict[ it.key() ];
+ /* Unknown attributes will be stored as "Custom" elements */
+ if ( !find ) {
+ // qWarning("Attribute %s not known.", it.key().latin1());
+ //contact.setCustomField(it.key(), it.data());
+ customMap.insert( it.key(), it.data() );
+ continue;
+ }
+
+ /* Check if special conversion is needed and add attribute
+ * into Contact class
+ */
+ switch( *find ) {
+ /*
+ case Qtopia::AddressUid:
+ contact.setUid( it.data().toInt() );
+ break;
+ case Qtopia::AddressCategory:
+ contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
+ break;
+ */
+ case JOURNALACTION:
+ action = journal_action(it.data().toInt());
+ foundAction = true;
+ qWarning ("ODefBack(journal)::ACTION found: %d", action);
+ break;
+ case JOURNALROW:
+ journalKey = it.data().toInt();
+ break;
+ default: // no conversion needed add them to the map
+ contactMap.insert( *find, it.data() );
+ break;
+ }
+ }
+ /* now generate the Contact contact */
+ OContact contact( contactMap );
+
+ for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
+ contact.setCustomField( customIt.key(), customIt.data() );
+ }
+
+ if (foundAction){
+ foundAction = false;
+ switch ( action ) {
+ case ACTION_ADD:
+ addContact_p (contact);
+ break;
+ case ACTION_REMOVE:
+ if ( !remove (contact.uid()) )
+ qWarning ("ODefBack(journal)::Unable to remove uid: %d",
+ contact.uid() );
+ break;
+ case ACTION_REPLACE:
+ if ( !replace ( contact ) )
+ qWarning ("ODefBack(journal)::Unable to replace uid: %d",
+ contact.uid() );
+ break;
+ default:
+ qWarning ("Unknown action: ignored !");
+ break;
+ }
+ }else{
+ /* Add contact to list */
+ addContact_p (contact);
+ }
+
+ /* Move to next element */
+ element = element->nextChild();
+ }
+ }else {
+ qWarning("ODefBack::could not load");
+ }
+ delete root;
+ qWarning("returning from loading" );
+ return true;
+}
+
+
+void OContactAccessBackend_XML::updateJournal( const OContact& cnt,
+ journal_action action )
+{
+ QFile f( m_journalName );
+ bool created = !f.exists();
+ if ( !f.open(IO_WriteOnly|IO_Append) )
+ return;
+
+ QString buf;
+ QCString str;
+
+ // if the file was created, we have to set the Tag "<CONTACTS>" to
+ // get a XML-File which is readable by our parser.
+ // This is just a cheat, but better than rewrite the parser.
+ if ( created ){
+ buf = "<Contacts>";
+ QCString cstr = buf.utf8();
+ f.writeBlock( cstr.data(), cstr.length() );
+ }
+
+ buf = "<Contact ";
+ cnt.save( buf );
+ buf += " action=\"" + QString::number( (int)action ) + "\" ";
+ buf += "/>\n";
+ QCString cstr = buf.utf8();
+ f.writeBlock( cstr.data(), cstr.length() );
+}
+
+void OContactAccessBackend_XML::removeJournal()
+{
+ QFile f ( m_journalName );
+ if ( f.exists() )
+ f.remove();
+}
+
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 @@
+/*
+ * XML Backend for the OPIE-Contact Database.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * =====================================================================
+ * ToDo: XML-Backend: Automatic reload if something was changed...
+ * File Locking to protect against concurrent access
+ *
+ *
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2004/11/16 21:46:07 mickeyl
+ * libopie1 goes into unsupported
+ *
+ * Revision 1.15 2003/09/22 14:31:16 eilers
+ * Added first experimental incarnation of sql-backend for addressbook.
+ * Some modifications to be able to compile the todo sql-backend.
+ * A lot of changes fill follow...
+ *
+ * Revision 1.14 2003/04/13 18:07:10 zecke
+ * More API doc
+ * QString -> const QString&
+ * QString = 0l -> QString::null
+ *
+ * Revision 1.13 2003/03/21 10:33:09 eilers
+ * Merged speed optimized xml backend for contacts to main.
+ * Added QDateTime to querybyexample. For instance, it is now possible to get
+ * all Birthdays/Anniversaries between two dates. This should be used
+ * to show all birthdays in the datebook..
+ * This change is sourcecode backward compatible but you have to upgrade
+ * the binaries for today-addressbook.
+ *
+ * Revision 1.12.2.2 2003/02/11 12:17:28 eilers
+ * Speed optimization. Removed the sequential search loops.
+ *
+ * Revision 1.12.2.1 2003/02/09 15:05:01 eilers
+ * Nothing happened.. Just some cleanup before I will start..
+ *
+ * Revision 1.12 2003/01/03 16:58:03 eilers
+ * Reenable debug output
+ *
+ * Revision 1.11 2003/01/03 12:31:28 eilers
+ * Bugfix for calculating data diffs..
+ *
+ * Revision 1.10 2003/01/02 14:27:12 eilers
+ * Improved query by example: Search by date is possible.. First step
+ * for a today plugin for birthdays..
+ *
+ * Revision 1.9 2002/12/08 12:48:57 eilers
+ * Moved journal-enum from ocontact into i the xml-backend..
+ *
+ * Revision 1.8 2002/11/14 17:04:24 eilers
+ * Sorting will now work if fullname is identical on some entries
+ *
+ * Revision 1.7 2002/11/13 15:02:46 eilers
+ * Small Bug in sorted fixed
+ *
+ * Revision 1.6 2002/11/13 14:14:51 eilers
+ * Added sorted for Contacts..
+ *
+ * Revision 1.5 2002/11/01 15:10:42 eilers
+ * Added regExp-search in database for all fields in a contact.
+ *
+ * Revision 1.4 2002/10/16 10:52:40 eilers
+ * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
+ *
+ * Revision 1.3 2002/10/14 16:21:54 eilers
+ * Some minor interface updates
+ *
+ * Revision 1.2 2002/10/07 17:34:24 eilers
+ * added OBackendFactory for advanced backend access
+ *
+ * Revision 1.1 2002/09/27 17:11:44 eilers
+ * Added API for accessing the Contact-Database ! It is compiling, but
+ * please do not expect that anything is working !
+ * I will debug that stuff in the next time ..
+ * Please read README_COMPILE for compiling !
+ *
+ *
+ */
+
+#ifndef _OContactAccessBackend_XML_
+#define _OContactAccessBackend_XML_
+
+#include "ocontactaccessbackend.h"
+#include "ocontactaccess.h"
+
+#include <qlist.h>
+#include <qdict.h>
+
+/* the default xml implementation */
+/**
+ * This class is the XML implementation of a Contact backend
+ * it does implement everything available for OContact.
+ * @see OPimAccessBackend for more information of available methods
+ */
+class OContactAccessBackend_XML : public OContactAccessBackend {
+ public:
+ OContactAccessBackend_XML ( const QString& appname, const QString& filename = QString::null );
+
+ bool save();
+
+ bool load ();
+
+ void clear ();
+
+ bool wasChangedExternally();
+
+ QArray<int> allRecords() const;
+
+ OContact find ( int uid ) const;
+
+ QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() );
+
+ QArray<int> matchRegexp( const QRegExp &r ) const;
+
+ const uint querySettings();
+
+ bool hasQuerySettings (uint querySettings) const;
+
+ // Currently only asc implemented..
+ QArray<int> sorted( bool asc, int , int , int );
+ bool add ( const OContact &newcontact );
+
+ bool replace ( const OContact &contact );
+
+ bool remove ( int uid );
+ bool reload();
+
+ private:
+
+ enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE };
+
+ void addContact_p( const OContact &newcontact );
+
+ /* This function loads the xml-database and the journalfile */
+ bool load( const QString filename, bool isJournal );
+
+
+ void updateJournal( const OContact& cnt, journal_action action );
+ void removeJournal();
+
+ protected:
+ bool m_changed;
+ QString m_journalName;
+ QString m_fileName;
+ QString m_appName;
+ QList<OContact> m_contactList;
+ QDateTime m_readtime;
+
+ QDict<OContact> m_uidToContact;
+};
+
+#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 @@
+
+#include "ocontactfields.h"
+
+#include <qstringlist.h>
+#include <qobject.h>
+
+// We should use our own enum in the future ..
+#include <qpe/recordfields.h>
+#include <qpe/config.h>
+#include <opie/ocontact.h>
+
+/*!
+ \internal
+ Returns a list of personal field names for a contact.
+*/
+QStringList OContactFields::personalfields( bool sorted, bool translated )
+{
+ QStringList list;
+ QMap<int, QString> mapIdToStr;
+ if ( translated )
+ mapIdToStr = idToTrFields();
+ else
+ mapIdToStr = idToUntrFields();
+
+ list.append( mapIdToStr[ Qtopia::AddressUid ] );
+ list.append( mapIdToStr[ Qtopia::AddressCategory ] );
+
+ list.append( mapIdToStr[ Qtopia::Title ] );
+ list.append( mapIdToStr[ Qtopia::FirstName ] );
+ list.append( mapIdToStr[ Qtopia::MiddleName ] );
+ list.append( mapIdToStr[ Qtopia::LastName ] );
+ list.append( mapIdToStr[ Qtopia::Suffix ] );
+ list.append( mapIdToStr[ Qtopia::FileAs ] );
+
+ list.append( mapIdToStr[ Qtopia::JobTitle ] );
+ list.append( mapIdToStr[ Qtopia::Department ] );
+ list.append( mapIdToStr[ Qtopia::Company ] );
+
+ list.append( mapIdToStr[ Qtopia::Notes ] );
+ list.append( mapIdToStr[ Qtopia::Groups ] );
+
+ if (sorted) list.sort();
+ return list;
+}
+
+/*!
+ \internal
+ Returns a list of details field names for a contact.
+*/
+QStringList OContactFields::detailsfields( bool sorted, bool translated )
+{
+ QStringList list;
+ QMap<int, QString> mapIdToStr;
+ if ( translated )
+ mapIdToStr = idToTrFields();
+ else
+ mapIdToStr = idToUntrFields();
+
+ list.append( mapIdToStr[ Qtopia::Office ] );
+ list.append( mapIdToStr[ Qtopia::Profession ] );
+ list.append( mapIdToStr[ Qtopia::Assistant ] );
+ list.append( mapIdToStr[ Qtopia::Manager ] );
+
+ list.append( mapIdToStr[ Qtopia::Spouse ] );
+ list.append( mapIdToStr[ Qtopia::Gender ] );
+ list.append( mapIdToStr[ Qtopia::Birthday ] );
+ list.append( mapIdToStr[ Qtopia::Anniversary ] );
+ list.append( mapIdToStr[ Qtopia::Nickname ] );
+ list.append( mapIdToStr[ Qtopia::Children ] );
+
+ if (sorted) list.sort();
+ return list;
+}
+
+/*!
+ \internal
+ Returns a list of phone field names for a contact.
+*/
+QStringList OContactFields::phonefields( bool sorted, bool translated )
+{
+ QStringList list;
+ QMap<int, QString> mapIdToStr;
+ if ( translated )
+ mapIdToStr = idToTrFields();
+ else
+ mapIdToStr = idToUntrFields();
+
+ list.append( mapIdToStr[Qtopia::BusinessPhone] );
+ list.append( mapIdToStr[Qtopia::BusinessFax] );
+ list.append( mapIdToStr[Qtopia::BusinessMobile] );
+ list.append( mapIdToStr[Qtopia::BusinessPager] );
+ list.append( mapIdToStr[Qtopia::BusinessWebPage] );
+
+ list.append( mapIdToStr[Qtopia::DefaultEmail] );
+ list.append( mapIdToStr[Qtopia::Emails] );
+
+ list.append( mapIdToStr[Qtopia::HomePhone] );
+ list.append( mapIdToStr[Qtopia::HomeFax] );
+ list.append( mapIdToStr[Qtopia::HomeMobile] );
+ // list.append( mapIdToStr[Qtopia::HomePager] );
+ list.append( mapIdToStr[Qtopia::HomeWebPage] );
+
+ if (sorted) list.sort();
+
+ return list;
+}
+
+/*!
+ \internal
+ Returns a list of field names for a contact.
+*/
+QStringList OContactFields::fields( bool sorted, bool translated )
+{
+ QStringList list;
+ QMap<int, QString> mapIdToStr;
+ if ( translated )
+ mapIdToStr = idToTrFields();
+ else
+ mapIdToStr = idToUntrFields();
+
+ list += personalfields( sorted, translated );
+
+ list += phonefields( sorted, translated );
+
+ list.append( mapIdToStr[Qtopia::BusinessStreet] );
+ list.append( mapIdToStr[Qtopia::BusinessCity] );
+ list.append( mapIdToStr[Qtopia::BusinessState] );
+ list.append( mapIdToStr[Qtopia::BusinessZip] );
+ list.append( mapIdToStr[Qtopia::BusinessCountry] );
+
+ list.append( mapIdToStr[Qtopia::HomeStreet] );
+ list.append( mapIdToStr[Qtopia::HomeCity] );
+ list.append( mapIdToStr[Qtopia::HomeState] );
+ list.append( mapIdToStr[Qtopia::HomeZip] );
+ list.append( mapIdToStr[Qtopia::HomeCountry] );
+
+ list += detailsfields( sorted, translated );
+
+ if (sorted) list.sort();
+
+ return list;
+}
+
+
+/*!
+ \internal
+ Returns an untranslated list of personal field names for a contact.
+*/
+QStringList OContactFields::untrpersonalfields( bool sorted )
+{
+ return personalfields( sorted, false );
+}
+
+
+/*!
+ \internal
+ Returns a translated list of personal field names for a contact.
+*/
+QStringList OContactFields::trpersonalfields( bool sorted )
+{
+ return personalfields( sorted, true );
+}
+
+
+/*!
+ \internal
+ Returns an untranslated list of details field names for a contact.
+*/
+QStringList OContactFields::untrdetailsfields( bool sorted )
+{
+ return detailsfields( sorted, false );
+}
+
+
+/*!
+ \internal
+ Returns a translated list of details field names for a contact.
+*/
+QStringList OContactFields::trdetailsfields( bool sorted )
+{
+ return detailsfields( sorted, true );
+}
+
+
+/*!
+ \internal
+ Returns a translated list of phone field names for a contact.
+*/
+QStringList OContactFields::trphonefields( bool sorted )
+{
+ return phonefields( sorted, true );
+}
+
+/*!
+ \internal
+ Returns an untranslated list of phone field names for a contact.
+*/
+QStringList OContactFields::untrphonefields( bool sorted )
+{
+ return phonefields( sorted, false );
+}
+
+
+/*!
+ \internal
+ Returns a translated list of field names for a contact.
+*/
+QStringList OContactFields::trfields( bool sorted )
+{
+ return fields( sorted, true );
+}
+
+/*!
+ \internal
+ Returns an untranslated list of field names for a contact.
+*/
+QStringList OContactFields::untrfields( bool sorted )
+{
+ return fields( sorted, false );
+}
+
+QMap<int, QString> OContactFields::idToTrFields()
+{
+ QMap<int, QString> ret_map;
+
+ ret_map.insert( Qtopia::AddressUid, QObject::tr( "User Id" ) );
+ ret_map.insert( Qtopia::AddressCategory, QObject::tr( "Categories" ) );
+
+ ret_map.insert( Qtopia::Title, QObject::tr( "Name Title") );
+ ret_map.insert( Qtopia::FirstName, QObject::tr( "First Name" ) );
+ ret_map.insert( Qtopia::MiddleName, QObject::tr( "Middle Name" ) );
+ ret_map.insert( Qtopia::LastName, QObject::tr( "Last Name" ) );
+ ret_map.insert( Qtopia::Suffix, QObject::tr( "Suffix" ));
+ ret_map.insert( Qtopia::FileAs, QObject::tr( "File As" ) );
+
+ ret_map.insert( Qtopia::JobTitle, QObject::tr( "Job Title" ) );
+ ret_map.insert( Qtopia::Department, QObject::tr( "Department" ) );
+ ret_map.insert( Qtopia::Company, QObject::tr( "Company" ) );
+ ret_map.insert( Qtopia::BusinessPhone, QObject::tr( "Business Phone" ) );
+ ret_map.insert( Qtopia::BusinessFax, QObject::tr( "Business Fax" ) );
+ ret_map.insert( Qtopia::BusinessMobile, QObject::tr( "Business Mobile" ));
+
+ // email
+ ret_map.insert( Qtopia::DefaultEmail, QObject::tr( "Default Email" ) );
+ ret_map.insert( Qtopia::Emails, QObject::tr( "Emails" ) );
+
+ ret_map.insert( Qtopia::HomePhone, QObject::tr( "Home Phone" ) );
+ ret_map.insert( Qtopia::HomeFax, QObject::tr( "Home Fax" ) );
+ ret_map.insert( Qtopia::HomeMobile, QObject::tr( "Home Mobile" ) );
+
+ // business
+ ret_map.insert( Qtopia::BusinessStreet, QObject::tr( "Business Street" ) );
+ ret_map.insert( Qtopia::BusinessCity, QObject::tr( "Business City" ) );
+ ret_map.insert( Qtopia::BusinessState, QObject::tr( "Business State" ) );
+ ret_map.insert( Qtopia::BusinessZip, QObject::tr( "Business Zip" ) );
+ ret_map.insert( Qtopia::BusinessCountry, QObject::tr( "Business Country" ) );
+ ret_map.insert( Qtopia::BusinessPager, QObject::tr( "Business Pager" ) );
+ ret_map.insert( Qtopia::BusinessWebPage, QObject::tr( "Business WebPage" ) );
+
+ ret_map.insert( Qtopia::Office, QObject::tr( "Office" ) );
+ ret_map.insert( Qtopia::Profession, QObject::tr( "Profession" ) );
+ ret_map.insert( Qtopia::Assistant, QObject::tr( "Assistant" ) );
+ ret_map.insert( Qtopia::Manager, QObject::tr( "Manager" ) );
+
+ // home
+ ret_map.insert( Qtopia::HomeStreet, QObject::tr( "Home Street" ) );
+ ret_map.insert( Qtopia::HomeCity, QObject::tr( "Home City" ) );
+ ret_map.insert( Qtopia::HomeState, QObject::tr( "Home State" ) );
+ ret_map.insert( Qtopia::HomeZip, QObject::tr( "Home Zip" ) );
+ ret_map.insert( Qtopia::HomeCountry, QObject::tr( "Home Country" ) );
+ ret_map.insert( Qtopia::HomeWebPage, QObject::tr( "Home Web Page" ) );
+
+ //personal
+ ret_map.insert( Qtopia::Spouse, QObject::tr( "Spouse" ) );
+ ret_map.insert( Qtopia::Gender, QObject::tr( "Gender" ) );
+ ret_map.insert( Qtopia::Birthday, QObject::tr( "Birthday" ) );
+ ret_map.insert( Qtopia::Anniversary, QObject::tr( "Anniversary" ) );
+ ret_map.insert( Qtopia::Nickname, QObject::tr( "Nickname" ) );
+ ret_map.insert( Qtopia::Children, QObject::tr( "Children" ) );
+
+ // other
+ ret_map.insert( Qtopia::Notes, QObject::tr( "Notes" ) );
+
+
+ return ret_map;
+}
+
+QMap<int, QString> OContactFields::idToUntrFields()
+{
+ QMap<int, QString> ret_map;
+
+ ret_map.insert( Qtopia::AddressUid, "User Id" );
+ ret_map.insert( Qtopia::AddressCategory, "Categories" );
+
+ ret_map.insert( Qtopia::Title, "Name Title" );
+ ret_map.insert( Qtopia::FirstName, "First Name" );
+ ret_map.insert( Qtopia::MiddleName, "Middle Name" );
+ ret_map.insert( Qtopia::LastName, "Last Name" );
+ ret_map.insert( Qtopia::Suffix, "Suffix" );
+ ret_map.insert( Qtopia::FileAs, "File As" );
+
+ ret_map.insert( Qtopia::JobTitle, "Job Title" );
+ ret_map.insert( Qtopia::Department, "Department" );
+ ret_map.insert( Qtopia::Company, "Company" );
+ ret_map.insert( Qtopia::BusinessPhone, "Business Phone" );
+ ret_map.insert( Qtopia::BusinessFax, "Business Fax" );
+ ret_map.insert( Qtopia::BusinessMobile, "Business Mobile" );
+
+ // email
+ ret_map.insert( Qtopia::DefaultEmail, "Default Email" );
+ ret_map.insert( Qtopia::Emails, "Emails" );
+
+ ret_map.insert( Qtopia::HomePhone, "Home Phone" );
+ ret_map.insert( Qtopia::HomeFax, "Home Fax" );
+ ret_map.insert( Qtopia::HomeMobile, "Home Mobile" );
+
+ // business
+ ret_map.insert( Qtopia::BusinessStreet, "Business Street" );
+ ret_map.insert( Qtopia::BusinessCity, "Business City" );
+ ret_map.insert( Qtopia::BusinessState, "Business State" );
+ ret_map.insert( Qtopia::BusinessZip, "Business Zip" );
+ ret_map.insert( Qtopia::BusinessCountry, "Business Country" );
+ ret_map.insert( Qtopia::BusinessPager, "Business Pager" );
+ ret_map.insert( Qtopia::BusinessWebPage, "Business WebPage" );
+
+ ret_map.insert( Qtopia::Office, "Office" );
+ ret_map.insert( Qtopia::Profession, "Profession" );
+ ret_map.insert( Qtopia::Assistant, "Assistant" );
+ ret_map.insert( Qtopia::Manager, "Manager" );
+
+ // home
+ ret_map.insert( Qtopia::HomeStreet, "Home Street" );
+ ret_map.insert( Qtopia::HomeCity, "Home City" );
+ ret_map.insert( Qtopia::HomeState, "Home State" );
+ ret_map.insert( Qtopia::HomeZip, "Home Zip" );
+ ret_map.insert( Qtopia::HomeCountry, "Home Country" );
+ ret_map.insert( Qtopia::HomeWebPage, "Home Web Page" );
+
+ //personal
+ ret_map.insert( Qtopia::Spouse, "Spouse" );
+ ret_map.insert( Qtopia::Gender, "Gender" );
+ ret_map.insert( Qtopia::Birthday, "Birthday" );
+ ret_map.insert( Qtopia::Anniversary, "Anniversary" );
+ ret_map.insert( Qtopia::Nickname, "Nickname" );
+ ret_map.insert( Qtopia::Children, "Children" );
+
+ // other
+ ret_map.insert( Qtopia::Notes, "Notes" );
+ ret_map.insert( Qtopia::Groups, "Groups" );
+
+
+ return ret_map;
+}
+
+QMap<QString, int> OContactFields::trFieldsToId()
+{
+ QMap<int, QString> idtostr = idToTrFields();
+ QMap<QString, int> ret_map;
+
+
+ QMap<int, QString>::Iterator it;
+ for( it = idtostr.begin(); it != idtostr.end(); ++it )
+ ret_map.insert( *it, it.key() );
+
+
+ return ret_map;
+}
+
+/* ======================================================================= */
+
+QMap<QString, int> OContactFields::untrFieldsToId()
+{
+ QMap<int, QString> idtostr = idToUntrFields();
+ QMap<QString, int> ret_map;
+
+
+ QMap<int, QString>::Iterator it;
+ for( it = idtostr.begin(); it != idtostr.end(); ++it )
+ ret_map.insert( *it, it.key() );
+
+
+ return ret_map;
+}
+
+
+OContactFields::OContactFields():
+ fieldOrder( DEFAULT_FIELD_ORDER ),
+ changedFieldOrder( false )
+{
+ // Get the global field order from the config file and
+ // use it as a start pattern
+ Config cfg ( "AddressBook" );
+ cfg.setGroup( "ContactFieldOrder" );
+ globalFieldOrder = cfg.readEntry( "General", DEFAULT_FIELD_ORDER );
+}
+
+OContactFields::~OContactFields(){
+
+ // We will store the fieldorder into the config file
+ // to reuse it for the future..
+ if ( changedFieldOrder ){
+ Config cfg ( "AddressBook" );
+ cfg.setGroup( "ContactFieldOrder" );
+ cfg.writeEntry( "General", globalFieldOrder );
+ }
+}
+
+
+
+void OContactFields::saveToRecord( OContact &cnt ){
+
+ qDebug("ocontactfields saveToRecord: >%s<",fieldOrder.latin1());
+
+ // Store fieldorder into this contact.
+ cnt.setCustomField( CONTACT_FIELD_ORDER_NAME, fieldOrder );
+
+ globalFieldOrder = fieldOrder;
+ changedFieldOrder = true;
+
+}
+
+void OContactFields::loadFromRecord( const OContact &cnt ){
+ qDebug("ocontactfields loadFromRecord");
+ qDebug("loading >%s<",cnt.fullName().latin1());
+
+ // Get fieldorder for this contact. If none is defined,
+ // we will use the global one from the config file..
+
+ fieldOrder = cnt.customField( CONTACT_FIELD_ORDER_NAME );
+
+ qDebug("fieldOrder from contact>%s<",fieldOrder.latin1());
+
+ if (fieldOrder.isEmpty()){
+ fieldOrder = globalFieldOrder;
+ }
+
+
+ qDebug("effective fieldOrder in loadFromRecord >%s<",fieldOrder.latin1());
+}
+
+void OContactFields::setFieldOrder( int num, int index ){
+ qDebug("qcontactfields setfieldorder pos %i -> %i",num,index);
+
+ fieldOrder[num] = QString::number( index, 16 )[0];
+
+ // We will store this new fieldorder globally to
+ // remember it for contacts which have none
+ globalFieldOrder = fieldOrder;
+ changedFieldOrder = true;
+
+ qDebug("fieldOrder >%s<",fieldOrder.latin1());
+}
+
+int OContactFields::getFieldOrder( int num, int defIndex ){
+ qDebug("ocontactfields getFieldOrder");
+ qDebug("fieldOrder >%s<",fieldOrder.latin1());
+
+ // Get index of combo as char..
+ QChar poschar = fieldOrder[num];
+
+ bool ok;
+ int ret = 0;
+ // Convert char to number..
+ if ( !( poschar == QChar::null ) )
+ ret = QString( poschar ).toInt(&ok, 16);
+ else
+ ok = false;
+
+ // Return default value if index for
+ // num was not set or if anything else happened..
+ if ( !ok ) ret = defIndex;
+
+ qDebug("returning >%i<",ret);
+
+ return ret;
+
+}
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 @@
+#ifndef OPIE_CONTACTS_FIELDS
+#define OPIE_CONTACTS_FIELDS
+
+class QStringList;
+
+#include <qmap.h>
+#include <qstring.h>
+#include <opie/ocontact.h>
+
+#define CONTACT_FIELD_ORDER_NAME "opie-contactfield-order"
+#define DEFAULT_FIELD_ORDER "__________"
+
+class OContactFields{
+
+ public:
+ OContactFields();
+ ~OContactFields();
+ /** Set the index for combo boxes.
+ * Sets the <b>index</b> of combo <b>num</b>.
+ * @param num selects the number of the combo
+ * @param index sets the index in the combo
+ */
+ void setFieldOrder( int num, int index );
+
+ /** Get the index for combo boxes.
+ * Returns the index of combo <b>num</b> or defindex
+ * if none was defined..
+ * @param num Selects the number of the combo
+ * @param defIndex will be returned if none was defined (either
+ * globally in the config file, nor by the contact which was used
+ * by loadFromRecord() )
+ */
+ int getFieldOrder( int num, int defIndex);
+
+ /** Store fieldorder to contact. */
+ void saveToRecord( OContact& );
+ /** Get Fieldorder from contact. */
+ void loadFromRecord( const OContact& );
+
+ private:
+ QString fieldOrder;
+ QString globalFieldOrder;
+ bool changedFieldOrder;
+
+ public:
+ static QStringList personalfields( bool sorted = true, bool translated = false );
+ static QStringList phonefields( bool sorted = true, bool translated = false );
+ static QStringList detailsfields( bool sorted = true, bool translated = false );
+ static QStringList fields( bool sorted = true, bool translated = false );
+
+ static QStringList trpersonalfields( bool sorted = true );
+ static QStringList untrpersonalfields( bool sorted = true );
+ static QStringList trphonefields( bool sorted = true );
+ static QStringList untrphonefields( bool sorted = true );
+ static QStringList trdetailsfields( bool sorted = true );
+ static QStringList untrdetailsfields( bool sorted = true );
+ static QStringList trfields( bool sorted = true );
+ static QStringList untrfields( bool sorted = true );
+
+ static QMap<int, QString> idToTrFields();
+ static QMap<QString, int> trFieldsToId();
+ static QMap<int, QString> idToUntrFields();
+ static QMap<QString, int> untrFieldsToId();
+
+};
+
+#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 @@
+/**********************************************************************
+** Copyright (C) 2003 by Stefan Eilers (eilers.stefan@epost.de)
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+**********************************************************************/
+
+#include "oconversion.h"
+#include <qpe/timeconversion.h>
+
+
+QString OConversion::dateToString( const QDate &d )
+{
+ if ( d.isNull() || !d.isValid() )
+ return QString::null;
+
+ // ISO format in year, month, day (YYYYMMDD); e.g. 20021231
+ QString year = QString::number( d.year() );
+ QString month = QString::number( d.month() );
+ month = month.rightJustify( 2, '0' );
+ QString day = QString::number( d.day() );
+ day = day.rightJustify( 2, '0' );
+
+ QString str = year + month + day;
+ //qDebug( "\tPimContact dateToStr = %s", str.latin1() );
+
+ return str;
+}
+
+QDate OConversion::dateFromString( const QString& s )
+{
+ QDate date;
+
+ if ( s.isEmpty() )
+ return date;
+
+ // Be backward compatible to old Opie format:
+ // Try to load old format. If it fails, try new ISO-Format!
+ date = TimeConversion::fromString ( s );
+ if ( date.isValid() )
+ return date;
+
+ // Read ISO-Format (YYYYMMDD)
+ int year = s.mid(0, 4).toInt();
+ int month = s.mid(4,2).toInt();
+ int day = s.mid(6,2).toInt();
+
+ // do some quick sanity checking -eilers
+ // but we isValid() again? -zecke
+ if ( year < 1900 || year > 3000 ) {
+ qWarning( "PimContact year is not in range");
+ return date;
+ }
+ if ( month < 0 || month > 12 ) {
+ qWarning( "PimContact month is not in range");
+ return date;
+ }
+ if ( day < 0 || day > 31 ) {
+ qWarning( "PimContact day is not in range");
+ return date;
+ }
+
+ date.setYMD( year, month, day );
+ if ( !date.isValid() ) {
+ qWarning( "PimContact date is not valid");
+ return date;
+ }
+
+ return date;
+}
+QString OConversion::dateTimeToString( const QDateTime& dt ) {
+ if (!dt.isValid() || dt.isNull() ) return QString::null;
+
+ QString year = QString::number( dt.date().year() );
+ QString month = QString::number( dt.date().month() );
+ QString day = QString::number( dt.date().day() );
+
+ QString hour = QString::number( dt.time().hour() );
+ QString min = QString::number( dt.time().minute() );
+ QString sec = QString::number( dt.time().second() );
+
+ month = month.rightJustify( 2, '0' );
+ day = day. rightJustify( 2, '0' );
+ hour = hour. rightJustify( 2, '0' );
+ min = min. rightJustify( 2, '0' );
+ sec = sec. rightJustify( 2, '0' );
+
+ QString str = day + month + year + hour + min + sec;
+
+ return str;
+}
+QDateTime OConversion::dateTimeFromString( const QString& str) {
+
+ if ( str.isEmpty() ) return QDateTime();
+ int day = str.mid(0, 2).toInt();
+ int month = str.mid(2, 2).toInt();
+ int year = str.mid(4, 4).toInt();
+ int hour = str.mid(8, 2).toInt();
+ int min = str.mid(10, 2).toInt();
+ int sec = str.mid(12, 2).toInt();
+
+ QDate date( year, month, day );
+ QTime time( hour, min, sec );
+ QDateTime dt( date, time );
+ return dt;
+}
+
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 @@
+/**********************************************************************
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+** Copyright (C) 2002-2003 by Stefan Eilers (eilers.stefan@epost.de)
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**********************************************************************/
+
+#ifndef __oconversion_h__
+#define __oconversion_h__
+
+/* #include <time.h> */
+/* #include <sys/types.h> */
+#include <qdatetime.h>
+
+/* FIXME namespace? -zecke */
+class OConversion
+{
+public:
+ static QString dateToString( const QDate &d );
+ static QDate dateFromString( const QString &datestr );
+
+ /**
+ * simple function to store DateTime as string and read from string
+ * no timezone changing is done
+ * DDMMYYYYHHMMSS is the simple format
+ */
+ static QString dateTimeToString( const QDateTime& );
+ static QDateTime dateTimeFromString( const QString& );
+
+private:
+ class Private;
+ Private* d;
+
+};
+
+#endif // __oconversion_h__
+
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 @@
+#include "obackendfactory.h"
+#include "odatebookaccess.h"
+
+/**
+ * Simple constructor
+ * It takes a ODateBookAccessBackend as parent. If it is 0 the default implementation
+ * will be used!
+ * @param back The backend to be used or 0 for the default backend
+ * @param ac What kind of access is intended
+ */
+ODateBookAccess::ODateBookAccess( ODateBookAccessBackend* back, enum Access ac )
+ : OPimAccessTemplate<OEvent>( back )
+{
+ if (!back )
+ back = OBackendFactory<ODateBookAccessBackend>::Default("datebook", QString::null );
+
+ m_backEnd = back;
+ setBackEnd( m_backEnd );
+}
+ODateBookAccess::~ODateBookAccess() {
+}
+
+/**
+ * @return all events available
+ */
+ODateBookAccess::List ODateBookAccess::rawEvents()const {
+ QArray<int> ints = m_backEnd->rawEvents();
+
+ List lis( ints, this );
+ return lis;
+}
+
+/**
+ * @return all repeating events
+ */
+ODateBookAccess::List ODateBookAccess::rawRepeats()const {
+ QArray<int> ints = m_backEnd->rawRepeats();
+
+ List lis( ints, this );
+ return lis;
+}
+
+/**
+ * @return all non repeating events
+ */
+ODateBookAccess::List ODateBookAccess::nonRepeats()const {
+ QArray<int> ints = m_backEnd->nonRepeats();
+
+ List lis( ints, this );
+ return lis;
+}
+
+/**
+ * @return dates in the time span between from and to
+ * @param from Include all events from...
+ * @param to Include all events to...
+ */
+OEffectiveEvent::ValueList ODateBookAccess::effectiveEvents( const QDate& from, const QDate& to ) const {
+ return m_backEnd->effectiveEvents( from, to );
+}
+/**
+ * @return all events at a given datetime
+ */
+OEffectiveEvent::ValueList ODateBookAccess::effectiveEvents( const QDateTime& start ) const {
+ return m_backEnd->effectiveEvents( start );
+}
+
+/**
+ * @return non repeating dates in the time span between from and to
+ * @param from Include all events from...
+ * @param to Include all events to...
+ */
+OEffectiveEvent::ValueList ODateBookAccess::effectiveNonRepeatingEvents( const QDate& from, const QDate& to ) const {
+ return m_backEnd->effectiveNonRepeatingEvents( from, to );
+}
+/**
+ * @return all non repeating events at a given datetime
+ */
+OEffectiveEvent::ValueList ODateBookAccess::effectiveNonRepeatingEvents( const QDateTime& start ) const {
+ return m_backEnd->effectiveNonRepeatingEvents( start );
+}
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 @@
+#ifndef OPIE_DATE_BOOK_ACCESS_H
+#define OPIE_DATE_BOOK_ACCESS_H
+
+#include "odatebookaccessbackend.h"
+#include "opimaccesstemplate.h"
+
+#include "oevent.h"
+
+/**
+ * This is the object orientated datebook database. It'll use OBackendFactory
+ * to query for a backend.
+ * All access to the datebook should be done via this class.
+ * Make sure to load and save the datebook this is not part of
+ * destructing and creating the object
+ *
+ * @author Holger Freyther, Stefan Eilers
+ */
+class ODateBookAccess : public OPimAccessTemplate<OEvent> {
+public:
+ ODateBookAccess( ODateBookAccessBackend* = 0l, enum Access acc = Random );
+ ~ODateBookAccess();
+
+ /* return all events */
+ List rawEvents()const;
+
+ /* return repeating events */
+ List rawRepeats()const;
+
+ /* return non repeating events */
+ List nonRepeats()const;
+
+ /* return non repeating events (from,to) */
+ OEffectiveEvent::ValueList effectiveEvents( const QDate& from, const QDate& to ) const;
+ OEffectiveEvent::ValueList effectiveEvents( const QDateTime& start ) const;
+ OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDate& from, const QDate& to ) const;
+ OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDateTime& start ) const;
+
+private:
+ ODateBookAccessBackend* m_backEnd;
+ class Private;
+ Private* d;
+};
+
+#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 @@
+#include <qtl.h>
+
+#include "orecur.h"
+
+#include "odatebookaccessbackend.h"
+
+namespace {
+/* a small helper to get all NonRepeating events for a range of time */
+ void events( OEffectiveEvent::ValueList& tmpList, const OEvent::ValueList& events,
+ const QDate& from, const QDate& to ) {
+ QDateTime dtStart, dtEnd;
+
+ for ( OEvent::ValueList::ConstIterator it = events.begin(); it != events.end(); ++it ) {
+ dtStart = (*it).startDateTime();
+ dtEnd = (*it).endDateTime();
+
+ /*
+ * If in range
+ */
+ if (dtStart.date() >= from && dtEnd.date() <= to ) {
+ OEffectiveEvent eff;
+ eff.setEvent( (*it) );
+ eff.setDate( dtStart.date() );
+ eff.setStartTime( dtStart.time() );
+
+ /* if not on the same day */
+ if ( dtStart.date() != dtEnd.date() )
+ eff.setEndTime( QTime(23, 59, 0 ) );
+ else
+ eff.setEndTime( dtEnd.time() );
+
+ tmpList.append( eff );
+ }
+
+ /* we must also check for end date information... */
+ if ( dtEnd.date() != dtStart.date() && dtEnd.date() >= from ) {
+ QDateTime dt = dtStart.addDays( 1 );
+ dt.setTime( QTime(0, 0, 0 ) );
+ QDateTime dtStop;
+ if ( dtEnd > to )
+ dtStop = to;
+ else
+ dtStop = dtEnd;
+
+ while ( dt <= dtStop ) {
+ OEffectiveEvent eff;
+ eff.setEvent( (*it) );
+ eff.setDate( dt.date() );
+
+ if ( dt >= from ) {
+ eff.setStartTime( QTime(0, 0, 0 ) );
+ if ( dt.date() == dtEnd.date() )
+ eff.setEndTime( dtEnd.time() );
+ else
+ eff.setEndTime( QTime(23, 59, 0 ) );
+ tmpList.append( eff );
+ }
+ dt = dt.addDays( 1 );
+ }
+ }
+ }
+ }
+
+ void repeat( OEffectiveEvent::ValueList& tmpList, const OEvent::ValueList& list,
+ const QDate& from, const QDate& to ) {
+ QDate repeat;
+ for ( OEvent::ValueList::ConstIterator it = list.begin(); it != list.end(); ++it ) {
+ int dur = (*it).startDateTime().date().daysTo( (*it).endDateTime().date() );
+ QDate itDate = from.addDays(-dur );
+ ORecur rec = (*it).recurrence();
+ if ( !rec.hasEndDate() || rec.endDate() > to ) {
+ rec.setEndDate( to );
+ rec.setHasEndDate( true );
+ }
+ while (rec.nextOcurrence(itDate, repeat ) ) {
+ if (repeat > to ) break;
+ OEffectiveEvent eff;
+ eff.setDate( repeat );
+ if ( (*it).isAllDay() ) {
+ eff.setStartTime( QTime(0, 0, 0 ) );
+ eff.setEndTime( QTime(23, 59, 59 ) );
+ }else {
+ /* we only occur by days, not hours/minutes/seconds. Hence
+ * the actual end and start times will be the same for
+ * every repeated event. For multi day events this is
+ * fixed up later if on wronge day span
+ */
+ eff.setStartTime( (*it).startDateTime().time() );
+ eff.setEndTime( (*it).endDateTime().time() );
+ }
+ if ( dur != 0 ) {
+ // multi-day repeating events
+ QDate sub_it = QMAX( repeat, from );
+ QDate startDate = repeat;
+ QDate endDate = startDate.addDays( dur );
+
+ while ( sub_it <= endDate && sub_it <= to ) {
+ OEffectiveEvent tmpEff = eff;
+ tmpEff.setEvent( (*it) );
+ if ( sub_it != startDate )
+ tmpEff.setStartTime( QTime(0, 0, 0 ) );
+ if ( sub_it != endDate )
+ tmpEff.setEndTime( QTime( 23, 59, 59 ) );
+
+ tmpEff.setDate( sub_it );
+ tmpEff.setEffectiveDates( startDate, endDate );
+ tmpList.append( tmpEff );
+
+ sub_it = sub_it.addDays( 1 );
+ }
+ itDate = endDate;
+ }else {
+ eff.setEvent( (*it) );
+ tmpList.append( eff );
+ itDate = repeat.addDays( 1 );
+ }
+ }
+ }
+ }
+}
+
+ODateBookAccessBackend::ODateBookAccessBackend()
+ : OPimAccessBackend<OEvent>()
+{
+
+}
+ODateBookAccessBackend::~ODateBookAccessBackend() {
+
+}
+OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveEvents( const QDate& from,
+ const QDate& to ) {
+ OEffectiveEvent::ValueList tmpList;
+ OEvent::ValueList list = directNonRepeats();
+
+ events( tmpList, list, from, to );
+ repeat( tmpList, directRawRepeats(),from,to );
+
+ list = directRawRepeats(); // Useless, isn't it ? (eilers)
+
+ qHeapSort( tmpList );
+ return tmpList;
+}
+OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveEvents( const QDateTime& dt ) {
+ OEffectiveEvent::ValueList day = effectiveEvents( dt.date(), dt.date() );
+ OEffectiveEvent::ValueList::Iterator it;
+
+ OEffectiveEvent::ValueList tmpList;
+ QDateTime dtTmp;
+ for ( it = day.begin(); it != day.end(); ++it ) {
+ dtTmp = QDateTime( (*it).date(), (*it).startTime() );
+ if ( QABS(dt.secsTo(dtTmp) ) < 60 )
+ tmpList.append( (*it) );
+ }
+
+ return tmpList;
+}
+
+OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveNonRepeatingEvents( const QDate& from,
+ const QDate& to ) {
+ OEffectiveEvent::ValueList tmpList;
+ OEvent::ValueList list = directNonRepeats();
+
+ events( tmpList, list, from, to );
+
+ qHeapSort( tmpList );
+ return tmpList;
+}
+
+OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveNonRepeatingEvents( const QDateTime& dt ) {
+ OEffectiveEvent::ValueList day = effectiveNonRepeatingEvents( dt.date(), dt.date() );
+ OEffectiveEvent::ValueList::Iterator it;
+
+ OEffectiveEvent::ValueList tmpList;
+ QDateTime dtTmp;
+ for ( it = day.begin(); it != day.end(); ++it ) {
+ dtTmp = QDateTime( (*it).date(), (*it).startTime() );
+ if ( QABS(dt.secsTo(dtTmp) ) < 60 )
+ tmpList.append( (*it) );
+ }
+
+ return tmpList;
+}
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 @@
+#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_H
+#define OPIE_DATE_BOOK_ACCESS_BACKEND_H
+
+#include <qarray.h>
+
+#include "opimaccessbackend.h"
+#include "oevent.h"
+
+/**
+ * This class is the interface to the storage of Events.
+ * @see OPimAccessBackend
+ *
+ */
+class ODateBookAccessBackend : public OPimAccessBackend<OEvent> {
+public:
+ typedef int UID;
+
+ /**
+ * c'tor without parameter
+ */
+ ODateBookAccessBackend();
+ ~ODateBookAccessBackend();
+
+ /**
+ * This method should return a list of UIDs containing
+ * all events. No filter should be applied
+ * @return list of events
+ */
+ virtual QArray<UID> rawEvents()const = 0;
+
+ /**
+ * This method should return a list of UIDs containing
+ * all repeating events. No filter should be applied
+ * @return list of repeating events
+ */
+ virtual QArray<UID> rawRepeats()const = 0;
+
+ /**
+ * This mthod should return a list of UIDs containing all non
+ * repeating events. No filter should be applied
+ * @return list of nonrepeating events
+ */
+ virtual QArray<UID> nonRepeats() const = 0;
+
+ /**
+ * If you do not want to implement the effectiveEvents methods below
+ * you need to supply it with directNonRepeats.
+ * This method can return empty lists if effectiveEvents is implememted
+ */
+ virtual OEvent::ValueList directNonRepeats() = 0;
+
+ /**
+ * Same as above but return raw repeats!
+ */
+ virtual OEvent::ValueList directRawRepeats() = 0;
+
+ /* is implemented by default but you can reimplement it*/
+ /**
+ * Effective Events are special event occuring during a time frame. This method does calcualte
+ * EffectiveEvents bases on the directNonRepeats and directRawRepeats. You may implement this method
+ * yourself
+ */
+ virtual OEffectiveEvent::ValueList effectiveEvents( const QDate& from, const QDate& to );
+
+ /**
+ * this is an overloaded member function
+ * @see effectiveEvents( const QDate& from, const QDate& to )
+ */
+ virtual OEffectiveEvent::ValueList effectiveEvents( const QDateTime& start );
+
+ /**
+ * Effective Events are special event occuring during a time frame. This method does calcualte
+ * EffectiveEvents bases on the directNonRepeats and directRawRepeats. You may implement this method
+ * yourself
+ */
+ virtual OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDate& from, const QDate& to );
+
+ /**
+ * this is an overloaded member function
+ * @see effectiveNonRepeatingEvents( const QDate& from, const QDate& to )
+ */
+ virtual OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDateTime& start );
+
+private:
+ class Private;
+ Private *d;
+
+};
+
+#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 @@
+/*
+ * SQL Backend for the OPIE-Calender Database.
+ *
+ * Copyright (c) 2003 by Stefan Eilers (Eilers.Stefan@epost.de)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * =====================================================================
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2004/11/16 21:46:08 mickeyl
+ * libopie1 goes into unsupported
+ *
+ * Revision 1.4 2004/03/14 13:50:35 alwin
+ * namespace correction
+ *
+ * Revision 1.3 2003/12/22 11:41:39 eilers
+ * Fixing stupid bug, found by sourcode review..
+ *
+ * Revision 1.2 2003/12/22 10:19:26 eilers
+ * Finishing implementation of sql-backend for datebook. But I have to
+ * port the PIM datebook application to use it, before I could debug the
+ * whole stuff.
+ * Thus, PIM-Database backend is finished, but highly experimental. And some
+ * parts are still generic. For instance, the "queryByExample()" methods are
+ * not (or not fully) implemented. Todo: custom-entries not stored.
+ * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
+ * expression search in the database, which is not supported by sqlite !
+ * Therefore we need either an extended sqlite or a workaround which would
+ * be very slow and memory consuming..
+ *
+ * Revision 1.1 2003/12/08 15:18:12 eilers
+ * Committing unfinished sql implementation before merging to libopie2 starts..
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <qarray.h>
+#include <qstringlist.h>
+
+#include <qpe/global.h>
+
+#include <opie2/osqldriver.h>
+#include <opie2/osqlmanager.h>
+#include <opie2/osqlquery.h>
+
+#include "orecur.h"
+#include "odatebookaccessbackend_sql.h"
+
+using namespace Opie::DB;
+
+
+ODateBookAccessBackend_SQL::ODateBookAccessBackend_SQL( const QString& ,
+ const QString& fileName )
+ : ODateBookAccessBackend(), m_driver( NULL )
+{
+ m_fileName = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.db" ) : fileName;
+
+ // Get the standart sql-driver from the OSQLManager..
+ OSQLManager man;
+ m_driver = man.standard();
+ m_driver->setUrl( m_fileName );
+
+ initFields();
+
+ load();
+}
+
+ODateBookAccessBackend_SQL::~ODateBookAccessBackend_SQL() {
+ if( m_driver )
+ delete m_driver;
+}
+
+void ODateBookAccessBackend_SQL::initFields()
+{
+
+ // This map contains the translation of the fieldtype id's to
+ // the names of the table columns
+ m_fieldMap.insert( OEvent::FUid, "uid" );
+ m_fieldMap.insert( OEvent::FCategories, "Categories" );
+ m_fieldMap.insert( OEvent::FDescription, "Description" );
+ m_fieldMap.insert( OEvent::FLocation, "Location" );
+ m_fieldMap.insert( OEvent::FType, "Type" );
+ m_fieldMap.insert( OEvent::FAlarm, "Alarm" );
+ m_fieldMap.insert( OEvent::FSound, "Sound" );
+ m_fieldMap.insert( OEvent::FRType, "RType" );
+ m_fieldMap.insert( OEvent::FRWeekdays, "RWeekdays" );
+ m_fieldMap.insert( OEvent::FRPosition, "RPosition" );
+ m_fieldMap.insert( OEvent::FRFreq, "RFreq" );
+ m_fieldMap.insert( OEvent::FRHasEndDate, "RHasEndDate" );
+ m_fieldMap.insert( OEvent::FREndDate, "REndDate" );
+ m_fieldMap.insert( OEvent::FRCreated, "RCreated" );
+ m_fieldMap.insert( OEvent::FRExceptions, "RExceptions" );
+ m_fieldMap.insert( OEvent::FStart, "Start" );
+ m_fieldMap.insert( OEvent::FEnd, "End" );
+ m_fieldMap.insert( OEvent::FNote, "Note" );
+ m_fieldMap.insert( OEvent::FTimeZone, "TimeZone" );
+ m_fieldMap.insert( OEvent::FRecParent, "RecParent" );
+ m_fieldMap.insert( OEvent::FRecChildren, "Recchildren" );
+
+ // Create a map that maps the column name to the id
+ QMapConstIterator<int, QString> it;
+ for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
+ m_reverseFieldMap.insert( it.data(), it.key() );
+ }
+
+}
+
+bool ODateBookAccessBackend_SQL::load()
+{
+ if (!m_driver->open() )
+ return false;
+
+ // Don't expect that the database exists.
+ // It is save here to create the table, even if it
+ // do exist. ( Is that correct for all databases ?? )
+ QString qu = "create table datebook( uid INTEGER PRIMARY KEY ";
+
+ QMap<int, QString>::Iterator it;
+ for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
+ qu += QString( ",%1 VARCHAR(10)" ).arg( it.data() );
+ }
+ qu += " );";
+
+ qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
+
+ qWarning( "command: %s", qu.latin1() );
+
+ OSQLRawQuery raw( qu );
+ OSQLResult res = m_driver->query( &raw );
+ if ( res.state() != OSQLResult::Success )
+ return false;
+
+ update();
+
+ return true;
+}
+
+void ODateBookAccessBackend_SQL::update()
+{
+
+ QString qu = "select uid from datebook";
+ OSQLRawQuery raw( qu );
+ OSQLResult res = m_driver->query( &raw );
+ if ( res.state() != OSQLResult::Success ){
+ // m_uids.clear();
+ return;
+ }
+
+ m_uids = extractUids( res );
+
+}
+
+bool ODateBookAccessBackend_SQL::reload()
+{
+ return load();
+}
+
+bool ODateBookAccessBackend_SQL::save()
+{
+ return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
+}
+
+QArray<int> ODateBookAccessBackend_SQL::allRecords()const
+{
+ return m_uids;
+}
+
+QArray<int> ODateBookAccessBackend_SQL::queryByExample(const OEvent&, int, const QDateTime& ) {
+ return QArray<int>();
+}
+
+void ODateBookAccessBackend_SQL::clear()
+{
+ QString qu = "drop table datebook;";
+ qu += "drop table custom_data;";
+
+ OSQLRawQuery raw( qu );
+ OSQLResult res = m_driver->query( &raw );
+
+ reload();
+}
+
+
+OEvent ODateBookAccessBackend_SQL::find( int uid ) const{
+ QString qu = "select *";
+ qu += "from datebook where uid = " + QString::number(uid);
+
+ OSQLRawQuery raw( qu );
+ OSQLResult res = m_driver->query( &raw );
+
+ OSQLResultItem resItem = res.first();
+
+ // Create Map for date event and insert UID
+ QMap<int,QString> dateEventMap;
+ dateEventMap.insert( OEvent::FUid, QString::number( uid ) );
+
+ // Now insert the data out of the columns into the map.
+ QMapConstIterator<int, QString> it;
+ for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
+ dateEventMap.insert( m_reverseFieldMap[*it], resItem.data( *it ) );
+ }
+
+ // Last step: Put map into date event and return it
+ OEvent retDate( dateEventMap );
+
+ return retDate;
+}
+
+// FIXME: Speed up update of uid's..
+bool ODateBookAccessBackend_SQL::add( const OEvent& ev )
+{
+ QMap<int,QString> eventMap = ev.toMap();
+
+ QString qu = "insert into datebook VALUES( " + QString::number( ev.uid() );
+ QMap<int, QString>::Iterator it;
+ for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
+ if ( !eventMap[it.key()].isEmpty() )
+ qu += QString( ",\"%1\"" ).arg( eventMap[it.key()] );
+ else
+ qu += QString( ",\"\"" );
+ }
+ qu += " );";
+
+ // Add custom entries
+ int id = 0;
+ QMap<QString, QString> customMap = ev.toExtraMap();
+ for( QMap<QString, QString>::Iterator it = customMap.begin();
+ it != customMap.end(); ++it ){
+ qu += "insert into custom_data VALUES("
+ + QString::number( ev.uid() )
+ + ","
+ + QString::number( id++ )
+ + ",'"
+ + it.key() //.latin1()
+ + "',"
+ + "0" // Priority for future enhancements
+ + ",'"
+ + it.data() //.latin1()
+ + "');";
+ }
+ qWarning("add %s", qu.latin1() );
+
+ OSQLRawQuery raw( qu );
+ OSQLResult res = m_driver->query( &raw );
+ if ( res.state() != OSQLResult::Success ){
+ return false;
+ }
+
+ // Update list of uid's
+ update();
+
+ return true;
+}
+
+// FIXME: Speed up update of uid's..
+bool ODateBookAccessBackend_SQL::remove( int uid )
+{
+ QString qu = "DELETE from datebook where uid = "
+ + QString::number( uid ) + ";";
+ qu += "DELETE from custom_data where uid = "
+ + QString::number( uid ) + ";";
+
+ OSQLRawQuery raw( qu );
+ OSQLResult res = m_driver->query( &raw );
+ if ( res.state() != OSQLResult::Success ){
+ return false;
+ }
+
+ // Update list of uid's
+ update();
+
+ return true;
+}
+
+bool ODateBookAccessBackend_SQL::replace( const OEvent& ev )
+{
+ remove( ev.uid() );
+ return add( ev );
+}
+
+QArray<int> ODateBookAccessBackend_SQL::rawEvents()const
+{
+ return allRecords();
+}
+
+QArray<int> ODateBookAccessBackend_SQL::rawRepeats()const
+{
+ QString qu = "select uid from datebook where RType!=\"\" AND RType!=\"NoRepeat\"";
+ OSQLRawQuery raw( qu );
+ OSQLResult res = m_driver->query( &raw );
+ if ( res.state() != OSQLResult::Success ){
+ QArray<int> nix;
+ return nix;
+ }
+
+ return extractUids( res );
+}
+
+QArray<int> ODateBookAccessBackend_SQL::nonRepeats()const
+{
+ QString qu = "select uid from datebook where RType=\"\" or RType=\"NoRepeat\"";
+ OSQLRawQuery raw( qu );
+ OSQLResult res = m_driver->query( &raw );
+ if ( res.state() != OSQLResult::Success ){
+ QArray<int> nix;
+ return nix;
+ }
+
+ return extractUids( res );
+}
+
+OEvent::ValueList ODateBookAccessBackend_SQL::directNonRepeats()
+{
+ QArray<int> nonRepUids = nonRepeats();
+ OEvent::ValueList list;
+
+ for (uint i = 0; i < nonRepUids.count(); ++i ){
+ list.append( find( nonRepUids[i] ) );
+ }
+
+ return list;
+
+}
+OEvent::ValueList ODateBookAccessBackend_SQL::directRawRepeats()
+{
+ QArray<int> rawRepUids = rawRepeats();
+ OEvent::ValueList list;
+
+ for (uint i = 0; i < rawRepUids.count(); ++i ){
+ list.append( find( rawRepUids[i] ) );
+ }
+
+ return list;
+}
+
+
+QArray<int> ODateBookAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
+{
+ QArray<int> null;
+ return null;
+}
+
+/* ===== Private Functions ========================================== */
+
+QArray<int> ODateBookAccessBackend_SQL::extractUids( OSQLResult& res ) const
+{
+ qWarning("extractUids");
+ QTime t;
+ t.start();
+ OSQLResultItem::ValueList list = res.results();
+ OSQLResultItem::ValueList::Iterator it;
+ QArray<int> ints(list.count() );
+ qWarning(" count = %d", list.count() );
+
+ int i = 0;
+ for (it = list.begin(); it != list.end(); ++it ) {
+ ints[i] = (*it).data("uid").toInt();
+ i++;
+ }
+ qWarning("extractUids ready: count2 = %d needs %d ms", i, t.elapsed() );
+
+ return ints;
+
+}
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 @@
+#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
+#define OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
+
+#include <qmap.h>
+#include <opie2/osqlresult.h>
+
+#include "odatebookaccessbackend.h"
+
+namespace Opie { namespace DB {
+class OSQLDriver;
+
+}}
+
+/**
+ * This is the default SQL implementation for DateBoook SQL storage
+ * It fully implements the interface
+ * @see ODateBookAccessBackend
+ * @see OPimAccessBackend
+ */
+class ODateBookAccessBackend_SQL : public ODateBookAccessBackend {
+public:
+ ODateBookAccessBackend_SQL( const QString& appName,
+ const QString& fileName = QString::null);
+ ~ODateBookAccessBackend_SQL();
+
+ bool load();
+ bool reload();
+ bool save();
+
+ QArray<int> allRecords()const;
+ QArray<int> matchRegexp(const QRegExp &r) const;
+ QArray<int> queryByExample( const OEvent&, int, const QDateTime& d = QDateTime() );
+ OEvent find( int uid )const;
+ void clear();
+ bool add( const OEvent& ev );
+ bool remove( int uid );
+ bool replace( const OEvent& ev );
+
+ QArray<UID> rawEvents()const;
+ QArray<UID> rawRepeats()const;
+ QArray<UID> nonRepeats()const;
+
+ OEvent::ValueList directNonRepeats();
+ OEvent::ValueList directRawRepeats();
+
+private:
+ bool loadFile();
+ QString m_fileName;
+ QArray<int> m_uids;
+
+ QMap<int, QString> m_fieldMap;
+ QMap<QString, int> m_reverseFieldMap;
+
+ Opie::DB::OSQLDriver* m_driver;
+
+ class Private;
+ Private *d;
+
+ void initFields();
+ void update();
+ QArray<int> extractUids( Opie::DB::OSQLResult& res ) const;
+
+};
+
+#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 @@
+#include <errno.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <unistd.h>
+
+#include <qasciidict.h>
+#include <qfile.h>
+
+#include <qtopia/global.h>
+#include <qtopia/stringutil.h>
+#include <qtopia/timeconversion.h>
+
+#include "opimnotifymanager.h"
+#include "orecur.h"
+#include "otimezone.h"
+#include "odatebookaccessbackend_xml.h"
+
+namespace {
+ // FROM TT again
+char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
+{
+ char needleChar;
+ char haystackChar;
+ if (!needle || !haystack || !hLen || !nLen)
+ return 0;
+
+ const char* hsearch = haystack;
+
+ if ((needleChar = *needle++) != 0) {
+ nLen--; //(to make up for needle++)
+ do {
+ do {
+ if ((haystackChar = *hsearch++) == 0)
+ return (0);
+ if (hsearch >= haystack + hLen)
+ return (0);
+ } while (haystackChar != needleChar);
+ } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
+ hsearch--;
+ }
+ return ((char *)hsearch);
+}
+}
+
+namespace {
+ time_t start, end, created, rp_end;
+ ORecur* rec;
+ ORecur* recur() {
+ if (!rec)
+ rec = new ORecur;
+
+ return rec;
+ }
+ int alarmTime;
+ int snd;
+ enum Attribute{
+ FDescription = 0,
+ FLocation,
+ FCategories,
+ FUid,
+ FType,
+ FAlarm,
+ FSound,
+ FRType,
+ FRWeekdays,
+ FRPosition,
+ FRFreq,
+ FRHasEndDate,
+ FREndDate,
+ FRStart,
+ FREnd,
+ FNote,
+ FCreated, // Should't this be called FRCreated ?
+ FTimeZone,
+ FRecParent,
+ FRecChildren,
+ FExceptions
+ };
+
+ // FIXME: Use OEvent::toMap() here !! (eilers)
+ inline void save( const OEvent& ev, QString& buf ) {
+ qWarning("Saving %d %s", ev.uid(), ev.description().latin1() );
+ buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\"";
+ if (!ev.location().isEmpty() )
+ buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\"";
+
+ buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\"";
+ buf += " uid=\"" + QString::number( ev.uid() ) + "\"";
+
+ if (ev.isAllDay() )
+ buf += " type=\"AllDay\""; // is that all ?? (eilers)
+
+ if (ev.hasNotifiers() ) {
+ OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first
+ int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60;
+ buf += " alarm=\"" + QString::number(minutes) + "\" sound=\"";
+ if ( alarm.sound() == OPimAlarm::Loud )
+ buf += "loud";
+ else
+ buf += "silent";
+ buf += "\"";
+ }
+ if ( ev.hasRecurrence() ) {
+ buf += ev.recurrence().toString();
+ }
+
+ /*
+ * fscking timezones :) well, we'll first convert
+ * the QDateTime to a QDateTime in UTC time
+ * and then we'll create a nice time_t
+ */
+ OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
+ buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\"";
+ buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\"";
+ if (!ev.note().isEmpty() ) {
+ buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\"";
+ }
+
+ buf += " timezone=\"";
+ if ( ev.timeZone().isEmpty() )
+ buf += "None";
+ else
+ buf += ev.timeZone();
+ buf += "\"";
+
+ if (ev.parent() != 0 ) {
+ buf += " recparent=\""+QString::number(ev.parent() )+"\"";
+ }
+
+ if (ev.children().count() != 0 ) {
+ QArray<int> children = ev.children();
+ buf += " recchildren=\"";
+ for ( uint i = 0; i < children.count(); i++ ) {
+ if ( i != 0 ) buf += " ";
+ buf += QString::number( children[i] );
+ }
+ buf+= "\"";
+ }
+
+ // skip custom writing
+ }
+
+ inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) {
+ QMap<int, OEvent>::ConstIterator it;
+ QString buf;
+ QCString str;
+ int total_written;
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ buf = "<event";
+ save( it.data(), buf );
+ buf += " />\n";
+ str = buf.utf8();
+
+ total_written = file.writeBlock(str.data(), str.length() );
+ if ( total_written != int(str.length() ) )
+ return false;
+ }
+ return true;
+ }
+}
+
+ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& ,
+ const QString& fileName )
+ : ODateBookAccessBackend() {
+ m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName;
+ m_changed = false;
+}
+ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() {
+}
+bool ODateBookAccessBackend_XML::load() {
+ return loadFile();
+}
+bool ODateBookAccessBackend_XML::reload() {
+ clear();
+ return load();
+}
+bool ODateBookAccessBackend_XML::save() {
+ if (!m_changed) return true;
+
+ int total_written;
+ QString strFileNew = m_name + ".new";
+
+ QFile f( strFileNew );
+ if (!f.open( IO_WriteOnly | IO_Raw ) ) return false;
+
+ QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
+ buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n";
+ buf += "<events>\n";
+ QCString str = buf.utf8();
+ total_written = f.writeBlock( str.data(), str.length() );
+ if ( total_written != int(str.length() ) ) {
+ f.close();
+ QFile::remove( strFileNew );
+ return false;
+ }
+
+ if (!forAll( m_raw, f ) ) {
+ f.close();
+ QFile::remove( strFileNew );
+ return false;
+ }
+ if (!forAll( m_rep, f ) ) {
+ f.close();
+ QFile::remove( strFileNew );
+ return false;
+ }
+
+ buf = "</events>\n</DATEBOOK>\n";
+ str = buf.utf8();
+ total_written = f.writeBlock( str.data(), str.length() );
+ if ( total_written != int(str.length() ) ) {
+ f.close();
+ QFile::remove( strFileNew );
+ return false;
+ }
+ f.close();
+
+ if ( ::rename( strFileNew, m_name ) < 0 ) {
+ QFile::remove( strFileNew );
+ return false;
+ }
+
+ m_changed = false;
+ return true;
+}
+QArray<int> ODateBookAccessBackend_XML::allRecords()const {
+ QArray<int> ints( m_raw.count()+ m_rep.count() );
+ uint i = 0;
+ QMap<int, OEvent>::ConstIterator it;
+
+ for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
+ ints[i] = it.key();
+ i++;
+ }
+ for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
+ ints[i] = it.key();
+ i++;
+ }
+
+ return ints;
+}
+QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) {
+ return QArray<int>();
+}
+void ODateBookAccessBackend_XML::clear() {
+ m_changed = true;
+ m_raw.clear();
+ m_rep.clear();
+}
+OEvent ODateBookAccessBackend_XML::find( int uid ) const{
+ if ( m_raw.contains( uid ) )
+ return m_raw[uid];
+ else
+ return m_rep[uid];
+}
+bool ODateBookAccessBackend_XML::add( const OEvent& ev ) {
+ m_changed = true;
+ if (ev.hasRecurrence() )
+ m_rep.insert( ev.uid(), ev );
+ else
+ m_raw.insert( ev.uid(), ev );
+
+ return true;
+}
+bool ODateBookAccessBackend_XML::remove( int uid ) {
+ m_changed = true;
+ m_rep.remove( uid );
+ m_rep.remove( uid );
+
+ return true;
+}
+bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) {
+ replace( ev.uid() ); // ??? Shouldn't this be "remove( ev.uid() ) ??? (eilers)
+ return add( ev );
+}
+QArray<int> ODateBookAccessBackend_XML::rawEvents()const {
+ return allRecords();
+}
+QArray<int> ODateBookAccessBackend_XML::rawRepeats()const {
+ QArray<int> ints( m_rep.count() );
+ uint i = 0;
+ QMap<int, OEvent>::ConstIterator it;
+
+ for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
+ ints[i] = it.key();
+ i++;
+ }
+
+ return ints;
+}
+QArray<int> ODateBookAccessBackend_XML::nonRepeats()const {
+ QArray<int> ints( m_raw.count() );
+ uint i = 0;
+ QMap<int, OEvent>::ConstIterator it;
+
+ for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
+ ints[i] = it.key();
+ i++;
+ }
+
+ return ints;
+}
+OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() {
+ OEvent::ValueList list;
+ QMap<int, OEvent>::ConstIterator it;
+ for (it = m_raw.begin(); it != m_raw.end(); ++it )
+ list.append( it.data() );
+
+ return list;
+}
+OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() {
+ OEvent::ValueList list;
+ QMap<int, OEvent>::ConstIterator it;
+ for (it = m_rep.begin(); it != m_rep.end(); ++it )
+ list.append( it.data() );
+
+ return list;
+}
+
+// FIXME: Use OEvent::fromMap() (eilers)
+bool ODateBookAccessBackend_XML::loadFile() {
+ m_changed = false;
+
+ int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY );
+ if ( fd < 0 ) return false;
+
+ struct stat attribute;
+ if ( ::fstat(fd, &attribute ) == -1 ) {
+ ::close( fd );
+ return false;
+ }
+ void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 );
+ if ( map_addr == ( (caddr_t)-1) ) {
+ ::close( fd );
+ return false;
+ }
+
+ ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL );
+ ::close( fd );
+
+ QAsciiDict<int> dict(FExceptions+1);
+ dict.setAutoDelete( true );
+ dict.insert( "description", new int(FDescription) );
+ dict.insert( "location", new int(FLocation) );
+ dict.insert( "categories", new int(FCategories) );
+ dict.insert( "uid", new int(FUid) );
+ dict.insert( "type", new int(FType) );
+ dict.insert( "alarm", new int(FAlarm) );
+ dict.insert( "sound", new int(FSound) );
+ dict.insert( "rtype", new int(FRType) );
+ dict.insert( "rweekdays", new int(FRWeekdays) );
+ dict.insert( "rposition", new int(FRPosition) );
+ dict.insert( "rfreq", new int(FRFreq) );
+ dict.insert( "rhasenddate", new int(FRHasEndDate) );
+ dict.insert( "enddt", new int(FREndDate) );
+ dict.insert( "start", new int(FRStart) );
+ dict.insert( "end", new int(FREnd) );
+ dict.insert( "note", new int(FNote) );
+ dict.insert( "created", new int(FCreated) ); // Shouldn't this be FRCreated ??
+ dict.insert( "recparent", new int(FRecParent) );
+ dict.insert( "recchildren", new int(FRecChildren) );
+ dict.insert( "exceptions", new int(FExceptions) );
+ dict.insert( "timezone", new int(FTimeZone) );
+
+ char* dt = (char*)map_addr;
+ int len = attribute.st_size;
+ int i = 0;
+ char* point;
+ const char* collectionString = "<event ";
+ int strLen = ::strlen(collectionString);
+ int *find;
+ while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) {
+ i = point -dt;
+ i+= strLen;
+
+ alarmTime = -1;
+ snd = 0; // silent
+
+ OEvent ev;
+ rec = 0;
+
+ while ( TRUE ) {
+ while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
+ ++i;
+ if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
+ break;
+
+
+ // we have another attribute, read it.
+ int j = i;
+ while ( j < len && dt[j] != '=' )
+ ++j;
+ QCString attr( dt+i, j-i+1);
+
+ i = ++j; // skip =
+
+ // find the start of quotes
+ while ( i < len && dt[i] != '"' )
+ ++i;
+ j = ++i;
+
+ bool haveUtf = FALSE;
+ bool haveEnt = FALSE;
+ while ( j < len && dt[j] != '"' ) {
+ if ( ((unsigned char)dt[j]) > 0x7f )
+ haveUtf = TRUE;
+ if ( dt[j] == '&' )
+ haveEnt = TRUE;
+ ++j;
+ }
+ if ( i == j ) {
+ // empty value
+ i = j + 1;
+ continue;
+ }
+
+ QCString value( dt+i, j-i+1 );
+ i = j + 1;
+
+ QString str = (haveUtf ? QString::fromUtf8( value )
+ : QString::fromLatin1( value ) );
+ if ( haveEnt )
+ str = Qtopia::plainString( str );
+
+ /*
+ * add key + value
+ */
+ find = dict[attr.data()];
+ if (!find)
+ ev.setCustomField( attr, str );
+ else {
+ setField( ev, *find, str );
+ }
+ }
+ /* time to finalize */
+ finalizeRecord( ev );
+ delete rec;
+ }
+ ::munmap(map_addr, attribute.st_size );
+ m_changed = false; // changed during add
+
+ return true;
+}
+
+// FIXME: Use OEvent::fromMap() which makes this obsolete.. (eilers)
+void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) {
+ /* AllDay is alway in UTC */
+ if ( ev.isAllDay() ) {
+ OTimeZone utc = OTimeZone::utc();
+ ev.setStartDateTime( utc.fromUTCDateTime( start ) );
+ ev.setEndDateTime ( utc.fromUTCDateTime( end ) );
+ ev.setTimeZone( "UTC"); // make sure it is really utc
+ }else {
+ /* to current date time */
+ // qWarning(" Start is %d", start );
+ OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
+ QDateTime date = zone.toDateTime( start );
+ qWarning(" Start is %s", date.toString().latin1() );
+ ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
+
+ date = zone.toDateTime( end );
+ ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
+ }
+ if ( rec && rec->doesRecur() ) {
+ OTimeZone utc = OTimeZone::utc();
+ ORecur recu( *rec ); // call copy c'tor;
+ recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() );
+ recu.setCreatedDateTime( utc.fromUTCDateTime( created ) );
+ recu.setStart( ev.startDateTime().date() );
+ ev.setRecurrence( recu );
+ }
+
+ if (alarmTime != -1 ) {
+ QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 );
+ OPimAlarm al( snd , dt );
+ ev.notifiers().add( al );
+ }
+ if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) {
+ qWarning("already contains assign uid");
+ ev.setUid( 1 );
+ }
+ qWarning("addind %d %s", ev.uid(), ev.description().latin1() );
+ if ( ev.hasRecurrence() )
+ m_rep.insert( ev.uid(), ev );
+ else
+ m_raw.insert( ev.uid(), ev );
+
+}
+void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) {
+// qWarning(" setting %s", value.latin1() );
+ switch( id ) {
+ case FDescription:
+ e.setDescription( value );
+ break;
+ case FLocation:
+ e.setLocation( value );
+ break;
+ case FCategories:
+ e.setCategories( e.idsFromString( value ) );
+ break;
+ case FUid:
+ e.setUid( value.toInt() );
+ break;
+ case FType:
+ if ( value == "AllDay" ) {
+ e.setAllDay( true );
+ e.setTimeZone( "UTC" );
+ }
+ break;
+ case FAlarm:
+ alarmTime = value.toInt();
+ break;
+ case FSound:
+ snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent;
+ break;
+ // recurrence stuff
+ case FRType:
+ if ( value == "Daily" )
+ recur()->setType( ORecur::Daily );
+ else if ( value == "Weekly" )
+ recur()->setType( ORecur::Weekly);
+ else if ( value == "MonthlyDay" )
+ recur()->setType( ORecur::MonthlyDay );
+ else if ( value == "MonthlyDate" )
+ recur()->setType( ORecur::MonthlyDate );
+ else if ( value == "Yearly" )
+ recur()->setType( ORecur::Yearly );
+ else
+ recur()->setType( ORecur::NoRepeat );
+ break;
+ case FRWeekdays:
+ recur()->setDays( value.toInt() );
+ break;
+ case FRPosition:
+ recur()->setPosition( value.toInt() );
+ break;
+ case FRFreq:
+ recur()->setFrequency( value.toInt() );
+ break;
+ case FRHasEndDate:
+ recur()->setHasEndDate( value.toInt() );
+ break;
+ case FREndDate: {
+ rp_end = (time_t) value.toLong();
+ break;
+ }
+ case FRStart: {
+ start = (time_t) value.toLong();
+ break;
+ }
+ case FREnd: {
+ end = ( (time_t) value.toLong() );
+ break;
+ }
+ case FNote:
+ e.setNote( value );
+ break;
+ case FCreated:
+ created = value.toInt();
+ break;
+ case FRecParent:
+ e.setParent( value.toInt() );
+ break;
+ case FRecChildren:{
+ QStringList list = QStringList::split(' ', value );
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
+ e.addChild( (*it).toInt() );
+ }
+ }
+ break;
+ case FExceptions:{
+ QStringList list = QStringList::split(' ', value );
+ for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
+ QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() );
+ qWarning("adding exception %s", date.toString().latin1() );
+ recur()->exceptions().append( date );
+ }
+ }
+ break;
+ case FTimeZone:
+ if ( value != "None" )
+ e.setTimeZone( value );
+ break;
+ default:
+ break;
+ }
+}
+QArray<int> ODateBookAccessBackend_XML::matchRegexp( const QRegExp &r ) const
+{
+ QArray<int> m_currentQuery( m_raw.count()+ m_rep.count() );
+ uint arraycounter = 0;
+ QMap<int, OEvent>::ConstIterator it;
+
+ for ( it = m_raw.begin(); it != m_raw.end(); ++it )
+ if ( it.data().match( r ) )
+ m_currentQuery[arraycounter++] = it.data().uid();
+ for ( it = m_rep.begin(); it != m_rep.end(); ++it )
+ if ( it.data().match( r ) )
+ m_currentQuery[arraycounter++] = it.data().uid();
+
+ // Shrink to fit..
+ m_currentQuery.resize(arraycounter);
+
+ return m_currentQuery;
+}
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 @@
+#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H
+#define OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H
+
+#include <qmap.h>
+
+#include "odatebookaccessbackend.h"
+
+/**
+ * This is the default XML implementation for DateBoook XML storage
+ * It fully implements the interface
+ * @see ODateBookAccessBackend
+ * @see OPimAccessBackend
+ */
+class ODateBookAccessBackend_XML : public ODateBookAccessBackend {
+public:
+ ODateBookAccessBackend_XML( const QString& appName,
+ const QString& fileName = QString::null);
+ ~ODateBookAccessBackend_XML();
+
+ bool load();
+ bool reload();
+ bool save();
+
+ QArray<int> allRecords()const;
+ QArray<int> matchRegexp(const QRegExp &r) const;
+ QArray<int> queryByExample( const OEvent&, int, const QDateTime& d = QDateTime() );
+ OEvent find( int uid )const;
+ void clear();
+ bool add( const OEvent& ev );
+ bool remove( int uid );
+ bool replace( const OEvent& ev );
+
+ QArray<UID> rawEvents()const;
+ QArray<UID> rawRepeats()const;
+ QArray<UID> nonRepeats()const;
+
+ OEvent::ValueList directNonRepeats();
+ OEvent::ValueList directRawRepeats();
+
+private:
+ bool m_changed :1 ;
+ bool loadFile();
+ inline void finalizeRecord( OEvent& ev );
+ inline void setField( OEvent&, int field, const QString& val );
+ QString m_name;
+ QMap<int, OEvent> m_raw;
+ QMap<int, OEvent> m_rep;
+
+ struct Data;
+ Data* data;
+ class Private;
+ Private *d;
+};
+
+#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 @@
+#include <qshared.h>
+#include <qarray.h>
+
+#include <qpe/palmtopuidgen.h>
+#include <qpe/categories.h>
+#include <qpe/stringutil.h>
+
+#include "orecur.h"
+#include "opimresolver.h"
+#include "opimnotifymanager.h"
+
+#include "oevent.h"
+
+int OCalendarHelper::week( const QDate& date) {
+ // Calculates the week this date is in within that
+ // month. Equals the "row" is is in in the month view
+ int week = 1;
+ QDate tmp( date.year(), date.month(), 1 );
+ if ( date.dayOfWeek() < tmp.dayOfWeek() )
+ ++week;
+
+ week += ( date.day() - 1 ) / 7;
+
+ return week;
+}
+int OCalendarHelper::ocurrence( const QDate& date) {
+ // calculates the number of occurrances of this day of the
+ // week till the given date (e.g 3rd Wednesday of the month)
+ return ( date.day() - 1 ) / 7 + 1;
+}
+int OCalendarHelper::dayOfWeek( char day ) {
+ int dayOfWeek = 1;
+ char i = ORecur::MON;
+ while ( !( i & day ) && i <= ORecur::SUN ) {
+ i <<= 1;
+ ++dayOfWeek;
+ }
+ return dayOfWeek;
+}
+int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) {
+ return ( second.year() - first.year() ) * 12 +
+ second.month() - first.month();
+}
+
+struct OEvent::Data : public QShared {
+ Data() : QShared() {
+ child = 0;
+ recur = 0;
+ manager = 0;
+ isAllDay = false;
+ parent = 0;
+ }
+ ~Data() {
+ delete manager;
+ delete recur;
+ }
+ QString description;
+ QString location;
+ OPimNotifyManager* manager;
+ ORecur* recur;
+ QString note;
+ QDateTime created;
+ QDateTime start;
+ QDateTime end;
+ bool isAllDay : 1;
+ QString timezone;
+ QArray<int>* child;
+ int parent;
+};
+
+OEvent::OEvent( int uid )
+ : OPimRecord( uid ) {
+ data = new Data;
+}
+OEvent::OEvent( const OEvent& ev)
+ : OPimRecord( ev ), data( ev.data )
+{
+ data->ref();
+}
+
+OEvent::OEvent( const QMap<int, QString> map )
+ : OPimRecord( 0 )
+{
+ data = new Data;
+
+ fromMap( map );
+}
+
+OEvent::~OEvent() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0;
+ }
+}
+OEvent& OEvent::operator=( const OEvent& ev) {
+ if ( this == &ev ) return *this;
+
+ OPimRecord::operator=( ev );
+ ev.data->ref();
+ deref();
+ data = ev.data;
+
+
+ return *this;
+}
+QString OEvent::description()const {
+ return data->description;
+}
+void OEvent::setDescription( const QString& description ) {
+ changeOrModify();
+ data->description = description;
+}
+void OEvent::setLocation( const QString& loc ) {
+ changeOrModify();
+ data->location = loc;
+}
+QString OEvent::location()const {
+ return data->location;
+}
+OPimNotifyManager &OEvent::notifiers()const {
+ // I hope we can skip the changeOrModify here
+ // the notifier should take care of it
+ // and OPimNotify is shared too
+ if (!data->manager )
+ data->manager = new OPimNotifyManager;
+
+ return *data->manager;
+}
+bool OEvent::hasNotifiers()const {
+ if (!data->manager )
+ return false;
+ if (data->manager->reminders().isEmpty() &&
+ data->manager->alarms().isEmpty() )
+ return false;
+
+ return true;
+}
+ORecur OEvent::recurrence()const {
+ if (!data->recur)
+ data->recur = new ORecur;
+
+ return *data->recur;
+}
+void OEvent::setRecurrence( const ORecur& rec) {
+ changeOrModify();
+ if (data->recur )
+ (*data->recur) = rec;
+ else
+ data->recur = new ORecur( rec );
+}
+bool OEvent::hasRecurrence()const {
+ if (!data->recur ) return false;
+ return data->recur->doesRecur();
+}
+QString OEvent::note()const {
+ return data->note;
+}
+void OEvent::setNote( const QString& note ) {
+ changeOrModify();
+ data->note = note;
+}
+QDateTime OEvent::createdDateTime()const {
+ return data->created;
+}
+void OEvent::setCreatedDateTime( const QDateTime& time ) {
+ changeOrModify();
+ data->created = time;
+}
+QDateTime OEvent::startDateTime()const {
+ if ( data->isAllDay )
+ return QDateTime( data->start.date(), QTime(0, 0, 0 ) );
+ return data->start;
+}
+QDateTime OEvent::startDateTimeInZone()const {
+ /* if no timezone, or all day event or if the current and this timeZone match... */
+ if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime();
+
+ OTimeZone zone(data->timezone );
+ return zone.toDateTime( data->start, OTimeZone::current() );
+}
+void OEvent::setStartDateTime( const QDateTime& dt ) {
+ changeOrModify();
+ data->start = dt;
+}
+QDateTime OEvent::endDateTime()const {
+ /*
+ * if all Day event the end time needs
+ * to be on the same day as the start
+ */
+ if ( data->isAllDay )
+ return QDateTime( data->start.date(), QTime(23, 59, 59 ) );
+ return data->end;
+}
+QDateTime OEvent::endDateTimeInZone()const {
+ /* if no timezone, or all day event or if the current and this timeZone match... */
+ if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime();
+
+ OTimeZone zone(data->timezone );
+ return zone.toDateTime( data->end, OTimeZone::current() );
+}
+void OEvent::setEndDateTime( const QDateTime& dt ) {
+ changeOrModify();
+ data->end = dt;
+}
+bool OEvent::isMultipleDay()const {
+ return data->end.date().day() - data->start.date().day();
+}
+bool OEvent::isAllDay()const {
+ return data->isAllDay;
+}
+void OEvent::setAllDay( bool allDay ) {
+ changeOrModify();
+ data->isAllDay = allDay;
+ if (allDay ) data->timezone = "UTC";
+}
+void OEvent::setTimeZone( const QString& tz ) {
+ changeOrModify();
+ data->timezone = tz;
+}
+QString OEvent::timeZone()const {
+ if (data->isAllDay ) return QString::fromLatin1("UTC");
+ return data->timezone;
+}
+bool OEvent::match( const QRegExp& re )const {
+ if ( re.match( data->description ) != -1 ){
+ setLastHitField( Qtopia::DatebookDescription );
+ return true;
+ }
+ if ( re.match( data->note ) != -1 ){
+ setLastHitField( Qtopia::Note );
+ return true;
+ }
+ if ( re.match( data->location ) != -1 ){
+ setLastHitField( Qtopia::Location );
+ return true;
+ }
+ if ( re.match( data->start.toString() ) != -1 ){
+ setLastHitField( Qtopia::StartDateTime );
+ return true;
+ }
+ if ( re.match( data->end.toString() ) != -1 ){
+ setLastHitField( Qtopia::EndDateTime );
+ return true;
+ }
+ return false;
+}
+QString OEvent::toRichText()const {
+ QString text, value;
+
+ // description
+ text += "<b><h3><img src=\"datebook/DateBook\">";
+ if ( !description().isEmpty() ) {
+ text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "" );
+ }
+ text += "</h3></b><br><hr><br>";
+
+ // location
+ if ( !(value = location()).isEmpty() ) {
+ text += "<b>" + QObject::tr( "Location:" ) + "</b> ";
+ text += Qtopia::escapeString(value) + "<br>";
+ }
+
+ // all day event
+ if ( isAllDay() ) {
+ text += "<b><i>" + QObject::tr( "This is an all day event" ) + "</i></b><br>";
+ }
+ // multiple day event
+ else if ( isMultipleDay () ) {
+ text += "<b><i>" + QObject::tr( "This is a multiple day event" ) + "</i></b><br>";
+ }
+ // start & end times
+ else {
+ // start time
+ if ( startDateTime().isValid() ) {
+ text += "<b>" + QObject::tr( "Start:") + "</b> ";
+ text += Qtopia::escapeString(startDateTime().toString() ).
+ replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
+ }
+
+ // end time
+ if ( endDateTime().isValid() ) {
+ text += "<b>" + QObject::tr( "End:") + "</b> ";
+ text += Qtopia::escapeString(endDateTime().toString() ).
+ replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
+ }
+ }
+
+ // categories
+ if ( categoryNames("Calendar").count() ){
+ text += "<b>" + QObject::tr( "Category:") + "</b> ";
+ text += categoryNames("Calendar").join(", ");
+ text += "<br>";
+ }
+
+ //notes
+ if ( !note().isEmpty() ) {
+ text += "<b>" + QObject::tr( "Note:") + "</b><br>";
+ text += note();
+// text += Qtopia::escapeString(note() ).
+// replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
+ }
+ return text;
+}
+QString OEvent::toShortText()const {
+ QString text;
+ text += QString::number( startDateTime().date().day() );
+ text += ".";
+ text += QString::number( startDateTime().date().month() );
+ text += ".";
+ text += QString::number( startDateTime().date().year() );
+ text += " ";
+ text += QString::number( startDateTime().time().hour() );
+ text += ":";
+ text += QString::number( startDateTime().time().minute() );
+ text += " - ";
+ text += description();
+ return text;
+}
+QString OEvent::type()const {
+ return QString::fromLatin1("OEvent");
+}
+QString OEvent::recordField( int /*id */ )const {
+ return QString::null;
+}
+int OEvent::rtti() {
+ return OPimResolver::DateBook;
+}
+bool OEvent::loadFromStream( QDataStream& ) {
+ return true;
+}
+bool OEvent::saveToStream( QDataStream& )const {
+ return true;
+}
+void OEvent::changeOrModify() {
+ if ( data->count != 1 ) {
+ data->deref();
+ Data* d2 = new Data;
+ d2->description = data->description;
+ d2->location = data->location;
+
+ if (data->manager )
+ d2->manager = new OPimNotifyManager( *data->manager );
+
+ if ( data->recur )
+ d2->recur = new ORecur( *data->recur );
+
+ d2->note = data->note;
+ d2->created = data->created;
+ d2->start = data->start;
+ d2->end = data->end;
+ d2->isAllDay = data->isAllDay;
+ d2->timezone = data->timezone;
+ d2->parent = data->parent;
+
+ if ( data->child ) {
+ d2->child = new QArray<int>( *data->child );
+ d2->child->detach();
+ }
+
+ data = d2;
+ }
+}
+void OEvent::deref() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0;
+ }
+}
+// Exporting Event data to map. Using the same
+// encoding as ODateBookAccessBackend_xml does..
+// Thus, we could remove the stuff there and use this
+// for it and for all other places..
+// Encoding should happen at one place, only ! (eilers)
+QMap<int, QString> OEvent::toMap()const {
+ QMap<int, QString> retMap;
+
+ retMap.insert( OEvent::FUid, QString::number( uid() ) );
+ retMap.insert( OEvent::FCategories, Qtopia::escapeString( Qtopia::Record::idsToString( categories() ) ));
+ retMap.insert( OEvent::FDescription, Qtopia::escapeString( description() ) );
+ retMap.insert( OEvent::FLocation, Qtopia::escapeString( location() ) );
+ retMap.insert( OEvent::FType, isAllDay() ? "AllDay" : "" );
+ OPimAlarm alarm = notifiers().alarms()[0];
+ retMap.insert( OEvent::FAlarm, QString::number( alarm.dateTime().secsTo( startDateTime() ) / 60 ) );
+ retMap.insert( OEvent::FSound, (alarm.sound() == OPimAlarm::Loud) ? "loud" : "silent" );
+
+ OTimeZone zone( timeZone().isEmpty() ? OTimeZone::current() : timeZone() );
+ retMap.insert( OEvent::FStart, QString::number( zone.fromUTCDateTime( zone.toDateTime( startDateTime(), OTimeZone::utc() ) ) ) );
+ retMap.insert( OEvent::FEnd, QString::number( zone.fromUTCDateTime( zone.toDateTime( endDateTime(), OTimeZone::utc() ) ) ) );
+ retMap.insert( OEvent::FNote, Qtopia::escapeString( note() ) );
+ retMap.insert( OEvent::FTimeZone, timeZone().isEmpty() ? QString( "None" ) : timeZone() );
+ if( parent() )
+ retMap.insert( OEvent::FRecParent, QString::number( parent() ) );
+ if( children().count() ){
+ QArray<int> childr = children();
+ QString buf;
+ for ( uint i = 0; i < childr.count(); i++ ) {
+ if ( i != 0 ) buf += " ";
+ buf += QString::number( childr[i] );
+ }
+ retMap.insert( OEvent::FRecChildren, buf );
+ }
+
+ // Add recurrence stuff
+ if( hasRecurrence() ){
+ ORecur recur = recurrence();
+ QMap<int, QString> recFields = recur.toMap();
+ retMap.insert( OEvent::FRType, recFields[ORecur::RType] );
+ retMap.insert( OEvent::FRWeekdays, recFields[ORecur::RWeekdays] );
+ retMap.insert( OEvent::FRPosition, recFields[ORecur::RPosition] );
+ retMap.insert( OEvent::FRFreq, recFields[ORecur::RFreq] );
+ retMap.insert( OEvent::FRHasEndDate, recFields[ORecur::RHasEndDate] );
+ retMap.insert( OEvent::FREndDate, recFields[ORecur::EndDate] );
+ retMap.insert( OEvent::FRCreated, recFields[ORecur::Created] );
+ retMap.insert( OEvent::FRExceptions, recFields[ORecur::Exceptions] );
+ } else {
+ ORecur recur = recurrence();
+ QMap<int, QString> recFields = recur.toMap();
+ retMap.insert( OEvent::FRType, recFields[ORecur::RType] );
+ }
+
+ return retMap;
+}
+
+void OEvent::fromMap( const QMap<int, QString>& map )
+{
+
+ // We just want to set the UID if it is really stored.
+ if ( !map[OEvent::FUid].isEmpty() )
+ setUid( map[OEvent::FUid].toInt() );
+
+ setCategories( idsFromString( map[OEvent::FCategories] ) );
+ setDescription( map[OEvent::FDescription] );
+ setLocation( map[OEvent::FLocation] );
+
+ if ( map[OEvent::FType] == "AllDay" )
+ setAllDay( true );
+ else
+ setAllDay( false );
+
+ int alarmTime = -1;
+ if( !map[OEvent::FAlarm].isEmpty() )
+ alarmTime = map[OEvent::FAlarm].toInt();
+
+ int sound = ( ( map[OEvent::FSound] == "loud" ) ? OPimAlarm::Loud : OPimAlarm::Silent );
+ if ( ( alarmTime != -1 ) ){
+ QDateTime dt = startDateTime().addSecs( -1*alarmTime*60 );
+ OPimAlarm al( sound , dt );
+ notifiers().add( al );
+ }
+ if ( !map[OEvent::FTimeZone].isEmpty() && ( map[OEvent::FTimeZone] != "None" ) ){
+ setTimeZone( map[OEvent::FTimeZone] );
+ }
+
+ time_t start = (time_t) map[OEvent::FStart].toLong();
+ time_t end = (time_t) map[OEvent::FEnd].toLong();
+
+ /* AllDay is always in UTC */
+ if ( isAllDay() ) {
+ OTimeZone utc = OTimeZone::utc();
+ setStartDateTime( utc.fromUTCDateTime( start ) );
+ setEndDateTime ( utc.fromUTCDateTime( end ) );
+ setTimeZone( "UTC"); // make sure it is really utc
+ }else {
+ /* to current date time */
+ // qWarning(" Start is %d", start );
+ OTimeZone zone( timeZone().isEmpty() ? OTimeZone::current() : timeZone() );
+ QDateTime date = zone.toDateTime( start );
+ qWarning(" Start is %s", date.toString().latin1() );
+ setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
+
+ date = zone.toDateTime( end );
+ setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
+ }
+
+ if ( !map[OEvent::FRecParent].isEmpty() )
+ setParent( map[OEvent::FRecParent].toInt() );
+
+ if ( !map[OEvent::FRecChildren].isEmpty() ){
+ QStringList list = QStringList::split(' ', map[OEvent::FRecChildren] );
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
+ addChild( (*it).toInt() );
+ }
+ }
+
+ // Fill recurrence stuff and put it directly into the ORecur-Object using fromMap..
+ if( !map[OEvent::FRType].isEmpty() ){
+ QMap<int, QString> recFields;
+ recFields.insert( ORecur::RType, map[OEvent::FRType] );
+ recFields.insert( ORecur::RWeekdays, map[OEvent::FRWeekdays] );
+ recFields.insert( ORecur::RPosition, map[OEvent::FRPosition] );
+ recFields.insert( ORecur::RFreq, map[OEvent::FRFreq] );
+ recFields.insert( ORecur::RHasEndDate, map[OEvent::FRHasEndDate] );
+ recFields.insert( ORecur::EndDate, map[OEvent::FREndDate] );
+ recFields.insert( ORecur::Created, map[OEvent::FRCreated] );
+ recFields.insert( ORecur::Exceptions, map[OEvent::FRExceptions] );
+ ORecur recur( recFields );
+ setRecurrence( recur );
+ }
+
+}
+
+
+int OEvent::parent()const {
+ return data->parent;
+}
+void OEvent::setParent( int uid ) {
+ changeOrModify();
+ data->parent = uid;
+}
+QArray<int> OEvent::children() const{
+ if (!data->child) return QArray<int>();
+ else
+ return data->child->copy();
+}
+void OEvent::setChildren( const QArray<int>& arr ) {
+ changeOrModify();
+ if (data->child) delete data->child;
+
+ data->child = new QArray<int>( arr );
+ data->child->detach();
+}
+void OEvent::addChild( int uid ) {
+ changeOrModify();
+ if (!data->child ) {
+ data->child = new QArray<int>(1);
+ (*data->child)[0] = uid;
+ }else{
+ int count = data->child->count();
+ data->child->resize( count + 1 );
+ (*data->child)[count] = uid;
+ }
+}
+void OEvent::removeChild( int uid ) {
+ if (!data->child || !data->child->contains( uid ) ) return;
+ changeOrModify();
+ QArray<int> newAr( data->child->count() - 1 );
+ int j = 0;
+ uint count = data->child->count();
+ for ( uint i = 0; i < count; i++ ) {
+ if ( (*data->child)[i] != uid ) {
+ newAr[j] = (*data->child)[i];
+ j++;
+ }
+ }
+ (*data->child) = newAr;
+}
+struct OEffectiveEvent::Data : public QShared {
+ Data() : QShared() {
+ }
+ OEvent event;
+ QDate date;
+ QTime start, end;
+ QDate startDate, endDate;
+ bool dates : 1;
+};
+
+OEffectiveEvent::OEffectiveEvent() {
+ data = new Data;
+ data->date = QDate::currentDate();
+ data->start = data->end = QTime::currentTime();
+ data->dates = false;
+}
+OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate,
+ Position pos ) {
+ data = new Data;
+ data->event = ev;
+ data->date = startDate;
+ if ( pos & Start )
+ data->start = ev.startDateTime().time();
+ else
+ data->start = QTime( 0, 0, 0 );
+
+ if ( pos & End )
+ data->end = ev.endDateTime().time();
+ else
+ data->end = QTime( 23, 59, 59 );
+
+ data->dates = false;
+}
+OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) {
+ data = ev.data;
+ data->ref();
+}
+OEffectiveEvent::~OEffectiveEvent() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0;
+ }
+}
+OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) {
+ if ( *this == ev ) return *this;
+
+ ev.data->ref();
+ deref();
+ data = ev.data;
+
+ return *this;
+}
+
+void OEffectiveEvent::setStartTime( const QTime& ti) {
+ changeOrModify();
+ data->start = ti;
+}
+void OEffectiveEvent::setEndTime( const QTime& en) {
+ changeOrModify();
+ data->end = en;
+}
+void OEffectiveEvent::setEvent( const OEvent& ev) {
+ changeOrModify();
+ data->event = ev;
+}
+void OEffectiveEvent::setDate( const QDate& da) {
+ changeOrModify();
+ data->date = da;
+}
+void OEffectiveEvent::setEffectiveDates( const QDate& from,
+ const QDate& to ) {
+ if (!from.isValid() ) {
+ data->dates = false;
+ return;
+ }
+
+ data->startDate = from;
+ data->endDate = to;
+}
+QString OEffectiveEvent::description()const {
+ return data->event.description();
+}
+QString OEffectiveEvent::location()const {
+ return data->event.location();
+}
+QString OEffectiveEvent::note()const {
+ return data->event.note();
+}
+OEvent OEffectiveEvent::event()const {
+ return data->event;
+}
+QTime OEffectiveEvent::startTime()const {
+ return data->start;
+}
+QTime OEffectiveEvent::endTime()const {
+ return data->end;
+}
+QDate OEffectiveEvent::date()const {
+ return data->date;
+}
+int OEffectiveEvent::length()const {
+ return (data->end.hour() * 60 - data->start.hour() * 60)
+ + QABS(data->start.minute() - data->end.minute() );
+}
+int OEffectiveEvent::size()const {
+ return ( data->end.hour() - data->start.hour() ) * 3600
+ + (data->end.minute() - data->start.minute() * 60
+ + data->end.second() - data->start.second() );
+}
+QDate OEffectiveEvent::startDate()const {
+ if ( data->dates )
+ return data->startDate;
+ else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer
+ return data->date;
+ else
+ return data->event.startDateTime().date();
+}
+QDate OEffectiveEvent::endDate()const {
+ if ( data->dates )
+ return data->endDate;
+ else if ( data->event.hasRecurrence() )
+ return data->date;
+ else
+ return data->event.endDateTime().date();
+}
+void OEffectiveEvent::deref() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0;
+ }
+}
+void OEffectiveEvent::changeOrModify() {
+ if ( data->count != 1 ) {
+ data->deref();
+ Data* d2 = new Data;
+ d2->event = data->event;
+ d2->date = data->date;
+ d2->start = data->start;
+ d2->end = data->end;
+ d2->startDate = data->startDate;
+ d2->endDate = data->endDate;
+ d2->dates = data->dates;
+ data = d2;
+ }
+}
+bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{
+ if ( data->date < e.date() )
+ return TRUE;
+ if ( data->date == e.date() )
+ return ( startTime() < e.startTime() );
+ else
+ return FALSE;
+}
+bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{
+ return (data->date <= e.date() );
+}
+bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const {
+ return ( date() == e.date()
+ && startTime() == e.startTime()
+ && endTime()== e.endTime()
+ && event() == e.event() );
+}
+bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const {
+ return !(*this == e );
+}
+bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const {
+ return !(*this <= e );
+}
+bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const {
+ return !(*this < e);
+}
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 @@
+// CONTAINS GPLed code of TT
+
+#ifndef OPIE_PIM_EVENT_H
+#define OPIE_PIM_EVENT_H
+
+#include <qstring.h>
+#include <qdatetime.h>
+#include <qvaluelist.h>
+
+#include <qpe/recordfields.h>
+#include <qpe/palmtopuidgen.h>
+
+#include "otimezone.h"
+#include "opimrecord.h"
+
+struct OCalendarHelper {
+ /** calculate the week number of the date */
+ static int week( const QDate& );
+ /** calculate the occurence of week days since the start of the month */
+ static int ocurrence( const QDate& );
+
+ // returns the dayOfWeek for the *first* day it finds (ignores
+ // any further days!). Returns 1 (Monday) if there isn't any day found
+ static int dayOfWeek( char day );
+
+ /** returns the diff of month */
+ static int monthDiff( const QDate& first, const QDate& second );
+
+};
+
+class OPimNotifyManager;
+class ORecur;
+
+/**
+ * This is the container for all Events. It encapsules all
+ * available information for a single Event
+ * @short container for events.
+ */
+class OEvent : public OPimRecord {
+public:
+ typedef QValueList<OEvent> ValueList;
+ /**
+ * RecordFields contain possible attributes
+ * used in the Results of toMap()..
+ */
+ enum RecordFields {
+ FUid = Qtopia::UID_ID,
+ FCategories = Qtopia::CATEGORY_ID,
+ FDescription = 0,
+ FLocation,
+ FType,
+ FAlarm,
+ FSound,
+ FRType,
+ FRWeekdays,
+ FRPosition,
+ FRFreq,
+ FRHasEndDate,
+ FREndDate,
+ FRCreated,
+ FRExceptions,
+ FStart,
+ FEnd,
+ FNote,
+ FTimeZone,
+ FRecParent,
+ FRecChildren,
+ };
+
+ /**
+ * Start with an Empty OEvent. UID == 0 means that it is empty
+ */
+ OEvent(int uid = 0);
+
+ /**
+ * copy c'tor
+ */
+ OEvent( const OEvent& );
+
+ /**
+ * Create OEvent, initialized by map
+ * @see enum RecordFields
+ */
+ OEvent( const QMap<int, QString> map );
+ ~OEvent();
+ OEvent &operator=( const OEvent& );
+
+ QString description()const;
+ void setDescription( const QString& description );
+
+ QString location()const;
+ void setLocation( const QString& loc );
+
+ bool hasNotifiers()const;
+ OPimNotifyManager &notifiers()const;
+
+ ORecur recurrence()const;
+ void setRecurrence( const ORecur& );
+ bool hasRecurrence()const;
+
+ QString note()const;
+ void setNote( const QString& note );
+
+
+ QDateTime createdDateTime()const;
+ void setCreatedDateTime( const QDateTime& dt);
+
+ /** set the date to dt. dt is the QDateTime in localtime */
+ void setStartDateTime( const QDateTime& );
+ /** returns the datetime in the local timeZone */
+ QDateTime startDateTime()const;
+
+ /** returns the start datetime in the current zone */
+ QDateTime startDateTimeInZone()const;
+
+ /** in current timezone */
+ void setEndDateTime( const QDateTime& );
+ /** in current timezone */
+ QDateTime endDateTime()const;
+ QDateTime endDateTimeInZone()const;
+
+ bool isMultipleDay()const;
+ bool isAllDay()const;
+ void setAllDay( bool isAllDay );
+
+ /* pin this event to a timezone! FIXME */
+ void setTimeZone( const QString& timeZone );
+ QString timeZone()const;
+
+
+ virtual bool match( const QRegExp& )const;
+
+ /** For exception to recurrence here is a list of children... */
+ QArray<int> children()const;
+ void setChildren( const QArray<int>& );
+ void addChild( int uid );
+ void removeChild( int uid );
+
+ /** return the parent OEvent */
+ int parent()const;
+ void setParent( int uid );
+
+
+ /* needed reimp */
+ QString toRichText()const;
+ QString toShortText()const;
+ QString type()const;
+
+ QMap<int, QString> toMap()const;
+ void fromMap( const QMap<int, QString>& map );
+ QString recordField(int )const;
+
+ static int rtti();
+
+ bool loadFromStream( QDataStream& );
+ bool saveToStream( QDataStream& )const;
+
+/* bool operator==( const OEvent& );
+ bool operator!=( const OEvent& );
+ bool operator<( const OEvent& );
+ bool operator<=( const OEvent& );
+ bool operator>( const OEvent& );
+ bool operator>=(const OEvent& );
+*/
+private:
+ inline void changeOrModify();
+ void deref();
+ struct Data;
+ Data* data;
+ class Private;
+ Private* priv;
+
+};
+
+/**
+ * AN Event can span through multiple days. We split up a multiday eve
+ */
+class OEffectiveEvent {
+public:
+ typedef QValueList<OEffectiveEvent> ValueList;
+ enum Position { MidWay, Start, End, StartEnd };
+ // If we calculate the effective event of a multi-day event
+ // we have to figure out whether we are at the first day,
+ // at the end, or anywhere else ("middle"). This is important
+ // for the start/end times (00:00/23:59)
+ // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi-
+ // day event
+ // Start: start time -> 23:59
+ // End: 00:00 -> end time
+ // Start | End == StartEnd: for single-day events (default)
+ // here we draw start time -> end time
+ OEffectiveEvent();
+ OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd );
+ OEffectiveEvent( const OEffectiveEvent& );
+ OEffectiveEvent &operator=(const OEffectiveEvent& );
+ ~OEffectiveEvent();
+
+ void setStartTime( const QTime& );
+ void setEndTime( const QTime& );
+ void setEvent( const OEvent& );
+ void setDate( const QDate& );
+
+ void setEffectiveDates( const QDate& from, const QDate& to );
+
+ QString description()const;
+ QString location()const;
+ QString note()const;
+ OEvent event()const;
+ QTime startTime()const;
+ QTime endTime()const;
+ QDate date()const;
+
+ /* return the length in hours */
+ int length()const;
+ int size()const;
+
+ QDate startDate()const;
+ QDate endDate()const;
+
+ bool operator<( const OEffectiveEvent &e ) const;
+ bool operator<=( const OEffectiveEvent &e ) const;
+ bool operator==( const OEffectiveEvent &e ) const;
+ bool operator!=( const OEffectiveEvent &e ) const;
+ bool operator>( const OEffectiveEvent &e ) const;
+ bool operator>= ( const OEffectiveEvent &e ) const;
+
+private:
+ void deref();
+ inline void changeOrModify();
+ class Private;
+ Private* priv;
+ struct Data;
+ Data* data;
+
+};
+#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 @@
+#ifndef OPIE_PIM_ACCESS_BACKEND
+#define OPIE_PIM_ACCESS_BACKEND
+
+#include <qarray.h>
+#include <qdatetime.h>
+
+#include <opie/otemplatebase.h>
+#include <opie/opimrecord.h>
+
+
+class OPimAccessBackendPrivate;
+/**
+ * OPimAccessBackend is the base class
+ * for all private backends
+ * it operates on OPimRecord as the base class
+ * and it's responsible for fast manipulating
+ * the resource the implementation takes care
+ * of
+ */
+template <class T = OPimRecord>
+class OPimAccessBackend {
+public:
+ typedef OTemplateBase<T> Frontend;
+
+ /** The access hint from the frontend */
+ OPimAccessBackend(int access = 0);
+ virtual ~OPimAccessBackend();
+
+ /**
+ * load the resource
+ */
+ virtual bool load() = 0;
+
+ /**
+ * reload the resource
+ */
+ virtual bool reload() = 0;
+
+ /**
+ * save the resource and
+ * all it's changes
+ */
+ virtual bool save() = 0;
+
+ /**
+ * return an array of
+ * all available uids
+ */
+ virtual QArray<int> allRecords()const = 0;
+
+ /**
+ * return a List of records
+ * that match the regex
+ */
+ virtual QArray<int> matchRegexp(const QRegExp &r) const = 0;
+
+ /**
+ * queryByExample for T with the given Settings
+ *
+ */
+ virtual QArray<int> queryByExample( const T& t, int settings, const QDateTime& d = QDateTime() ) = 0;
+
+ /**
+ * find the OPimRecord with uid @param uid
+ * returns T and T.isEmpty() if nothing was found
+ */
+ virtual T find(int uid )const = 0;
+
+ virtual T find(int uid, const QArray<int>& items,
+ uint current, typename Frontend::CacheDirection )const ;
+ /**
+ * clear the back end
+ */
+ virtual void clear() = 0;
+
+ /**
+ * add T
+ */
+ virtual bool add( const T& t ) = 0;
+
+ /**
+ * remove
+ */
+ virtual bool remove( int uid ) = 0;
+
+ /**
+ * replace a record with T.uid()
+ */
+ virtual bool replace( const T& t ) = 0;
+
+ /*
+ * setTheFrontEnd!!!
+ */
+ void setFrontend( Frontend* front );
+
+ /**
+ * set the read ahead count
+ */
+ void setReadAhead( uint count );
+protected:
+ int access()const;
+ void cache( const T& t )const;
+
+ /**
+ * use a prime number here!
+ */
+ void setSaneCacheSize( int );
+
+ uint readAhead()const;
+
+private:
+ OPimAccessBackendPrivate *d;
+ Frontend* m_front;
+ uint m_read;
+ int m_acc;
+
+};
+
+template <class T>
+OPimAccessBackend<T>::OPimAccessBackend(int acc)
+ : m_acc( acc )
+{
+ m_front = 0l;
+}
+template <class T>
+OPimAccessBackend<T>::~OPimAccessBackend() {
+
+}
+template <class T>
+void OPimAccessBackend<T>::setFrontend( Frontend* fr ) {
+ m_front = fr;
+}
+template <class T>
+void OPimAccessBackend<T>::cache( const T& t )const {
+ if (m_front )
+ m_front->cache( t );
+}
+template <class T>
+void OPimAccessBackend<T>::setSaneCacheSize( int size) {
+ if (m_front )
+ m_front->setSaneCacheSize( size );
+}
+template <class T>
+T OPimAccessBackend<T>::find( int uid, const QArray<int>&,
+ uint, typename Frontend::CacheDirection )const {
+ return find( uid );
+}
+template <class T>
+void OPimAccessBackend<T>::setReadAhead( uint count ) {
+ m_read = count;
+}
+template <class T>
+uint OPimAccessBackend<T>::readAhead()const {
+ return m_read;
+}
+template <class T>
+int OPimAccessBackend<T>::access()const {
+ return m_acc;
+}
+#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 @@
+#ifndef OPIE_PIM_ACCESS_TEMPLATE_H
+#define OPIE_PIM_ACCESS_TEMPLATE_H
+
+#include <qarray.h>
+
+#include <opie/opimrecord.h>
+#include <opie/opimaccessbackend.h>
+#include <opie/orecordlist.h>
+
+#include "opimcache.h"
+#include "otemplatebase.h"
+
+class OPimAccessTemplatePrivate;
+/**
+ * Thats the frontend to our OPIE PIM
+ * Library. Either you want to use it's
+ * interface or you want to implement
+ * your own Access lib
+ * Just create a OPimRecord and inherit from
+ * the plugins
+ */
+
+template <class T = OPimRecord >
+class OPimAccessTemplate : public OTemplateBase<T> {
+public:
+ enum Access {
+ Random = 0,
+ SortedAccess
+ };
+ typedef ORecordList<T> List;
+ typedef OPimAccessBackend<T> BackEnd;
+ typedef OPimCache<T> Cache;
+
+ /**
+ * c'tor BackEnd
+ * enum Access a small hint on how to handle the backend
+ */
+ OPimAccessTemplate( BackEnd* end);
+
+ virtual ~OPimAccessTemplate();
+
+ /**
+ * load from the backend
+ */
+ bool load();
+
+ /** Reload database.
+ * You should execute this function if the external database
+ * was changed.
+ * This function will load the external database and afterwards
+ * rejoin the local changes. Therefore the local database will be set consistent.
+ */
+ virtual bool reload();
+
+ /** Save contacts database.
+ * Save is more a "commit". After calling this function, all changes are public available.
+ * @return true if successful
+ */
+ bool save();
+
+ /**
+ * if the resource was changed externally
+ * You should use the signal handling instead of polling possible changes !
+ * zecke: Do you implement a signal for otodoaccess ?
+ */
+ bool wasChangedExternally()const;
+
+ /**
+ * return a List of records
+ * you can iterate over them
+ */
+ virtual List allRecords()const;
+
+ /**
+ * return a List of records
+ * that match the regex
+ */
+ virtual List matchRegexp( const QRegExp &r ) const;
+
+ /**
+ * queryByExample.
+ * @see otodoaccess, ocontactaccess
+ */
+ virtual List queryByExample( const T& t, int querySettings, const QDateTime& d = QDateTime() );
+
+ /**
+ * find the OPimRecord uid
+ */
+ virtual T find( int uid )const;
+
+ /**
+ * read ahead cache find method ;)
+ */
+ virtual T find( int uid, const QArray<int>&,
+ uint current, typename OTemplateBase<T>::CacheDirection dir = OTemplateBase<T>::Forward )const;
+
+ /* invalidate cache here */
+ /**
+ * clears the backend and invalidates the backend
+ */
+ void clear() ;
+
+ /**
+ * add T to the backend
+ * @param t The item to add.
+ * @return <i>true</i> if added successfully.
+ */
+ virtual bool add( const T& t ) ;
+ bool add( const OPimRecord& );
+
+ /* only the uid matters */
+ /**
+ * remove T from the backend
+ * @param t The item to remove
+ * @return <i>true</i> if successful.
+ */
+ virtual bool remove( const T& t );
+
+ /**
+ * remove the OPimRecord with uid
+ * @param uid The ID of the item to remove
+ * @return <i>true</i> if successful.
+ */
+ bool remove( int uid );
+ bool remove( const OPimRecord& );
+
+ /**
+ * replace T from backend
+ * @param t The item to replace
+ * @return <i>true</i> if successful.
+ */
+ virtual bool replace( const T& t) ;
+
+ void setReadAhead( uint count );
+ /**
+ * @internal
+ */
+ void cache( const T& )const;
+ void setSaneCacheSize( int );
+
+ QArray<int> records()const;
+protected:
+ /**
+ * invalidate the cache
+ */
+ void invalidateCache();
+
+ void setBackEnd( BackEnd* end );
+ /**
+ * returns the backend
+ */
+ BackEnd* backEnd();
+ BackEnd* m_backEnd;
+ Cache m_cache;
+
+private:
+ OPimAccessTemplatePrivate *d;
+
+};
+
+template <class T>
+OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end )
+ : OTemplateBase<T>(), m_backEnd( end )
+{
+ if (end )
+ end->setFrontend( this );
+}
+template <class T>
+OPimAccessTemplate<T>::~OPimAccessTemplate() {
+ qWarning("~OPimAccessTemplate<T>");
+ delete m_backEnd;
+}
+template <class T>
+bool OPimAccessTemplate<T>::load() {
+ invalidateCache();
+ return m_backEnd->load();
+}
+template <class T>
+bool OPimAccessTemplate<T>::reload() {
+ invalidateCache(); // zecke: I think this should be added (se)
+ return m_backEnd->reload();
+}
+template <class T>
+bool OPimAccessTemplate<T>::save() {
+ return m_backEnd->save();
+}
+template <class T>
+typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
+ QArray<int> ints = m_backEnd->allRecords();
+ List lis(ints, this );
+ return lis;
+}
+template <class T>
+typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::matchRegexp( const QRegExp &r )const {
+ QArray<int> ints = m_backEnd->matchRegexp( r );
+ List lis(ints, this );
+ return lis;
+}
+template <class T>
+QArray<int> OPimAccessTemplate<T>::records()const {
+ return m_backEnd->allRecords();
+}
+template <class T>
+typename OPimAccessTemplate<T>::List
+OPimAccessTemplate<T>::queryByExample( const T& t, int settings, const QDateTime& d ) {
+ QArray<int> ints = m_backEnd->queryByExample( t, settings, d );
+
+ List lis(ints, this );
+ return lis;
+}
+template <class T>
+T OPimAccessTemplate<T>::find( int uid ) const{
+ T t = m_backEnd->find( uid );
+ cache( t );
+ return t;
+}
+template <class T>
+T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar,
+ uint current, typename OTemplateBase<T>::CacheDirection dir )const {
+ /*
+ * better do T.isEmpty()
+ * after a find this way we would
+ * avoid two finds in QCache...
+ */
+ // qWarning("find it now %d", uid );
+ if (m_cache.contains( uid ) ) {
+ return m_cache.find( uid );
+ }
+
+ T t = m_backEnd->find( uid, ar, current, dir );
+ cache( t );
+ return t;
+}
+template <class T>
+void OPimAccessTemplate<T>::clear() {
+ invalidateCache();
+ m_backEnd->clear();
+}
+template <class T>
+bool OPimAccessTemplate<T>::add( const T& t ) {
+ cache( t );
+ return m_backEnd->add( t );
+}
+template <class T>
+bool OPimAccessTemplate<T>::add( const OPimRecord& rec) {
+ /* same type */
+ if ( rec.rtti() == T::rtti() ) {
+ const T &t = static_cast<const T&>(rec);
+ return add(t);
+ }
+ return false;
+}
+template <class T>
+bool OPimAccessTemplate<T>::remove( const T& t ) {
+ return remove( t.uid() );
+}
+template <class T>
+bool OPimAccessTemplate<T>::remove( int uid ) {
+ m_cache.remove( uid );
+ return m_backEnd->remove( uid );
+}
+template <class T>
+bool OPimAccessTemplate<T>::remove( const OPimRecord& rec) {
+ return remove( rec.uid() );
+}
+template <class T>
+bool OPimAccessTemplate<T>::replace( const T& t ) {
+ m_cache.replace( t );
+ return m_backEnd->replace( t );
+}
+template <class T>
+void OPimAccessTemplate<T>::invalidateCache() {
+ m_cache.invalidate();
+}
+template <class T>
+typename OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() {
+ return m_backEnd;
+}
+template <class T>
+bool OPimAccessTemplate<T>::wasChangedExternally()const {
+ return false;
+}
+template <class T>
+void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) {
+ m_backEnd = end;
+ if (m_backEnd )
+ m_backEnd->setFrontend( this );
+}
+template <class T>
+void OPimAccessTemplate<T>::cache( const T& t ) const{
+ /* hacky we need to work around the const*/
+ ((OPimAccessTemplate<T>*)this)->m_cache.add( t );
+}
+template <class T>
+void OPimAccessTemplate<T>::setSaneCacheSize( int size ) {
+ m_cache.setSize( size );
+}
+template <class T>
+void OPimAccessTemplate<T>::setReadAhead( uint count ) {
+ m_backEnd->setReadAhead( count );
+}
+#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 @@
+#ifndef OPIE_PIM_CACHE_H
+#define OPIE_PIM_CACHE_H
+
+#include <qintcache.h>
+
+#include "opimrecord.h"
+
+class OPimCacheItemPrivate;
+
+template <class T = OPimRecord>
+class OPimCacheItem {
+public:
+ OPimCacheItem( const T& t = T() );
+ OPimCacheItem( const OPimCacheItem& );
+ ~OPimCacheItem();
+
+ OPimCacheItem &operator=( const OPimCacheItem& );
+
+ T record()const;
+ void setRecord( const T& );
+private:
+ T m_t;
+ OPimCacheItemPrivate *d;
+};
+
+
+class OPimCachePrivate;
+/**
+ * OPimCache for caching the items
+ * We support adding, removing
+ * and finding
+ */
+template <class T = OPimRecord>
+class OPimCache {
+public:
+ typedef OPimCacheItem<T> Item;
+ OPimCache();
+ OPimCache( const OPimCache& );
+ ~OPimCache();
+
+ OPimCache &operator=( const OPimCache& );
+
+ bool contains(int uid)const;
+ void invalidate();
+ void setSize( int size );
+
+ T find(int uid )const;
+ void add( const T& );
+ void remove( int uid );
+ void replace( const T& );
+
+private:
+ QIntCache<Item> m_cache;
+ OPimCachePrivate* d;
+};
+
+// Implementation
+template <class T>
+OPimCacheItem<T>::OPimCacheItem( const T& t )
+ : m_t(t) {
+}
+template <class T>
+OPimCacheItem<T>::~OPimCacheItem() {
+
+}
+template <class T>
+T OPimCacheItem<T>::record()const {
+ return m_t;
+}
+template <class T>
+void OPimCacheItem<T>::setRecord( const T& t ) {
+ m_t = t;
+}
+// Cache
+template <class T>
+OPimCache<T>::OPimCache()
+ : m_cache(100, 53 )
+{
+ m_cache.setAutoDelete( TRUE );
+}
+template <class T>
+OPimCache<T>::~OPimCache() {
+
+}
+template <class T>
+bool OPimCache<T>::contains(int uid )const {
+ Item* it = m_cache.find( uid, FALSE );
+ if (!it)
+ return false;
+ return true;
+}
+template <class T>
+void OPimCache<T>::invalidate() {
+ m_cache.clear();
+}
+template <class T>
+void OPimCache<T>::setSize( int size ) {
+ m_cache.setMaxCost( size );
+}
+template <class T>
+T OPimCache<T>::find(int uid )const {
+ Item *it = m_cache.find( uid );
+ if (it)
+ return it->record();
+ return T();
+}
+template <class T>
+void OPimCache<T>::add( const T& t ) {
+ Item* it = 0l;
+ it = m_cache.find(t.uid(), FALSE );
+
+ if (it )
+ it->setRecord( t );
+
+ it = new Item( t );
+ if (!m_cache.insert( t.uid(), it ) )
+ delete it;
+}
+template <class T>
+void OPimCache<T>::remove( int uid ) {
+ m_cache.remove( uid );
+}
+template <class T>
+void OPimCache<T>::replace( const T& t) {
+ Item *it = m_cache.find( t.uid() );
+ if ( it ) {
+ it->setRecord( t );
+ }
+}
+
+#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 @@
+#include "opimmaintainer.h"
+
+OPimMaintainer::OPimMaintainer( int mode, int uid )
+ : m_mode(mode), m_uid(uid )
+{}
+OPimMaintainer::~OPimMaintainer() {
+}
+OPimMaintainer::OPimMaintainer( const OPimMaintainer& main ) {
+ *this = main;
+}
+OPimMaintainer &OPimMaintainer::operator=( const OPimMaintainer& main ) {
+ m_mode = main.m_mode;
+ m_uid = main.m_uid;
+
+ return *this;
+}
+bool OPimMaintainer::operator==( const OPimMaintainer& main ) {
+ if (m_mode != main.m_mode ) return false;
+ if (m_uid != main.m_uid ) return false;
+
+ return true;
+}
+bool OPimMaintainer::operator!=( const OPimMaintainer& main ) {
+ return !(*this == main );
+}
+int OPimMaintainer::mode()const {
+ return m_mode;
+}
+int OPimMaintainer::uid()const {
+ return m_uid;
+}
+void OPimMaintainer::setMode( int mo) {
+ m_mode = mo;
+}
+void OPimMaintainer::setUid( int uid ) {
+ m_uid = uid;
+}
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 @@
+#ifndef OPIE_PIM_MAINTAINER_H
+#define OPIE_PIM_MAINTAINER_H
+
+#include <qstring.h>
+
+/**
+ * Who maintains what?
+ */
+class OPimMaintainer {
+public:
+ enum Mode { Undefined = -1,
+ Nothing = 0,
+ Responsible,
+ DoneBy,
+ Coordinating,
+ };
+ OPimMaintainer( int mode = Undefined, int uid = 0);
+ OPimMaintainer( const OPimMaintainer& );
+ ~OPimMaintainer();
+
+ OPimMaintainer &operator=( const OPimMaintainer& );
+ bool operator==( const OPimMaintainer& );
+ bool operator!=( const OPimMaintainer& );
+
+
+ int mode()const;
+ int uid()const;
+
+ void setMode( int mode );
+ void setUid( int uid );
+
+private:
+ int m_mode;
+ int m_uid;
+ class Private;
+ Private *d;
+
+};
+
+#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 @@
+#include <qapplication.h>
+#include <qdatetime.h>
+#include <qcopchannel_qws.h>
+
+#include <qpe/sound.h>
+#include <qpe/qcopenvelope_qws.h>
+#include <qpe/qpeapplication.h>
+
+#include "opimresolver.h"
+#include "opimmainwindow.h"
+
+OPimMainWindow::OPimMainWindow( const QString& service, QWidget* parent,
+ const char* name, WFlags flag )
+ : QMainWindow( parent, name, flag ), m_rtti(-1), m_service( service ), m_fallBack(0l) {
+
+ /*
+ * let's generate our QCopChannel
+ */
+ m_str = QString("QPE/"+m_service).local8Bit();
+ m_channel= new QCopChannel(m_str, this );
+ connect(m_channel, SIGNAL(received(const QCString&,const QByteArray&) ),
+ this, SLOT( appMessage(const QCString&,const QByteArray&) ) );
+ connect(qApp, SIGNAL(appMessage(const QCString&,const QByteArray&) ),
+ this, SLOT( appMessage(const QCString&,const QByteArray&) ) );
+
+ /* connect flush and reload */
+ connect(qApp, SIGNAL(flush() ),
+ this, SLOT(flush() ) );
+ connect(qApp, SIGNAL(reload() ),
+ this, SLOT(reload() ) );
+}
+OPimMainWindow::~OPimMainWindow() {
+ delete m_channel;
+}
+QCopChannel* OPimMainWindow::channel() {
+ return m_channel;
+}
+void OPimMainWindow::doSetDocument( const QString& ) {
+
+}
+void OPimMainWindow::appMessage( const QCString& cmd, const QByteArray& array ) {
+ bool needShow = false;
+ /*
+ * create demands to create
+ * a new record...
+ */
+ QDataStream stream(array, IO_ReadOnly);
+ if ( cmd == "create()" ) {
+ raise();
+ int uid = create();
+ QCopEnvelope e(m_str, "created(int)" );
+ e << uid;
+ needShow = true;
+ }else if ( cmd == "remove(int)" ) {
+ int uid;
+ stream >> uid;
+ bool rem = remove( uid );
+ QCopEnvelope e(m_str, "removed(bool)" );
+ e << rem;
+ needShow = true;
+ }else if ( cmd == "beam(int)" ) {
+ int uid;
+ stream >> uid;
+ beam( uid);
+ }else if ( cmd == "show(int)" ) {
+ raise();
+ int uid;
+ stream >> uid;
+ show( uid );
+ needShow = true;
+ }else if ( cmd == "edit(int)" ) {
+ raise();
+ int uid;
+ stream >> uid;
+ edit( uid );
+ }else if ( cmd == "add(int,QByteArray)" ) {
+ int rtti;
+ QByteArray array;
+ stream >> rtti;
+ stream >> array;
+ m_fallBack = record(rtti, array );
+ if (!m_fallBack) return;
+ add( *m_fallBack );
+ delete m_fallBack;
+ }else if ( cmd == "alarm(QDateTime,int)" ) {
+ raise();
+ QDateTime dt; int uid;
+ stream >> dt;
+ stream >> uid;
+ qWarning(" Date: %s Uid: %d", dt.toString().latin1(), uid );
+ QDateTime current = QDateTime::currentDateTime();
+ if ( current.time().hour() != dt.time().hour() && current.time().minute() != dt.time().minute() )
+ return;
+ doAlarm( dt, uid );
+ needShow = true;
+ }
+
+ if (needShow )
+ QPEApplication::setKeepRunning();
+}
+/* implement the url scripting here */
+void OPimMainWindow::setDocument( const QString& str) {
+ doSetDocument( str );
+}
+/*
+ * we now try to get the array demarshalled
+ * check if the rtti matches this one
+ */
+OPimRecord* OPimMainWindow::record( int rtti, const QByteArray& array ) {
+ if ( service() != rtti )
+ return 0l;
+
+ OPimRecord* record = OPimResolver::self()->record( rtti );
+ QDataStream str(array, IO_ReadOnly );
+ if ( !record || !record->loadFromStream(str) ) {
+ delete record;
+ record = 0l;
+ }
+
+ return record;
+}
+/*
+ * get the rtti for the service
+ */
+int OPimMainWindow::service() {
+ if ( m_rtti == -1 )
+ m_rtti = OPimResolver::self()->serviceId( m_service );
+
+ return m_rtti;
+}
+void OPimMainWindow::doAlarm( const QDateTime&, int ) {
+
+}
+void OPimMainWindow::startAlarm(int count ) {
+ m_alarmCount = count;
+ m_playedCount = 0;
+ Sound::soundAlarm();
+ m_timerId = startTimer( 5000 );
+}
+void OPimMainWindow::killAlarm() {
+ killTimer( m_timerId );
+}
+void OPimMainWindow::timerEvent( QTimerEvent* e) {
+ if ( m_playedCount <m_alarmCount ) {
+ m_playedCount++;
+ Sound::soundAlarm();
+ }else {
+ killTimer( e->timerId() );
+ }
+}
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 @@
+#ifndef OPIE_PIM_MAINWINDOW_H
+#define OPIE_PIM_MAINWINDOW_H
+
+#include <qmainwindow.h>
+
+#include <opie/opimrecord.h>
+
+/**
+ * This is a common Opie PIM MainWindow
+ * it takes care of the QCOP internals
+ * and implements some functions
+ * for the URL scripting schema
+ */
+/*
+ * due Qt and Templates with signal and slots
+ * do not work that good :(
+ * (Ok how to moc a template ;) )
+ * We will have the mainwindow which calls a struct which
+ * is normally reimplemented as a template ;)
+ */
+
+class QCopChannel;
+class QDateTime;
+class OPimMainWindow : public QMainWindow {
+ Q_OBJECT
+public:
+ enum TransPort { BlueTooth=0,
+ IrDa };
+
+ OPimMainWindow( const QString& service, QWidget *parent = 0, const char* name = 0,
+ WFlags f = WType_TopLevel);
+ virtual ~OPimMainWindow();
+
+
+protected slots:
+ /*
+ * called when a setDocument
+ * couldn't be handled by this window
+ */
+ virtual void doSetDocument( const QString& );
+ /* for syncing */
+ virtual void flush() = 0;
+ virtual void reload() = 0;
+
+ /** create a new Records and return the uid */
+ virtual int create() = 0;
+ /** remove a record with UID == uid */
+ virtual bool remove( int uid ) = 0;
+ /** beam the record with UID = uid */
+ virtual void beam( int uid ) = 0;
+
+ /** show the record with UID == uid */
+ virtual void show( int uid ) = 0;
+ /** edit the record */
+ virtual void edit( int uid ) = 0;
+
+ /** make a copy of it! */
+ virtual void add( const OPimRecord& ) = 0;
+
+ virtual void doAlarm( const QDateTime&, int uid );
+
+ QCopChannel* channel();
+
+protected:
+ /**
+ * start to play soundAlarm()
+ * @param count How many times the alarm is played
+ */
+ void startAlarm(int count = 10);
+ void killAlarm();
+ void timerEvent( QTimerEvent* );
+
+private slots:
+ void appMessage( const QCString&, const QByteArray& );
+ void setDocument( const QString& );
+
+
+private:
+ class Private;
+ Private* d;
+
+ int m_rtti;
+ QCopChannel* m_channel;
+ QString m_service;
+ QCString m_str;
+ OPimRecord* m_fallBack;
+ int m_alarmCount;
+ int m_playedCount;
+ int m_timerId;
+ /* I would love to do this as a template
+ * but can't think of a right way
+ * because I need signal and slots -zecke
+ */
+ virtual OPimRecord* record( int rtti, const QByteArray& ) ;
+ int service();
+};
+
+
+#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 @@
+#include <qshared.h>
+
+#include "opimnotify.h"
+
+struct OPimNotify::Data : public QShared {
+ Data() : QShared(),dur(-1),parent(0) {
+
+ }
+ QDateTime start;
+ int dur;
+ QString application;
+ int parent;
+};
+
+OPimNotify::OPimNotify( const QDateTime& start, int duration, int parent ) {
+ data = new Data;
+ data->start = start;
+ data->dur = duration;
+ data->parent = parent;
+}
+OPimNotify::OPimNotify( const OPimNotify& noti)
+ : data( noti.data )
+{
+ data->ref();
+}
+OPimNotify::~OPimNotify() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0l;
+ }
+}
+
+OPimNotify &OPimNotify::operator=( const OPimNotify& noti) {
+ noti.data->ref();
+ deref();
+ data = noti.data;
+
+ return *this;
+}
+bool OPimNotify::operator==( const OPimNotify& noti ) {
+ if ( data == noti.data ) return true;
+ if ( data->dur != noti.data->dur ) return false;
+ if ( data->parent != noti.data->parent ) return false;
+ if ( data->application != noti.data->application ) return false;
+ if ( data->start != noti.data->start ) return false;
+
+ return true;
+}
+QDateTime OPimNotify::dateTime()const {
+ return data->start;
+}
+QString OPimNotify::service()const {
+ return data->application;
+}
+int OPimNotify::parent()const {
+ return data->parent;
+}
+int OPimNotify::duration()const {
+ return data->dur;
+}
+QDateTime OPimNotify::endTime()const {
+ return QDateTime( data->start.date(), data->start.time().addSecs( data->dur) );
+}
+void OPimNotify::setDateTime( const QDateTime& time ) {
+ copyIntern();
+ data->start = time;
+}
+void OPimNotify::setDuration( int dur ) {
+ copyIntern();
+ data->dur = dur;
+}
+void OPimNotify::setParent( int uid ) {
+ copyIntern();
+ data->parent = uid;
+}
+void OPimNotify::setService( const QString& str ) {
+ copyIntern();
+ data->application = str;
+}
+void OPimNotify::copyIntern() {
+ if ( data->count != 1 ) {
+ data->deref();
+ Data* dat = new Data;
+ dat->start = data->start;
+ dat->dur = data->dur;
+ dat->application = data->application;
+ dat->parent = data->parent;
+ data = dat;
+ }
+}
+void OPimNotify::deref() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0;
+ }
+}
+
+/***********************************************************/
+struct OPimAlarm::Data : public QShared {
+ Data() : QShared() {
+ sound = 1;
+ }
+ int sound;
+ QString file;
+};
+OPimAlarm::OPimAlarm( int sound, const QDateTime& start, int duration, int parent )
+ : OPimNotify( start, duration, parent )
+{
+ data = new Data;
+ data->sound = sound;
+}
+OPimAlarm::OPimAlarm( const OPimAlarm& al)
+ : OPimNotify(al), data( al.data )
+{
+ data->ref();
+}
+OPimAlarm::~OPimAlarm() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0l;
+ }
+}
+OPimAlarm &OPimAlarm::operator=( const OPimAlarm& al)
+{
+ OPimNotify::operator=( al );
+ deref();
+ al.data->ref();
+
+ data = al.data;
+
+
+ return *this;
+}
+bool OPimAlarm::operator==( const OPimAlarm& al) {
+ if ( data->sound != al.data->sound ) return false;
+ else if ( data->sound == Custom && data->file != al.data->file )
+ return false;
+
+ return OPimNotify::operator==( al );
+}
+QString OPimAlarm::type()const {
+ return QString::fromLatin1("OPimAlarm");
+}
+int OPimAlarm::sound()const {
+ return data->sound;
+}
+QString OPimAlarm::file()const {
+ return data->file;
+}
+void OPimAlarm::setSound( int snd) {
+ copyIntern();
+ data->sound = snd;
+}
+void OPimAlarm::setFile( const QString& sound ) {
+ copyIntern();
+ data->file = sound;
+}
+void OPimAlarm::deref() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0l;
+ }
+}
+void OPimAlarm::copyIntern() {
+ if ( data->count != 1 ) {
+ data->deref();
+ Data *newDat = new Data;
+ newDat->sound = data->sound;
+ newDat->file = data->file;
+ data = newDat;
+ }
+}
+/************************/
+struct OPimReminder::Data : public QShared {
+ Data() : QShared(), record( 0) {
+ }
+ int record;
+
+};
+OPimReminder::OPimReminder( int uid, const QDateTime& start, int dur, int parent )
+ : OPimNotify( start, dur, parent )
+{
+ data = new Data;
+ data->record = uid;
+}
+OPimReminder::OPimReminder( const OPimReminder& rem )
+ : OPimNotify( rem ), data( rem.data )
+{
+ data->ref();
+}
+OPimReminder& OPimReminder::operator=( const OPimReminder& rem) {
+ OPimNotify::operator=(rem );
+
+ deref();
+ rem.data->ref();
+ data = rem.data;
+
+ return *this;
+}
+bool OPimReminder::operator==( const OPimReminder& rem) {
+ if ( data->record != rem.data->record ) return false;
+
+ return OPimNotify::operator==( rem );
+}
+QString OPimReminder::type()const {
+ return QString::fromLatin1("OPimReminder");
+}
+int OPimReminder::recordUid()const {
+ return data->record;
+}
+void OPimReminder::setRecordUid( int uid ) {
+ copyIntern();
+ data->record = uid;
+}
+void OPimReminder::deref() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0l;
+ }
+}
+void OPimReminder::copyIntern() {
+ if ( data->count != 1 ) {
+ Data* da = new Data;
+ da->record = data->record;
+ data = da;
+ }
+}
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 @@
+#ifndef OPIE_PIM_NOTIFY_H
+#define OPIE_PIM_NOTIFY_H
+
+#include <qdatetime.h>
+#include <qvaluelist.h>
+
+/**
+ * This is the base class of Notifiers. Possible
+ * notifiers would be Alarms, Reminders
+ * What they share is that they have
+ * A DateTime, Type, Duration
+ * This is what this base class takes care of
+ * on top of that it's shared
+ */
+/*
+ * TALK to eilers: have a class OPimDuration which sets the Duration
+ * given on the Due/Start Date? -zecke
+ * discuss: do we need a uid for the notify? -zecke
+ */
+class OPimNotify {
+public:
+ typedef QValueList<OPimNotify> ValueList;
+ OPimNotify( const QDateTime& start = QDateTime(), int duration = 0, int parent = 0 );
+ OPimNotify( const OPimNotify& );
+ virtual ~OPimNotify();
+
+ OPimNotify &operator=(const OPimNotify& );
+ bool operator==( const OPimNotify& );
+
+ virtual QString type()const = 0;
+
+ /** start date */
+ QDateTime dateTime()const;
+ QString service()const;
+
+ /**
+ * RETURN the parent uid
+ */
+ int parent()const;
+
+ /**
+ * in Seconds
+ */
+ int duration()const;
+
+ /**
+ * Start Time + Duration
+ */
+ QDateTime endTime()const;
+
+ void setDateTime( const QDateTime& );
+ void setDuration( int dur );
+ void setParent(int uid );
+ void setService( const QString& );
+
+
+private:
+ inline void copyIntern();
+ void deref();
+ struct Data;
+ Data* data;
+
+ /* d-pointer */
+ class NotifyPrivate;
+ NotifyPrivate* d;
+
+};
+/**
+ * An alarm is a sound/mail/buzzer played/send
+ * at a given time to inform about
+ * an Event
+ */
+class OPimAlarm : public OPimNotify {
+public:
+ enum Sound{Loud=1, Silent=0, Custom=2 };
+ OPimAlarm( int sound = Silent, const QDateTime& start = QDateTime(), int duration = 0, int parent = 0 );
+ OPimAlarm( const OPimAlarm& );
+ ~OPimAlarm();
+
+ OPimAlarm &operator=( const OPimAlarm& );
+ bool operator==( const OPimAlarm& );
+ QString type()const;
+
+ int sound()const;
+ QString file()const;
+
+ void setSound( int );
+ /* only when sound is custom... */
+ void setFile( const QString& sound );
+
+private:
+ void deref();
+ void copyIntern();
+ struct Data;
+ Data * data;
+
+ class Private;
+ Private* d;
+
+};
+
+/**
+ * A Reminder will be put into the
+ * datebook
+ * Note that the returned dateTime() may be not valid.
+ * In these cases one must resolve the uid and get the OEvent
+ */
+class OPimReminder : public OPimNotify {
+public:
+
+ /**
+ * c'tor of a reminder
+ * @param uid The uid of the Record inside the Datebook
+ * @param start the StartDate invalid for all day...
+ * @param duration The duration of the event ( -1 for all day )
+ * @param parent The 'parent' record of this reminder
+ */
+ OPimReminder( int uid = 0, const QDateTime& start = QDateTime(),
+ int duration = 0, int parent = 0 );
+ OPimReminder( const OPimReminder& );
+ OPimReminder &operator=(const OPimReminder& );
+
+ QString type()const;
+
+ bool operator==( const OPimReminder& );
+
+ /**
+ * the uid of the alarm
+ * inside the 'datebook' application
+ */
+ int recordUid()const;
+ void setRecordUid( int uid );
+
+private:
+ void deref();
+ void copyIntern();
+
+ struct Data;
+ Data* data;
+ class Private;
+ Private *d;
+};
+
+#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 @@
+#include "opimnotifymanager.h"
+
+#include "oconversion.h"
+
+#include <qstringlist.h>
+
+OPimNotifyManager::OPimNotifyManager( const Reminders& rem, const Alarms& al)
+ : m_rem( rem ), m_al( al )
+{}
+OPimNotifyManager::~OPimNotifyManager() {
+}
+/* use static_cast and type instead of dynamic... */
+void OPimNotifyManager::add( const OPimNotify& noti) {
+ if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
+ const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
+ m_rem.append( rem );
+ }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
+ const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
+ m_al.append( al );
+ }
+}
+void OPimNotifyManager::remove( const OPimNotify& noti) {
+ if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
+ const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
+ m_rem.remove( rem );
+ }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
+ const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
+ m_al.remove( al );
+ }
+}
+void OPimNotifyManager::replace( const OPimNotify& noti) {
+ if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
+ const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
+ m_rem.remove( rem );
+ m_rem.append( rem );
+ }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
+ const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
+ m_al.remove( al );
+ m_al.append( al );
+ }
+}
+OPimNotifyManager::Reminders OPimNotifyManager::reminders()const {
+ return m_rem;
+}
+OPimNotifyManager::Alarms OPimNotifyManager::alarms()const {
+ return m_al;
+}
+OPimAlarm OPimNotifyManager::alarmAtDateTime( const QDateTime& when, bool& found ) const {
+ Alarms::ConstIterator it;
+ found = true;
+
+ for ( it = m_al.begin(); it != m_al.end(); ++it ){
+ if ( (*it).dateTime() == when )
+ return (*it);
+ }
+
+ // Fall through if nothing could be found
+ found = false;
+ OPimAlarm empty;
+ return empty;
+}
+
+
+void OPimNotifyManager::setAlarms( const Alarms& al) {
+ m_al = al;
+}
+void OPimNotifyManager::setReminders( const Reminders& rem) {
+ m_rem = rem;
+}
+/* FIXME!!! */
+/**
+ * The idea is to check if the provider for our service
+ * is online
+ * if it is we will use QCOP
+ * if not the Factory to get the backend...
+ * Qtopia1.6 services would be kewl to have here....
+ */
+void OPimNotifyManager::registerNotify( const OPimNotify& ) {
+
+}
+/* FIXME!!! */
+/**
+ * same as above...
+ * Also implement Url model
+ * have a MainWindow....
+ */
+void OPimNotifyManager::deregister( const OPimNotify& ) {
+
+}
+
+bool OPimNotifyManager::isEmpty()const {
+ qWarning("is Empty called on OPimNotifyManager %d %d", m_rem.count(), m_al.count() );
+ if ( m_rem.isEmpty() && m_al.isEmpty() ) return true;
+ else return false;
+}
+
+// Taken from otodoaccessxml..
+QString OPimNotifyManager::alarmsToString() const
+{
+ QString str;
+
+ OPimNotifyManager::Alarms alarms = m_al;
+ if ( !alarms.isEmpty() ) {
+ QStringList als;
+ OPimNotifyManager::Alarms::Iterator it = alarms.begin();
+ for ( ; it != alarms.end(); ++it ) {
+ /* only if time is valid */
+ if ( (*it).dateTime().isValid() ) {
+ als << OConversion::dateTimeToString( (*it).dateTime() )
+ + ":" + QString::number( (*it).duration() )
+ + ":" + QString::number( (*it).sound() )
+ + ":";
+ }
+ }
+ // now write the list
+ qWarning("als: %s", als.join("____________").latin1() );
+ str = als.join(";");
+ }
+
+ return str;
+}
+QString OPimNotifyManager::remindersToString() const
+{
+ QString str;
+
+ OPimNotifyManager::Reminders reminders = m_rem;
+ if (!reminders.isEmpty() ) {
+ OPimNotifyManager::Reminders::Iterator it = reminders.begin();
+ QStringList records;
+ for ( ; it != reminders.end(); ++it ) {
+ records << QString::number( (*it).recordUid() );
+ }
+ str = records.join(";");
+ }
+
+ return str;
+}
+
+void OPimNotifyManager::alarmsFromString( const QString& str )
+{
+ QStringList als = QStringList::split(";", str );
+ for (QStringList::Iterator it = als.begin(); it != als.end(); ++it ) {
+ QStringList alarm = QStringList::split(":", (*it), TRUE ); // allow empty
+ qWarning("alarm: %s", alarm.join("___").latin1() );
+ qWarning("alarm[0]: %s %s", alarm[0].latin1(),
+ OConversion::dateTimeFromString( alarm[0] ).toString().latin1() );
+ OPimAlarm al( alarm[2].toInt(), OConversion::dateTimeFromString( alarm[0] ),
+ alarm[1].toInt() );
+ add( al );
+ }
+}
+
+void OPimNotifyManager::remindersFromString( const QString& str )
+{
+
+ QStringList rems = QStringList::split(";", str );
+ for (QStringList::Iterator it = rems.begin(); it != rems.end(); ++it ) {
+ OPimReminder rem( (*it).toInt() );
+ add( rem );
+ }
+
+}
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 @@
+#ifndef OPIE_PIM_NOTIFY_MANAGER_H
+#define OPIE_PIM_NOTIFY_MANAGER_H
+
+#include <qvaluelist.h>
+
+#include <opie/opimnotify.h>
+
+/**
+ * The notify manager keeps track of the Notifiers....
+ */
+class OPimNotifyManager {
+public:
+ typedef QValueList<OPimReminder> Reminders;
+ typedef QValueList<OPimAlarm> Alarms;
+ OPimNotifyManager( const Reminders& rems = Reminders(), const Alarms& alarms = Alarms() );
+ ~OPimNotifyManager();
+
+ /* we will cast it for you ;) */
+ void add( const OPimNotify& );
+ void remove( const OPimNotify& );
+ /* replaces all with this one! */
+ void replace( const OPimNotify& );
+
+ Reminders reminders()const;
+
+ /**
+ * Return
+ */
+ Alarms alarms()const;
+
+ /**
+ * Return alarm at DateTime "when". If more than one is registered at this
+ * DateTime, the first one is returned.
+ * If none was found, an empty Alarm is returned.
+ * @param when The date and time of the returned alarm
+ * @param found Returns true if anything was found.
+ * @return Returns the found alarm at given DateTime. It is empty if found is false
+ * (nothing could be found at given date and time)
+ */
+ OPimAlarm alarmAtDateTime( const QDateTime& when, bool& found ) const;
+
+ void setAlarms( const Alarms& );
+ void setReminders( const Reminders& );
+
+ /* register is a Ansi C keyword... */
+ /**
+ * This function will register the Notify to the Alarm Server
+ * or datebook depending on the type of the notify
+ */
+ void registerNotify( const OPimNotify& );
+
+ /**
+ * this will do the opposite..
+ */
+ void deregister( const OPimNotify& );
+
+ bool isEmpty()const;
+
+ /**
+ * Return all alarms as string
+ */
+ QString alarmsToString() const;
+ /**
+ * Return all notifiers as string
+ */
+ QString remindersToString() const;
+
+ /**
+ * Convert string to alarms
+ * @param str String created by alarmsToString()
+ */
+ void alarmsFromString( const QString& str );
+
+ /**
+ * Convert string to reminders
+ * @param str String created by remindersToString()
+ */
+ void remindersFromString( const QString& str );
+
+
+
+private:
+ Reminders m_rem;
+ Alarms m_al;
+
+ class Private;
+ Private *d;
+
+};
+
+#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 @@
+#include <qarray.h>
+
+#include <qpe/categories.h>
+#include <qpe/categoryselect.h>
+
+#include "opimrecord.h"
+
+Qtopia::UidGen OPimRecord::m_uidGen( Qtopia::UidGen::Qtopia );
+
+
+OPimRecord::OPimRecord( int uid )
+ : Qtopia::Record() {
+
+ m_lastHit = -1;
+ setUid( uid );
+}
+OPimRecord::~OPimRecord() {
+}
+OPimRecord::OPimRecord( const OPimRecord& rec )
+ : Qtopia::Record( rec )
+{
+ (*this) = rec;
+}
+
+OPimRecord &OPimRecord::operator=( const OPimRecord& rec) {
+ if ( this == &rec ) return *this;
+
+ Qtopia::Record::operator=( rec );
+ m_xrefman = rec.m_xrefman;
+ m_lastHit = rec.m_lastHit;
+
+ return *this;
+}
+/*
+ * category names
+ */
+QStringList OPimRecord::categoryNames( const QString& appname ) const {
+ QStringList list;
+ QArray<int> cats = categories();
+ Categories catDB;
+ catDB.load( categoryFileName() );
+
+ for (uint i = 0; i < cats.count(); i++ ) {
+ list << catDB.label( appname, cats[i] );
+ }
+
+ return list;
+}
+void OPimRecord::setCategoryNames( const QStringList& ) {
+
+}
+void OPimRecord::addCategoryName( const QString& ) {
+ Categories catDB;
+ catDB.load( categoryFileName() );
+
+
+}
+bool OPimRecord::isEmpty()const {
+ return ( uid() == 0 );
+}
+/*QString OPimRecord::crossToString()const {
+ QString str;
+ QMap<QString, QArray<int> >::ConstIterator it;
+ for (it = m_relations.begin(); it != m_relations.end(); ++it ) {
+ QArray<int> id = it.data();
+ for ( uint i = 0; i < id.size(); ++i ) {
+ str += it.key() + "," + QString::number( i ) + ";";
+ }
+ }
+ str = str.remove( str.length()-1, 1); // strip the ;
+ //qWarning("IDS " + str );
+
+ return str;
+ }*/
+/* if uid = 1 assign a new one */
+void OPimRecord::setUid( int uid ) {
+ if ( uid == 1)
+ uid = uidGen().generate();
+
+ Qtopia::Record::setUid( uid );
+};
+Qtopia::UidGen &OPimRecord::uidGen() {
+ return m_uidGen;
+}
+OPimXRefManager &OPimRecord::xrefmanager() {
+ return m_xrefman;
+}
+int OPimRecord::rtti(){
+ return 0;
+}
+
+/**
+ * now let's put our data into the stream
+ */
+/*
+ * First read UID
+ * Categories
+ * XRef
+ */
+bool OPimRecord::loadFromStream( QDataStream& stream ) {
+ int Int;
+ uint UInt;
+ stream >> Int;
+ setUid(Int);
+
+ /** Categories */
+ stream >> UInt;
+ QArray<int> array(UInt);
+ for (uint i = 0; i < UInt; i++ ) {
+ stream >> array[i];
+ }
+ setCategories( array );
+
+ /*
+ * now we do the X-Ref stuff
+ */
+ OPimXRef xref;
+ stream >> UInt;
+ for ( uint i = 0; i < UInt; i++ ) {
+ xref.setPartner( OPimXRef::One, partner( stream ) );
+ xref.setPartner( OPimXRef::Two, partner( stream ) );
+ m_xrefman.add( xref );
+ }
+
+ return true;
+}
+bool OPimRecord::saveToStream( QDataStream& stream )const {
+ /** UIDs */
+
+ stream << uid();
+
+ /** Categories */
+ stream << categories().count();
+ for ( uint i = 0; i < categories().count(); i++ ) {
+ stream << categories()[i];
+ }
+
+ /*
+ * first the XRef count
+ * then the xrefs
+ */
+ stream << m_xrefman.list().count();
+ for ( OPimXRef::ValueList::ConstIterator it = m_xrefman.list().begin();
+ it != m_xrefman.list().end(); ++it ) {
+ flush( (*it).partner( OPimXRef::One), stream );
+ flush( (*it).partner( OPimXRef::Two), stream );
+ }
+ return true;
+}
+void OPimRecord::flush( const OPimXRefPartner& par, QDataStream& str ) const{
+ str << par.service();
+ str << par.uid();
+ str << par.field();
+}
+OPimXRefPartner OPimRecord::partner( QDataStream& stream ) {
+ OPimXRefPartner par;
+ QString str;
+ int i;
+
+ stream >> str;
+ par.setService( str );
+
+ stream >> i;
+ par.setUid( i );
+
+ stream >> i ;
+ par.setField( i );
+
+ return par;
+}
+void OPimRecord::setLastHitField( int lastHit )const {
+ m_lastHit = lastHit;
+}
+int OPimRecord::lastHitField()const{
+ return m_lastHit;
+}
+QMap<QString, QString> OPimRecord::toExtraMap()const {
+ return customMap;
+}
+void OPimRecord::setExtraMap( const QMap<QString, QString>& map) {
+ customMap = map;
+}
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 @@
+#ifndef OPIE_PIM_RECORD_H
+#define OPIE_PIM_RECORD_H
+
+#include <qdatastream.h>
+#include <qmap.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+/*
+ * we need to get customMap which is private...
+ */
+#define private protected
+#include <qpe/palmtoprecord.h>
+#undef private
+
+#include <opie/opimxrefmanager.h>
+
+/**
+ * This is the base class for
+ * all PIM Records
+ *
+ */
+class OPimRecord : public Qtopia::Record {
+public:
+ /**
+ * c'tor
+ * uid of 0 isEmpty
+ * uid of 1 will be assigned a new one
+ */
+ OPimRecord(int uid = 0);
+ ~OPimRecord();
+
+ /**
+ * copy c'tor
+ */
+ OPimRecord( const OPimRecord& rec );
+
+ /**
+ * copy operator
+ */
+ OPimRecord &operator=( const OPimRecord& );
+
+ /**
+ * category names resolved
+ */
+ QStringList categoryNames( const QString& appname )const;
+
+ /**
+ * set category names they will be resolved
+ */
+ void setCategoryNames( const QStringList& );
+
+ /**
+ * addCategoryName adds a name
+ * to the internal category list
+ */
+ void addCategoryName( const QString& );
+
+ /**
+ * if a Record isEmpty
+ * it's empty if it's 0
+ */
+ virtual bool isEmpty()const;
+
+ /**
+ * toRichText summary
+ */
+ virtual QString toRichText()const = 0;
+
+ /**
+ * a small one line summary
+ */
+ virtual QString toShortText()const = 0;
+
+ /**
+ * the name of the Record
+ */
+ virtual QString type()const = 0;
+
+ /**
+ * matches the Records the regular expression?
+ */
+ virtual bool match( const QString &regexp ) const
+ {setLastHitField( -1 );
+ return Qtopia::Record::match(QRegExp(regexp));};
+
+ /**
+ * if implemented this function returns which item has been
+ * last hit by the match() function.
+ * or -1 if not implemented or no hit has occured
+ */
+ int lastHitField()const;
+
+ /**
+ * converts the internal structure to a map
+ */
+ virtual QMap<int, QString> toMap()const = 0;
+ // virtual fromMap( const <int, QString>& map ) = 0; // Should be added in the future (eilers)
+
+ /**
+ * key value representation of extra items
+ */
+ QMap<QString, QString> toExtraMap()const;
+ void setExtraMap( const QMap<QString, QString>& );
+
+ /**
+ * the name for a recordField
+ */
+ virtual QString recordField(int)const = 0;
+
+ /**
+ * returns a reference of the
+ * Cross Reference Manager
+ * Partner 'One' is THIS PIM RECORD!
+ * 'Two' is the Partner where we link to
+ */
+ OPimXRefManager& xrefmanager();
+
+ /**
+ * set the uid
+ */
+ virtual void setUid( int uid );
+
+ /*
+ * used inside the Templates for casting
+ * REIMPLEMENT in your ....
+ */
+ static int rtti();
+
+ /**
+ * some marshalling and de marshalling code
+ * saves the OPimRecord
+ * to and from a DataStream
+ */
+ virtual bool loadFromStream(QDataStream& );
+ virtual bool saveToStream( QDataStream& stream )const;
+
+protected:
+ // need to be const cause it is called from const methods
+ mutable int m_lastHit;
+ void setLastHitField( int lastHit )const;
+ Qtopia::UidGen &uidGen();
+// QString crossToString()const;
+
+private:
+ class OPimRecordPrivate;
+ OPimRecordPrivate *d;
+ OPimXRefManager m_xrefman;
+ static Qtopia::UidGen m_uidGen;
+
+private:
+ void flush( const OPimXRefPartner&, QDataStream& stream )const;
+ OPimXRefPartner partner( QDataStream& );
+};
+
+
+
+#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 @@
+#include <qcopchannel_qws.h>
+
+#include <qpe/qcopenvelope_qws.h>
+
+#include "otodoaccess.h"
+#include "ocontactaccess.h"
+
+//#include "opimfactory.h"
+#include "opimresolver.h"
+
+OPimResolver* OPimResolver::m_self = 0l;
+
+OPimResolver::OPimResolver() {
+ /* the built in channels */
+ m_builtIns << "Todolist" << "Addressbook" << "Datebook";
+}
+OPimResolver* OPimResolver::self() {
+ if (!m_self)
+ m_self = new OPimResolver();
+
+ return m_self;
+}
+
+/*
+ * FIXME use a cache here too
+ */
+OPimRecord* OPimResolver::record( const QString& service, int uid ) {
+ OPimRecord* rec = 0l;
+ OPimBase* base = backend( service );
+
+ if ( base )
+ rec = base->record( uid );
+ delete base;
+
+ return rec;
+}
+OPimRecord* OPimResolver::record( const QString& service ) {
+ return record( serviceId( service ) );
+}
+OPimRecord* OPimResolver::record( int rtti ) {
+ OPimRecord* rec = 0l;
+ switch( rtti ) {
+ case 1: /* todolist */
+ rec = new OTodo();
+ case 2: /* contact */
+ rec = new OContact();
+ default:
+ break;
+ }
+ /*
+ * FIXME resolve externally
+ */
+ if (!rec ) {
+ ;
+ }
+ return 0l;
+}
+bool OPimResolver::isBuiltIn( const QString& str) const{
+ return m_builtIns.contains( str );
+}
+QCString OPimResolver::qcopChannel( enum BuiltIn& built)const {
+ QCString str("QPE/");
+ switch( built ) {
+ case TodoList:
+ str += "Todolist";
+ break;
+ case DateBook:
+ str += "Datebook";
+ break;
+ case AddressBook:
+ str += "Addressbook";
+ break;
+ default:
+ break;
+ }
+
+ return str;
+}
+QCString OPimResolver::qcopChannel( const QString& service )const {
+ QCString str("QPE/");
+ str += service.latin1();
+ return str;
+}
+/*
+ * Implement services!!
+ * FIXME
+ */
+QCString OPimResolver::applicationChannel( enum BuiltIn& built)const {
+ QCString str("QPE/Application/");
+ switch( built ) {
+ case TodoList:
+ str += "todolist";
+ break;
+ case DateBook:
+ str += "datebook";
+ break;
+ case AddressBook:
+ str += "addressbook";
+ break;
+ }
+
+ return str;
+}
+QCString OPimResolver::applicationChannel( const QString& service )const {
+ QCString str("QPE/Application/");
+
+ if ( isBuiltIn( service ) ) {
+ if ( service == "Todolist" )
+ str += "todolist";
+ else if ( service == "Datebook" )
+ str += "datebook";
+ else if ( service == "Addressbook" )
+ str += "addressbook";
+ }else
+ ; // FIXME for additional stuff
+
+ return str;
+}
+QStringList OPimResolver::services()const {
+ return m_builtIns;
+}
+QString OPimResolver::serviceName( int rtti ) const{
+ QString str;
+ switch ( rtti ) {
+ case TodoList:
+ str = "Todolist";
+ break;
+ case DateBook:
+ str = "Datebook";
+ break;
+ case AddressBook:
+ str = "Addressbook";
+ break;
+ default:
+ break;
+ }
+ return str;
+ // FIXME me for 3rd party
+}
+int OPimResolver::serviceId( const QString& service ) {
+ int rtti = 0;
+ if ( service == "Todolist" )
+ rtti = TodoList;
+ else if ( service == "Datebook" )
+ rtti = DateBook;
+ else if ( service == "Addressbook" )
+ rtti = AddressBook;
+
+ return rtti;
+}
+/**
+ * check if the 'service' is registered and if so we'll
+ */
+bool OPimResolver::add( const QString& service, const OPimRecord& rec) {
+ if ( QCopChannel::isRegistered( applicationChannel( service ) ) ) {
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly );
+ if ( rec.saveToStream( arg ) ) {
+ QCopEnvelope env( applicationChannel( service ), "add(int,QByteArray)" );
+ env << rec.rtti();
+ env << data;
+ }else
+ return false;
+ }else{
+ OPimBase* base = backend( service );
+ if (!base ) return false;
+
+ base->load();
+ base->add( rec );
+ base->save();
+ delete base;
+ }
+
+ return true;
+}
+OPimBase* OPimResolver::backend( const QString& service ) {
+ return backend( serviceId( service ) );
+}
+OPimBase* OPimResolver::backend( int rtti ) {
+ OPimBase* base = 0l;
+ switch( rtti ) {
+ case TodoList:
+ base = new OTodoAccess();
+ break;
+ case DateBook:
+ break;
+ case AddressBook:
+ base = new OContactAccess("Resolver");
+ break;
+ default:
+ break;
+ }
+ // FIXME for 3rd party
+ if (!base )
+ ;
+
+ return base;
+}
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 @@
+#ifndef OPIE_PIM_RESOLVER
+#define OPIE_PIM_RESOLVER
+
+#include <qstring.h>
+#include <qvaluelist.h>
+
+#include <opie/otemplatebase.h>
+
+/**
+ * OPimResolver is a MetaClass to access
+ * available backends read only.
+ * It will be used to resolve uids + app names
+ * to full informations
+ * to traverse through a list of alarms, reminders
+ * to get access to built in PIM functionality
+ * and to more stuff
+ * THE PERFORMANCE will depend on THE BACKEND
+ * USING XML is a waste of memory!!!!!
+ */
+class OPimResolver {
+public:
+ enum BuiltIn { TodoList = 0,
+ DateBook,
+ AddressBook
+ };
+ static OPimResolver* self();
+
+
+ /**
+ * return a record for a uid
+ * and an service
+ * You've THE OWNERSHIP NOW!
+ */
+ OPimRecord *record( const QString& service, int uid );
+
+ /**
+ * return the QCopChannel for service
+ * When we will use Qtopia Services it will be used here
+ */
+ QCString qcopChannel( enum BuiltIn& )const;
+ QCString qcopChannel( const QString& service )const;
+
+ /**
+ * The Application channel (QPE/Application/name)
+ */
+ QCString applicationChannel( enum BuiltIn& )const;
+ QCString applicationChannel( const QString& service )const;
+
+ /**
+ * return a list of available services
+ */
+ QStringList services()const;
+ inline QString serviceName(int rrti )const;
+ int serviceId( const QString& Service);
+ /**
+ * add a record to a service... ;)
+ */
+ bool add( const QString& service, const OPimRecord& );
+
+
+ /**
+ * record returns an empty record for a given service.
+ * Be sure to delete it!!!
+ *
+ */
+ OPimRecord* record( const QString& service );
+ OPimRecord* record( int rtti );
+
+ /**
+ * you can cast to your
+ */
+ OPimBase* backend( const QString& service );
+ OPimBase* backend( int rtti );
+private:
+ OPimResolver();
+ void loadData();
+ inline bool isBuiltIn( const QString& )const;
+ OPimRecord* recordExtern( const QString&, int );
+ OPimRecord* recordExtern( const QString& );
+
+ static OPimResolver* m_self;
+ struct Data;
+ class Private;
+
+ Data* data;
+ Private* d;
+ QStringList m_builtIns;
+};
+
+#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 @@
+#include <qshared.h>
+
+#include "opimstate.h"
+
+/*
+ * for one int this does not make
+ * much sense but never the less
+ * we will do it for the future
+ */
+struct OPimState::Data : public QShared {
+ Data() : QShared(),state(Undefined) {
+ }
+ int state;
+};
+
+OPimState::OPimState( int state ) {
+ data = new Data;
+ data->state = state;
+}
+OPimState::OPimState( const OPimState& st) :
+ data( st.data ) {
+ /* ref up */
+ data->ref();
+}
+OPimState::~OPimState() {
+ if ( data->deref() ) {
+ delete data ;
+ data = 0;
+ }
+}
+bool OPimState::operator==( const OPimState& st) {
+ if ( data->state == st.data->state ) return true;
+
+ return false;
+}
+OPimState &OPimState::operator=( const OPimState& st) {
+ st.data->ref();
+ deref();
+ data = st.data;
+
+ return *this;
+}
+void OPimState::setState( int st) {
+ copyInternally();
+ data->state = st;
+}
+int OPimState::state()const {
+ return data->state;
+}
+void OPimState::deref() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0l;
+ }
+}
+void OPimState::copyInternally() {
+ /* we need to change it */
+ if ( data->count != 1 ) {
+ data->deref();
+ Data* d2 = new Data;
+ d2->state = data->state;
+ data = d2;
+ }
+}
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 @@
+#ifndef OPIE_PIM_STATE_H
+#define OPIE_PIM_STATE_H
+
+#include <qstring.h>
+
+/**
+ * The State of a Task
+ * This class encapsules the state of a todo
+ * and it's shared too
+ */
+/*
+ * in c a simple struct would be enough ;)
+ * g_new_state();
+ * g_do_some_thing( state_t* );
+ * ;)
+ */
+class OPimState {
+public:
+ enum State {
+ Started = 0,
+ Postponed,
+ Finished,
+ NotStarted,
+ Undefined
+ };
+ OPimState( int state = Undefined );
+ OPimState( const OPimState& );
+ ~OPimState();
+
+ bool operator==( const OPimState& );
+ OPimState &operator=( const OPimState& );
+ void setState( int state);
+ int state()const;
+private:
+ void deref();
+ inline void copyInternally();
+
+ struct Data;
+ Data* data;
+
+ class Private;
+ Private *d;
+};
+
+
+#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 @@
+#include "opimxref.h"
+
+OPimXRef::OPimXRef( const OPimXRefPartner& one, const OPimXRefPartner& two )
+ : m_partners(2)
+{
+ m_partners[0] = one;
+ m_partners[1] = two;
+}
+OPimXRef::OPimXRef()
+ : m_partners(2)
+{
+
+}
+OPimXRef::OPimXRef( const OPimXRef& ref) {
+ *this = ref;
+}
+OPimXRef::~OPimXRef() {
+}
+OPimXRef &OPimXRef::operator=( const OPimXRef& ref) {
+ m_partners = ref.m_partners;
+ m_partners.detach();
+
+ return* this;
+}
+bool OPimXRef::operator==( const OPimXRef& oper ) {
+ if ( m_partners == oper.m_partners ) return true;
+
+ return false;
+}
+OPimXRefPartner OPimXRef::partner( enum Partners par) const{
+ return m_partners[par];
+}
+void OPimXRef::setPartner( enum Partners par, const OPimXRefPartner& part) {
+ m_partners[par] = part;
+}
+bool OPimXRef::containsString( const QString& string ) const{
+ if ( m_partners[One].service() == string ||
+ m_partners[Two].service() == string ) return true;
+
+ return false;
+}
+bool OPimXRef::containsUid( int uid ) const{
+ if ( m_partners[One].uid() == uid ||
+ m_partners[Two].uid() == uid ) return true;
+
+ return false;
+}
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 @@
+#ifndef OPIM_XREF_H
+#define OPIM_XREF_H
+
+#include <qarray.h>
+#include <qvaluelist.h>
+
+#include <opie/opimxrefpartner.h>
+
+/**
+ * this is a Cross Referecne between
+ * two Cross Reference Partners
+ */
+class OPimXRef {
+public:
+ typedef QValueList<OPimXRef> ValueList;
+ enum Partners { One, Two };
+ OPimXRef( const OPimXRefPartner& ONE, const OPimXRefPartner& );
+ OPimXRef();
+ OPimXRef( const OPimXRef& );
+ ~OPimXRef();
+
+ OPimXRef &operator=( const OPimXRef& );
+ bool operator==( const OPimXRef& );
+
+ OPimXRefPartner partner( enum Partners )const;
+
+ void setPartner( enum Partners, const OPimXRefPartner& );
+
+ bool containsString( const QString& service)const;
+ bool containsUid( int uid )const;
+
+private:
+ QArray<OPimXRefPartner> m_partners;
+
+ class Private;
+ Private *d;
+};
+
+#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 @@
+#include "opimxrefmanager.h"
+
+
+OPimXRefManager::OPimXRefManager() {
+}
+OPimXRefManager::OPimXRefManager( const OPimXRefManager& ref) {
+ m_list = ref.m_list;
+}
+OPimXRefManager::~OPimXRefManager() {
+}
+OPimXRefManager &OPimXRefManager::operator=( const OPimXRefManager& ref) {
+ m_list = ref.m_list;
+ return *this;
+}
+bool OPimXRefManager::operator==( const OPimXRefManager& /*ref*/) {
+ // if ( m_list == ref.m_list ) return true;
+
+ return false;
+}
+void OPimXRefManager::add( const OPimXRef& ref) {
+ m_list.append( ref );
+}
+void OPimXRefManager::remove( const OPimXRef& ref) {
+ m_list.remove( ref );
+}
+void OPimXRefManager::replace( const OPimXRef& ref) {
+ m_list.remove( ref );
+ m_list.append( ref );
+}
+void OPimXRefManager::clear() {
+ m_list.clear();
+}
+QStringList OPimXRefManager::apps()const {
+ OPimXRef::ValueList::ConstIterator it;
+ QStringList list;
+
+ QString str;
+ for ( it = m_list.begin(); it != m_list.end(); ++it ) {
+ str = (*it).partner( OPimXRef::One ).service();
+ if ( !list.contains( str ) ) list << str;
+
+ str = (*it).partner( OPimXRef::Two ).service();
+ if ( !list.contains( str ) ) list << str;
+ }
+ return list;
+}
+OPimXRef::ValueList OPimXRefManager::list()const {
+ return m_list;
+}
+OPimXRef::ValueList OPimXRefManager::list( const QString& appName )const{
+ OPimXRef::ValueList list;
+ OPimXRef::ValueList::ConstIterator it;
+
+ for ( it = m_list.begin(); it != m_list.end(); ++it ) {
+ if ( (*it).containsString( appName ) )
+ list.append( (*it) );
+ }
+
+ return list;
+}
+OPimXRef::ValueList OPimXRefManager::list( int uid )const {
+ OPimXRef::ValueList list;
+ OPimXRef::ValueList::ConstIterator it;
+
+ for ( it = m_list.begin(); it != m_list.end(); ++it ) {
+ if ( (*it).containsUid( uid ) )
+ list.append( (*it) );
+ }
+
+ return list;
+}
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 @@
+#ifndef OPIM_XREF_MANAGER_H
+#define OPIM_XREF_MANAGER_H
+
+#include <qstringlist.h>
+
+#include <opie/opimxref.h>
+
+/**
+ * This is a simple manager for
+ * OPimXRefs.
+ * It allows addition, removing, replacing
+ * clearing and 'querying' the XRef...
+ */
+class OPimXRefManager {
+public:
+ OPimXRefManager();
+ OPimXRefManager( const OPimXRefManager& );
+ ~OPimXRefManager();
+
+ OPimXRefManager& operator=( const OPimXRefManager& );
+ bool operator==( const OPimXRefManager& );
+
+ void add( const OPimXRef& );
+ void remove( const OPimXRef& );
+ void replace( const OPimXRef& );
+
+ void clear();
+
+ /**
+ * apps participating
+ */
+ QStringList apps()const;
+ OPimXRef::ValueList list()const;
+ OPimXRef::ValueList list( const QString& service )const;
+ OPimXRef::ValueList list( int uid )const;
+
+private:
+ OPimXRef::ValueList m_list;
+ class Private;
+ Private *d;
+};
+
+#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 @@
+#include "opimxrefpartner.h"
+
+OPimXRefPartner::OPimXRefPartner( const QString& appName,
+ int uid, int field )
+ : m_app(appName), m_uid(uid), m_field( field ) {
+}
+OPimXRefPartner::OPimXRefPartner( const OPimXRefPartner& ref ) {
+ *this = ref;
+}
+OPimXRefPartner::~OPimXRefPartner() {
+}
+OPimXRefPartner &OPimXRefPartner::operator=( const OPimXRefPartner& par ) {
+ m_app = par.m_app;
+ m_uid = par.m_uid;
+ m_field = par.m_field;
+
+ return *this;
+}
+bool OPimXRefPartner::operator==( const OPimXRefPartner& par ) {
+ if ( m_app != par.m_app ) return false;
+ if ( m_uid != par.m_uid ) return false;
+ if ( m_field != par.m_field ) return false;
+
+ return true;
+}
+QString OPimXRefPartner::service()const {
+ return m_app;
+}
+int OPimXRefPartner::uid()const {
+ return m_uid;
+}
+int OPimXRefPartner::field()const {
+ return m_field;
+}
+void OPimXRefPartner::setService( const QString& appName ) {
+ m_app = appName;
+}
+void OPimXRefPartner::setUid( int uid ) {
+ m_uid = uid;
+}
+void OPimXRefPartner::setField( int field ) {
+ m_field = field;
+}
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 @@
+#ifndef OPIM_XREF_PARTNER_H
+#define OPIM_XREF_PARTNER_H
+
+#include <qstring.h>
+
+/**
+ * This class represents one partner
+ * of a Cross Reference.
+ * In Opie one application
+ * can link one uid
+ * with one tableId( fieldId ) to another.
+ */
+class OPimXRefPartner {
+public:
+ OPimXRefPartner( const QString& service = QString::null,
+ int uid = 0, int field = -1 );
+ OPimXRefPartner( const OPimXRefPartner& );
+ OPimXRefPartner& operator=( const OPimXRefPartner& );
+ ~OPimXRefPartner();
+
+ bool operator==(const OPimXRefPartner& );
+
+ QString service()const;
+ int uid()const;
+ int field()const;
+
+ void setService( const QString& service );
+ void setUid( int uid );
+ void setField( int field );
+private:
+ QString m_app;
+ int m_uid;
+ int m_field;
+
+ class Private;
+ Private* d;
+};
+
+
+#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 @@
+
+#ifndef OPIE_RECORD_LIST_H
+#define OPIE_RECORD_LIST_H
+
+#include <qarray.h>
+
+#include "otemplatebase.h"
+#include "opimrecord.h"
+
+class ORecordListIteratorPrivate;
+/**
+ * Our List Iterator
+ * it behaves like STL or Qt
+ *
+ * for(it = list.begin(); it != list.end(); ++it )
+ * doSomeCoolStuff( (*it) );
+ */
+template <class T> class ORecordList;
+template <class T = OPimRecord>
+class ORecordListIterator {
+ friend class ORecordList<T>;
+public:
+ typedef OTemplateBase<T> Base;
+
+ /**
+ * The c'tor used internally from
+ * ORecordList
+ */
+ ORecordListIterator( const QArray<int>, const Base* );
+
+ /**
+ * The standard c'tor
+ */
+ ORecordListIterator();
+ ~ORecordListIterator();
+
+ ORecordListIterator( const ORecordListIterator& );
+ ORecordListIterator &operator=(const ORecordListIterator& );
+
+ /**
+ * a * operator ;)
+ * use it like this T = (*it);
+ */
+ T operator*();
+ ORecordListIterator &operator++();
+ ORecordListIterator &operator--();
+
+ bool operator==( const ORecordListIterator& it );
+ bool operator!=( const ORecordListIterator& it );
+
+ /**
+ * the current item
+ */
+ uint current()const;
+
+ /**
+ * the number of items
+ */
+ uint count()const;
+
+ /**
+ * sets the current item
+ */
+ void setCurrent( uint cur );
+
+private:
+ QArray<int> m_uids;
+ uint m_current;
+ const Base* m_temp;
+ bool m_end : 1;
+ T m_record;
+ bool m_direction :1;
+
+ /* d pointer for future versions */
+ ORecordListIteratorPrivate *d;
+};
+
+class ORecordListPrivate;
+/**
+ * The recordlist used as a return type
+ * from OPimAccessTemplate
+ */
+template <class T = OPimRecord >
+class ORecordList {
+public:
+ typedef OTemplateBase<T> Base;
+ typedef ORecordListIterator<T> Iterator;
+
+ /**
+ * c'tor
+ */
+ ORecordList () {
+ }
+ORecordList( const QArray<int>& ids,
+ const Base* );
+ ~ORecordList();
+
+ /**
+ * the first iterator
+ */
+ Iterator begin();
+
+ /**
+ * the end
+ */
+ Iterator end();
+
+ /**
+ * the number of items in the list
+ */
+ uint count()const;
+
+ T operator[]( uint i );
+ int uidAt(uint i );
+
+ /**
+ * Remove the contact with given uid
+ */
+ bool remove( int uid );
+
+ /*
+ ConstIterator begin()const;
+ ConstIterator end()const;
+ */
+private:
+ QArray<int> m_ids;
+ const Base* m_acc;
+ ORecordListPrivate *d;
+};
+
+/* ok now implement it */
+template <class T>
+ORecordListIterator<T>::ORecordListIterator() {
+ m_current = 0;
+ m_temp = 0l;
+ m_end = true;
+ m_record = T();
+ /* forward */
+ m_direction = TRUE;
+}
+template <class T>
+ORecordListIterator<T>::~ORecordListIterator() {
+/* nothing to delete */
+}
+
+template <class T>
+ORecordListIterator<T>::ORecordListIterator( const ORecordListIterator<T>& it) {
+// qWarning("ORecordListIterator copy c'tor");
+ m_uids = it.m_uids;
+ m_current = it.m_current;
+ m_temp = it.m_temp;
+ m_end = it.m_end;
+ m_record = it.m_record;
+ m_direction = it.m_direction;
+}
+
+template <class T>
+ORecordListIterator<T> &ORecordListIterator<T>::operator=( const ORecordListIterator<T>& it) {
+ m_uids = it.m_uids;
+ m_current = it.m_current;
+ m_temp = it.m_temp;
+ m_end = it.m_end;
+ m_record = it.m_record;
+
+ return *this;
+}
+
+template <class T>
+T ORecordListIterator<T>::operator*() {
+ //qWarning("operator* %d %d", m_current, m_uids[m_current] );
+ if (!m_end )
+ m_record = m_temp->find( m_uids[m_current], m_uids, m_current,
+ m_direction ? Base::Forward :
+ Base::Reverse );
+ else
+ m_record = T();
+
+ return m_record;
+}
+
+template <class T>
+ORecordListIterator<T> &ORecordListIterator<T>::operator++() {
+ m_direction = true;
+ if (m_current < m_uids.count() ) {
+ m_end = false;
+ ++m_current;
+ }else
+ m_end = true;
+
+ return *this;
+}
+template <class T>
+ORecordListIterator<T> &ORecordListIterator<T>::operator--() {
+ m_direction = false;
+ if ( m_current > 0 ) {
+ --m_current;
+ m_end = false;
+ } else
+ m_end = true;
+
+ return *this;
+}
+
+template <class T>
+bool ORecordListIterator<T>::operator==( const ORecordListIterator<T>& it ) {
+
+ /* if both are at we're the same.... */
+ if ( m_end == it.m_end ) return true;
+
+ if ( m_uids != it.m_uids ) return false;
+ if ( m_current != it.m_current ) return false;
+ if ( m_temp != it.m_temp ) return false;
+
+ return true;
+}
+template <class T>
+bool ORecordListIterator<T>::operator!=( const ORecordListIterator<T>& it ) {
+ return !(*this == it );
+}
+template <class T>
+ORecordListIterator<T>::ORecordListIterator( const QArray<int> uids,
+ const Base* t )
+ : m_uids( uids ), m_current( 0 ), m_temp( t ), m_end( false ),
+ m_direction( false )
+{
+ /* if the list is empty we're already at the end of the list */
+ if (uids.count() == 0 )
+ m_end = true;
+}
+template <class T>
+uint ORecordListIterator<T>::current()const {
+ return m_current;
+}
+template <class T>
+void ORecordListIterator<T>::setCurrent( uint cur ) {
+ if( cur < m_uids.count() ) {
+ m_end = false;
+ m_current= cur;
+ }
+}
+template <class T>
+uint ORecordListIterator<T>::count()const {
+ return m_uids.count();
+}
+template <class T>
+ORecordList<T>::ORecordList( const QArray<int>& ids,
+ const Base* acc )
+ : m_ids( ids ), m_acc( acc )
+{
+}
+template <class T>
+ORecordList<T>::~ORecordList() {
+/* nothing to do here */
+}
+template <class T>
+typename ORecordList<T>::Iterator ORecordList<T>::begin() {
+ Iterator it( m_ids, m_acc );
+ return it;
+}
+template <class T>
+typename ORecordList<T>::Iterator ORecordList<T>::end() {
+ Iterator it( m_ids, m_acc );
+ it.m_end = true;
+ it.m_current = m_ids.count();
+
+ return it;
+}
+template <class T>
+uint ORecordList<T>::count()const {
+return m_ids.count();
+}
+template <class T>
+T ORecordList<T>::operator[]( uint i ) {
+ if ( i >= m_ids.count() )
+ return T();
+ /* forward */
+ return m_acc->find( m_ids[i], m_ids, i );
+}
+template <class T>
+int ORecordList<T>::uidAt( uint i ) {
+ return m_ids[i];
+}
+
+template <class T>
+bool ORecordList<T>::remove( int uid ) {
+ QArray<int> copy( m_ids.count() );
+ int counter = 0;
+ bool ret_val = false;
+
+ for (uint i = 0; i < m_ids.count(); i++){
+ if ( m_ids[i] != uid ){
+ copy[counter++] = m_ids[i];
+
+ }else
+ ret_val = true;
+ }
+
+ copy.resize( counter );
+ m_ids = copy;
+
+
+ return ret_val;
+}
+
+
+#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 @@
+#include <time.h>
+
+#include <qshared.h>
+
+#include <qtopia/timeconversion.h>
+
+#include "otimezone.h"
+#include "orecur.h"
+
+struct ORecur::Data : public QShared {
+ Data() : QShared() {
+ type = ORecur::NoRepeat;
+ freq = -1;
+ days = 0;
+ pos = 0;
+ create = QDateTime::currentDateTime();
+ hasEnd = FALSE;
+ end = QDate::currentDate();
+ }
+ char days; // Q_UINT8 for 8 seven days;)
+ ORecur::RepeatType type;
+ int freq;
+ int pos;
+ bool hasEnd : 1;
+ QDate end;
+ QDateTime create;
+ int rep;
+ QString app;
+ ExceptionList list;
+ QDate start;
+};
+
+
+ORecur::ORecur() {
+ data = new Data;
+}
+
+ORecur::ORecur( const QMap<int, QString>& map )
+{
+ ORecur();
+ fromMap( map );
+}
+
+
+ORecur::ORecur( const ORecur& rec)
+ : data( rec.data )
+{
+ data->ref();
+}
+ORecur::~ORecur() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0l;
+ }
+}
+void ORecur::deref() {
+ if ( data->deref() ) {
+ delete data;
+ data = 0l;
+ }
+}
+bool ORecur::operator==( const ORecur& )const {
+ return false;
+}
+ORecur &ORecur::operator=( const ORecur& re) {
+ if ( *this == re ) return *this;
+
+ re.data->ref();
+ deref();
+ data = re.data;
+
+ return *this;
+}
+bool ORecur::doesRecur()const {
+ return !( type() == NoRepeat );
+}
+/*
+ * we try to be smart here
+ *
+ */
+bool ORecur::doesRecur( const QDate& date ) {
+ /* the day before the recurrance */
+ QDate da = date.addDays(-1);
+
+ QDate recur;
+ if (!nextOcurrence( da, recur ) )
+ return false;
+
+ return (recur == date);
+}
+// FIXME unuglify!
+// GPL from Datebookdb.cpp
+// FIXME exception list!
+bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
+ bool stillLooking;
+ stillLooking = p_nextOccurrence( from, next );
+ while ( stillLooking && data->list.contains(next) )
+ stillLooking = p_nextOccurrence( next.addDays(1), next );
+
+ return stillLooking;
+}
+bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) {
+
+ // easy checks, first are we too far in the future or too far in the past?
+ QDate tmpDate;
+ int freq = frequency();
+ int diff, diff2, a;
+ int iday, imonth, iyear;
+ int dayOfWeek = 0;
+ int firstOfWeek = 0;
+ int weekOfMonth;
+
+
+ if (hasEndDate() && endDate() < from)
+ return FALSE;
+
+ if (start() >= from ) {
+ next = start();
+ return TRUE;
+ }
+
+ switch ( type() ) {
+ case Weekly:
+ /* weekly is just daily by 7 */
+ /* first convert the repeatPattern.Days() mask to the next
+ day of week valid after from */
+ dayOfWeek = from.dayOfWeek();
+ dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */
+
+ /* this is done in case freq > 1 and from in week not
+ for this round */
+ // firstOfWeek = 0; this is already done at decl.
+ while(!((1 << firstOfWeek) & days() ))
+ firstOfWeek++;
+
+ /* there is at least one 'day', or there would be no event */
+ while(!((1 << (dayOfWeek % 7)) & days() ))
+ dayOfWeek++;
+
+ dayOfWeek = dayOfWeek % 7; /* the actual day of week */
+ dayOfWeek -= start().dayOfWeek() -1;
+
+ firstOfWeek = firstOfWeek % 7; /* the actual first of week */
+ firstOfWeek -= start().dayOfWeek() -1;
+
+ // dayOfWeek may be negitive now
+ // day of week is number of days to add to start day
+
+ freq *= 7;
+ // FALL-THROUGH !!!!!
+ case Daily:
+ // the add is for the possible fall through from weekly */
+ if(start().addDays(dayOfWeek) > from) {
+ /* first week exception */
+ next = QDate(start().addDays(dayOfWeek) );
+ if ((next > endDate())
+ && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ }
+ /* if from is middle of a non-week */
+
+ diff = start().addDays(dayOfWeek).daysTo(from) % freq;
+ diff2 = start().addDays(firstOfWeek).daysTo(from) % freq;
+
+ if(diff != 0)
+ diff = freq - diff;
+ if(diff2 != 0)
+ diff2 = freq - diff2;
+ diff = QMIN(diff, diff2);
+
+ next = QDate(from.addDays(diff));
+ if ( (next > endDate())
+ && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ case MonthlyDay:
+ iday = from.day();
+ iyear = from.year();
+ imonth = from.month();
+ /* find equivelent day of month for this month */
+ dayOfWeek = start().dayOfWeek();
+ weekOfMonth = (start().day() - 1) / 7;
+
+ /* work out when the next valid month is */
+ a = from.year() - start().year();
+ a *= 12;
+ a = a + (imonth - start().month());
+ /* a is e.start()monthsFrom(from); */
+ if(a % freq) {
+ a = freq - (a % freq);
+ imonth = from.month() + a;
+ if (imonth > 12) {
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ }
+ }
+ /* imonth is now the first month after or on
+ from that matches the frequency given */
+
+ /* find for this month */
+ tmpDate = QDate( iyear, imonth, 1 );
+
+ iday = 1;
+ iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
+ iday += 7 * weekOfMonth;
+ while (iday > tmpDate.daysInMonth()) {
+ imonth += freq;
+ if (imonth > 12) {
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ }
+ tmpDate = QDate( iyear, imonth, 1 );
+ /* these loops could go for a while, check end case now */
+ if ((tmpDate > endDate()) && hasEndDate() )
+ return FALSE;
+ iday = 1;
+ iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
+ iday += 7 * weekOfMonth;
+ }
+ tmpDate = QDate(iyear, imonth, iday);
+
+ if (tmpDate >= from) {
+ next = tmpDate;
+ if ((next > endDate() ) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ }
+
+ /* need to find the next iteration */
+ do {
+ imonth += freq;
+ if (imonth > 12) {
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ }
+ tmpDate = QDate( iyear, imonth, 1 );
+ /* these loops could go for a while, check end case now */
+ if ((tmpDate > endDate()) && hasEndDate() )
+ return FALSE;
+ iday = 1;
+ iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
+ iday += 7 * weekOfMonth;
+ } while (iday > tmpDate.daysInMonth());
+ tmpDate = QDate(iyear, imonth, iday);
+
+ next = tmpDate;
+ if ((next > endDate()) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ case MonthlyDate:
+ iday = start().day();
+ iyear = from.year();
+ imonth = from.month();
+
+ a = from.year() - start().year();
+ a *= 12;
+ a = a + (imonth - start().month());
+ /* a is e.start()monthsFrom(from); */
+ if(a % freq) {
+ a = freq - (a % freq);
+ imonth = from.month() + a;
+ if (imonth > 12) {
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ }
+ }
+ /* imonth is now the first month after or on
+ from that matches the frequencey given */
+
+ /* this could go for a while, worse case, 4*12 iterations, probably */
+ while(!QDate::isValid(iyear, imonth, iday) ) {
+ imonth += freq;
+ if (imonth > 12) {
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ }
+ /* these loops could go for a while, check end case now */
+ if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
+ return FALSE;
+ }
+
+ if(QDate(iyear, imonth, iday) >= from) {
+ /* done */
+ next = QDate(iyear, imonth, iday);
+ if ((next > endDate()) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ }
+
+ /* ok, need to cycle */
+ imonth += freq;
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+
+ while(!QDate::isValid(iyear, imonth, iday) ) {
+ imonth += freq;
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
+ return FALSE;
+ }
+
+ next = QDate(iyear, imonth, iday);
+ if ((next > endDate()) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ case Yearly:
+ iday = start().day();
+ imonth = start().month();
+ iyear = from.year(); // after all, we want to start in this year
+
+ diff = 1;
+ if(imonth == 2 && iday > 28) {
+ /* leap year, and it counts, calculate actual frequency */
+ if(freq % 4)
+ if (freq % 2)
+ freq = freq * 4;
+ else
+ freq = freq * 2;
+ /* else divides by 4 already, leave freq alone */
+ diff = 4;
+ }
+
+ a = from.year() - start().year();
+ if(a % freq) {
+ a = freq - (a % freq);
+ iyear = iyear + a;
+ }
+
+ /* under the assumption we won't hit one of the special not-leap years twice */
+ if(!QDate::isValid(iyear, imonth, iday)) {
+ /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
+ iyear += freq;
+ }
+
+ if(QDate(iyear, imonth, iday) >= from) {
+ next = QDate(iyear, imonth, iday);
+
+ if ((next > endDate()) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ }
+ /* iyear == from.year(), need to advance again */
+ iyear += freq;
+ /* under the assumption we won't hit one of the special not-leap years twice */
+ if(!QDate::isValid(iyear, imonth, iday)) {
+ /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
+ iyear += freq;
+ }
+
+ next = QDate(iyear, imonth, iday);
+ if ((next > endDate()) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+ORecur::RepeatType ORecur::type()const{
+ return data->type;
+}
+int ORecur::frequency()const {
+ return data->freq;
+}
+int ORecur::position()const {
+ return data->pos;
+}
+char ORecur::days() const{
+ return data->days;
+}
+bool ORecur::hasEndDate()const {
+ return data->hasEnd;
+}
+QDate ORecur::endDate()const {
+ return data->end;
+}
+QDate ORecur::start()const{
+ return data->start;
+}
+QDateTime ORecur::createdDateTime()const {
+ return data->create;
+}
+int ORecur::repetition()const {
+ return data->rep;
+}
+QString ORecur::service()const {
+ return data->app;
+}
+ORecur::ExceptionList& ORecur::exceptions() {
+ return data->list;
+}
+void ORecur::setType( const RepeatType& z) {
+ checkOrModify();
+ data->type = z;
+}
+void ORecur::setFrequency( int freq ) {
+ checkOrModify();
+ data->freq = freq;
+}
+void ORecur::setPosition( int pos ) {
+ checkOrModify();
+ data->pos = pos;
+}
+void ORecur::setDays( char c ) {
+ checkOrModify();
+ data->days = c;
+}
+void ORecur::setEndDate( const QDate& dt) {
+ checkOrModify();
+ data->end = dt;
+}
+void ORecur::setCreatedDateTime( const QDateTime& t) {
+ checkOrModify();
+ data->create = t;
+}
+void ORecur::setHasEndDate( bool b) {
+ checkOrModify();
+ data->hasEnd = b;
+}
+void ORecur::setRepitition( int rep ) {
+ checkOrModify();
+ data->rep = rep;
+}
+void ORecur::setService( const QString& app ) {
+ checkOrModify();
+ data->app = app;
+}
+void ORecur::setStart( const QDate& dt ) {
+ checkOrModify();
+ data->start = dt;
+}
+void ORecur::checkOrModify() {
+ if ( data->count != 1 ) {
+ data->deref();
+ Data* d2 = new Data;
+ d2->days = data->days;
+ d2->type = data->type;
+ d2->freq = data->freq;
+ d2->pos = data->pos;
+ d2->hasEnd = data->hasEnd;
+ d2->end = data->end;
+ d2->create = data->create;
+ d2->rep = data->rep;
+ d2->app = data->app;
+ d2->list = data->list;
+ d2->start = data->start;
+ data = d2;
+ }
+}
+QString ORecur::toString()const {
+ QString buf;
+ QMap<int, QString> recMap = toMap();
+
+ buf += " rtype=\"";
+ buf += recMap[ORecur::RType];
+ buf += "\"";
+ if (data->days > 0 )
+ buf += " rweekdays=\"" + recMap[ORecur::RWeekdays] + "\"";
+ if ( data->pos != 0 )
+ buf += " rposition=\"" + recMap[ORecur::RPosition] + "\"";
+
+ buf += " rfreq=\"" + recMap[ORecur::RFreq] + "\"";
+ buf += " rhasenddate=\"" + recMap[ORecur::RHasEndDate]+ "\"";
+ if ( data->hasEnd )
+ buf += " enddt=\""
+ + recMap[ORecur::EndDate]
+ + "\"";
+ buf += " created=\"" + recMap[ORecur::Created] + "\"";
+
+ if ( data->list.isEmpty() ) return buf;
+ buf += " exceptions=\"";
+ buf += recMap[ORecur::Exceptions];
+ buf += "\" ";
+
+ return buf;
+}
+
+QString ORecur::rTypeString() const
+{
+ QString retString;
+ switch ( data->type ) {
+ case ORecur::Daily:
+ retString = "Daily";
+ break;
+ case ORecur::Weekly:
+ retString = "Weekly";
+ break;
+ case ORecur::MonthlyDay:
+ retString = "MonthlyDay";
+ break;
+ case ORecur::MonthlyDate:
+ retString = "MonthlyDate";
+ break;
+ case ORecur::Yearly:
+ retString = "Yearly";
+ break;
+ default:
+ retString = "NoRepeat";
+ break;
+
+ }
+
+ return retString;
+}
+
+QMap<QString, ORecur::RepeatType> ORecur::rTypeValueConvertMap() const
+{
+ QMap<QString, RepeatType> convertMap;
+
+ convertMap.insert( QString( "Daily" ), ORecur::Daily );
+ convertMap.insert( QString( "Weekly" ), ORecur::Weekly );
+ convertMap.insert( QString( "MonthlyDay" ), ORecur::MonthlyDay );
+ convertMap.insert( QString( "MonthlyDate" ), ORecur::MonthlyDate );
+ convertMap.insert( QString( "Yearly" ), ORecur::Yearly );
+ convertMap.insert( QString( "NoRepeat" ), ORecur::NoRepeat );
+
+ return convertMap;
+}
+
+
+QMap<int, QString> ORecur::toMap() const
+{
+ QMap<int, QString> retMap;
+
+ retMap.insert( ORecur::RType, rTypeString() );
+ retMap.insert( ORecur::RWeekdays, QString::number( static_cast<int>( data->days ) ) );
+ retMap.insert( ORecur::RPosition, QString::number(data->pos ) );
+ retMap.insert( ORecur::RFreq, QString::number( data->freq ) );
+ retMap.insert( ORecur::RHasEndDate, QString::number( static_cast<int>( data->hasEnd ) ) );
+ if( data -> hasEnd )
+ retMap.insert( ORecur::EndDate, QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) ) );
+ retMap.insert( ORecur::Created, QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) );
+
+ if ( data->list.isEmpty() ) return retMap;
+
+ // save exceptions list here!!
+ ExceptionList::ConstIterator it;
+ ExceptionList list = data->list;
+ QString exceptBuf;
+ QDate date;
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ date = (*it);
+ if ( it != list.begin() ) exceptBuf += " ";
+
+ exceptBuf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() );
+ }
+
+ retMap.insert( ORecur::Exceptions, exceptBuf );
+
+ return retMap;
+}
+
+void ORecur::fromMap( const QMap<int, QString>& map )
+{
+ QMap<QString, RepeatType> repTypeMap = rTypeValueConvertMap();
+
+ data -> type = repTypeMap[ map [ORecur::RType] ];
+ data -> days = (char) map[ ORecur::RWeekdays ].toInt();
+ data -> pos = map[ ORecur::RPosition ].toInt();
+ data -> freq = map[ ORecur::RFreq ].toInt();
+ data -> hasEnd= map[ ORecur::RHasEndDate ].toInt() ? true : false;
+ OTimeZone utc = OTimeZone::utc();
+ if ( data -> hasEnd ){
+ data -> end = utc.fromUTCDateTime( (time_t) map[ ORecur::EndDate ].toLong() ).date();
+ }
+ data -> create = utc.fromUTCDateTime( (time_t) map[ ORecur::Created ].toLong() ).date();
+
+#if 0
+ // FIXME: Exceptions currently not supported...
+ // Convert the list of exceptions from QString into ExceptionList
+ data -> list.clear();
+ QString exceptStr = map[ ORecur::Exceptions ];
+ QStringList exceptList = QStringList::split( " ", exceptStr );
+ ...
+#endif
+
+
+}
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 @@
+/*
+ * GPL from TT
+ */
+
+#ifndef OPIE_RECUR_H
+#define OPIE_RECUR_H
+
+#include <sys/types.h>
+
+#include <qdatetime.h>
+#include <qvaluelist.h>
+#include <qmap.h>
+
+
+/**
+ * Class to handle Recurrencies..
+ */
+
+class ORecur {
+public:
+ typedef QValueList<QDate> ExceptionList;
+ enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay,
+ MonthlyDate, Yearly };
+ enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08,
+ FRI = 0x10, SAT = 0x20, SUN = 0x40 };
+ enum Fields{ RType = 0, RWeekdays, RPosition, RFreq, RHasEndDate,
+ EndDate, Created, Exceptions };
+
+ ORecur();
+ ORecur( const QMap<int, QString>& map );
+ ORecur( const ORecur& );
+ ~ORecur();
+
+ ORecur &operator=( const ORecur& );
+ bool operator==(const ORecur& )const;
+
+ bool doesRecur()const;
+ /* if it recurrs on that day */
+ bool doesRecur( const QDate& );
+ RepeatType type()const;
+ int frequency()const;
+ int position()const;
+ char days()const;
+ bool hasEndDate()const;
+ QDate start()const;
+ QDate endDate()const;
+ QDateTime createdDateTime()const;
+ /**
+ * starting on monday=0, sunday=6
+ * for convience
+ */
+ bool repeatOnWeekDay( int day )const;
+
+ /**
+ * FromWhereToStart is not included!!!
+ */
+ bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate );
+
+ /**
+ * The module this ORecur belongs to
+ */
+ QString service()const;
+
+ /*
+ * reference to the exception list
+ */
+ ExceptionList &exceptions();
+
+ /**
+ * the current repetition
+ */
+ int repetition()const;
+
+ void setType( const RepeatType& );
+ void setFrequency( int freq );
+ void setPosition( int pos );
+ void setDays( char c);
+ void setEndDate( const QDate& dt );
+ void setStart( const QDate& dt );
+ void setCreatedDateTime( const QDateTime& );
+ void setHasEndDate( bool b );
+ void setRepitition(int );
+
+ void setService( const QString& ser );
+
+ QMap<int, QString> toMap() const;
+ void fromMap( const QMap<int, QString>& map );
+
+ /* almost internal */
+ QString toString()const;
+private:
+ bool p_nextOccurrence( const QDate& from, QDate& next );
+ void deref();
+ inline void checkOrModify();
+
+ /* Converts rType to String */
+ QString rTypeString() const;
+ /* Returns a map to convert Stringname for RType to RepeatType */
+ QMap<QString, RepeatType> rTypeValueConvertMap() const;
+
+ class Data;
+ Data* data;
+ class ORecurPrivate;
+ ORecurPrivate *d;
+};
+
+#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 @@
+#ifndef OPIE_TEMPLATE_BASE_H
+#define OPIE_TEMPLATE_BASE_H
+
+#include <qarray.h>
+
+#include <opie/opimrecord.h>
+
+
+/**
+ * Templates do not have a base class, This is why
+ * we've this class
+ * this is here to give us the possibility
+ * to have a common base class
+ * You may not want to use that interface internaly
+ * POOR mans interface
+ */
+class OPimBasePrivate;
+struct OPimBase {
+ /**
+ * return the rtti
+ */
+ virtual int rtti()= 0;
+ virtual OPimRecord* record()const = 0;
+ virtual OPimRecord* record(int uid)const = 0;
+ virtual bool add( const OPimRecord& ) = 0;
+ virtual bool remove( int uid ) = 0;
+ virtual bool remove( const OPimRecord& ) = 0;
+ virtual void clear() = 0;
+ virtual bool load() = 0;
+ virtual bool save() = 0;
+ virtual QArray<int> records()const = 0;
+ /*
+ * ADD editing here?
+ * -zecke
+ */
+private:
+ OPimBasePrivate* d;
+
+};
+/**
+ * internal template base
+ * T needs to implement the copy c'tor!!!
+ */
+class OTemplateBasePrivate;
+template <class T = OPimRecord>
+class OTemplateBase : public OPimBase {
+public:
+ enum CacheDirection { Forward=0, Reverse };
+ OTemplateBase() {
+ };
+ virtual ~OTemplateBase() {
+ }
+ virtual T find( int uid )const = 0;
+
+ /**
+ * read ahead find
+ */
+ virtual T find( int uid, const QArray<int>& items,
+ uint current, CacheDirection dir = Forward )const = 0;
+ virtual void cache( const T& )const = 0;
+ virtual void setSaneCacheSize( int ) = 0;
+
+ /* reimplement of OPimBase */
+ int rtti();
+ OPimRecord* record()const;
+ OPimRecord* record(int uid )const;
+ static T* rec();
+
+private:
+ OTemplateBasePrivate *d;
+};
+
+/*
+ * implementation
+ */
+template <class T>
+int
+OTemplateBase<T>::rtti() {
+ return T::rtti();
+}
+template <class T>
+OPimRecord* OTemplateBase<T>::record()const {
+ T* t = new T;
+ return t;
+}
+template <class T>
+OPimRecord* OTemplateBase<T>::record(int uid )const {
+ T t2 = find(uid );
+ T* t1 = new T(t2);
+
+ return t1;
+};
+template <class T>
+T* OTemplateBase<T>::rec() {
+ return new T;
+}
+
+#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 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+
+#include "otimezone.h"
+
+namespace {
+
+ QDateTime utcTime( time_t t) {
+ tm* broken = ::gmtime( &t );
+ QDateTime ret;
+ ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) );
+ ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) );
+ return ret;
+ }
+ QDateTime utcTime( time_t t, const QString& zone) {
+ QCString org = ::getenv( "TZ" );
+#ifndef Q_OS_MACX // Following line causes bus errors on Mac
+ ::setenv( "TZ", zone.latin1(), true );
+ ::tzset();
+
+ tm* broken = ::localtime( &t );
+ ::setenv( "TZ", org, true );
+#else
+#warning "Need a replacement for MacOSX!!"
+ tm* broken = ::localtime( &t );
+#endif
+
+ QDateTime ret;
+ ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) );
+ ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) );
+
+ return ret;
+ }
+ time_t to_Time_t( const QDateTime& utc, const QString& str ) {
+ QDate d = utc.date();
+ QTime t = utc.time();
+
+ tm broken;
+ broken.tm_year = d.year() - 1900;
+ broken.tm_mon = d.month() - 1;
+ broken.tm_mday = d.day();
+ broken.tm_hour = t.hour();
+ broken.tm_min = t.minute();
+ broken.tm_sec = t.second();
+
+ QCString org = ::getenv( "TZ" );
+#ifndef Q_OS_MACX // Following line causes bus errors on Mac
+ ::setenv( "TZ", str.latin1(), true );
+ ::tzset();
+
+ time_t ti = ::mktime( &broken );
+ ::setenv( "TZ", org, true );
+#else
+#warning "Need a replacement for MacOSX!!"
+ time_t ti = ::mktime( &broken );
+#endif
+ return ti;
+ }
+}
+OTimeZone::OTimeZone( const ZoneName& zone )
+ : m_name(zone) {
+}
+OTimeZone::~OTimeZone() {
+}
+
+bool OTimeZone::isValid()const {
+ return !m_name.isEmpty();
+}
+
+/*
+ * we will get the current timezone
+ * and ask it to convert to the timezone date
+ */
+QDateTime OTimeZone::toLocalDateTime( const QDateTime& dt) {
+ return OTimeZone::current().toDateTime( dt, *this );
+}
+QDateTime OTimeZone::toUTCDateTime( const QDateTime& dt ) {
+ return OTimeZone::utc().toDateTime( dt, *this );
+}
+QDateTime OTimeZone::fromUTCDateTime( time_t t) {
+ return utcTime( t );
+}
+QDateTime OTimeZone::toDateTime( time_t t) {
+ return utcTime( t, m_name );
+}
+/*
+ * convert dt to utc using zone.m_name
+ * convert utc -> timeZoneDT using this->m_name
+ */
+QDateTime OTimeZone::toDateTime( const QDateTime& dt, const OTimeZone& zone ) {
+ time_t utc = to_Time_t( dt, zone.m_name );
+ qWarning("%d %s", utc, zone.m_name.latin1() );
+ return utcTime( utc, m_name );
+}
+time_t OTimeZone::fromDateTime( const QDateTime& time ) {
+ return to_Time_t( time, m_name );
+}
+time_t OTimeZone::fromUTCDateTime( const QDateTime& time ) {
+ return to_Time_t( time, "UTC" );
+}
+OTimeZone OTimeZone::current() {
+ QCString str = ::getenv("TZ");
+ OTimeZone zone( str );
+ return zone;
+}
+OTimeZone OTimeZone::utc() {
+ return OTimeZone("UTC");
+}
+QString OTimeZone::timeZone()const {
+ return m_name;
+}
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 @@
+#ifndef OPIE_TIME_ZONE_H
+#define OPIE_TIME_ZONE_H
+
+#include <time.h>
+#include <qdatetime.h>
+
+/**
+ * A very primitive class to convert time
+ * from one timezone to another
+ * and to localtime
+ * and time_t
+ */
+class OTimeZone {
+ public:
+ typedef QString ZoneName;
+ OTimeZone( const ZoneName& = ZoneName::null );
+ virtual ~OTimeZone(); // just in case.
+
+ bool isValid()const;
+
+ /**
+ * converts the QDateTime to a DateTime
+ * in the local timezone
+ * if QDateTime is 25th Jan and takes place in Europe/Berlin at 12h
+ * and the current timezone is Europe/London the returned
+ * time will be 11h.
+ */
+ QDateTime toLocalDateTime( const QDateTime& dt );
+
+ /**
+ * converts the QDateTime to UTC time
+ */
+ QDateTime toUTCDateTime( const QDateTime& dt );
+
+ /**
+ * reads the time_t into a QDateTime using UTC as timezone!
+ */
+ QDateTime fromUTCDateTime( time_t );
+
+ /**
+ * converts the time_t to the time in the timezone
+ */
+ QDateTime toDateTime( time_t );
+
+ /**
+ * converts the QDateTime from one timezone to this timeZone
+ */
+ QDateTime toDateTime( const QDateTime&, const OTimeZone& timeZone );
+
+ /**
+ * converts the date time into a time_t. It takes the timezone into account
+ */
+ time_t fromDateTime( const QDateTime& );
+
+ /**
+ * converts the datetime with timezone UTC
+ */
+ time_t fromUTCDateTime( const QDateTime& );
+
+ static OTimeZone current();
+ static OTimeZone utc();
+
+ QString timeZone()const;
+ private:
+ ZoneName m_name;
+ class Private;
+ Private* d;
+};
+
+
+#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 @@
+
+#include <qobject.h>
+#include <qshared.h>
+
+
+
+#include <qpe/palmtopuidgen.h>
+#include <qpe/palmtoprecord.h>
+#include <qpe/categories.h>
+#include <qpe/categoryselect.h>
+#include <qpe/stringutil.h>
+
+
+#include "opimstate.h"
+#include "orecur.h"
+#include "opimmaintainer.h"
+#include "opimnotifymanager.h"
+#include "opimresolver.h"
+
+#include "otodo.h"
+
+
+struct OTodo::OTodoData : public QShared {
+ OTodoData() : QShared() {
+ recur = 0;
+ state = 0;
+ maintainer = 0;
+ notifiers = 0;
+ };
+ ~OTodoData() {
+ delete recur;
+ delete maintainer;
+ delete notifiers;
+ }
+
+ QDate date;
+ bool isCompleted:1;
+ bool hasDate:1;
+ int priority;
+ QString desc;
+ QString sum;
+ QMap<QString, QString> extra;
+ ushort prog;
+ OPimState *state;
+ ORecur *recur;
+ OPimMaintainer *maintainer;
+ QDate start;
+ QDate completed;
+ OPimNotifyManager *notifiers;
+};
+
+OTodo::OTodo(const OTodo &event )
+ : OPimRecord( event ), data( event.data )
+{
+ data->ref();
+// qWarning("ref up");
+}
+OTodo::~OTodo() {
+
+// qWarning("~OTodo " );
+ if ( data->deref() ) {
+// qWarning("OTodo::dereffing");
+ delete data;
+ data = 0l;
+ }
+}
+OTodo::OTodo(bool completed, int priority,
+ const QArray<int> &category,
+ const QString& summary,
+ const QString &description,
+ ushort progress,
+ bool hasDate, QDate date, int uid )
+ : OPimRecord( uid )
+{
+// qWarning("OTodoData " + summary);
+ setCategories( category );
+
+ data = new OTodoData;
+
+ data->date = date;
+ data->isCompleted = completed;
+ data->hasDate = hasDate;
+ data->priority = priority;
+ data->sum = summary;
+ data->prog = progress;
+ data->desc = Qtopia::simplifyMultiLineSpace(description );
+}
+OTodo::OTodo(bool completed, int priority,
+ const QStringList &category,
+ const QString& summary,
+ const QString &description,
+ ushort progress,
+ bool hasDate, QDate date, int uid )
+ : OPimRecord( uid )
+{
+// qWarning("OTodoData" + summary);
+ setCategories( idsFromString( category.join(";") ) );
+
+ data = new OTodoData;
+
+ data->date = date;
+ data->isCompleted = completed;
+ data->hasDate = hasDate;
+ data->priority = priority;
+ data->sum = summary;
+ data->prog = progress;
+ data->desc = Qtopia::simplifyMultiLineSpace(description );
+}
+bool OTodo::match( const QRegExp &regExp )const
+{
+ if( QString::number( data->priority ).find( regExp ) != -1 ){
+ setLastHitField( Priority );
+ return true;
+ }else if( data->hasDate && data->date.toString().find( regExp) != -1 ){
+ setLastHitField( HasDate );
+ return true;
+ }else if(data->desc.find( regExp ) != -1 ){
+ setLastHitField( Description );
+ return true;
+ }else if(data->sum.find( regExp ) != -1 ) {
+ setLastHitField( Summary );
+ return true;
+ }
+ return false;
+}
+bool OTodo::isCompleted() const
+{
+ return data->isCompleted;
+}
+bool OTodo::hasDueDate() const
+{
+ return data->hasDate;
+}
+bool OTodo::hasStartDate()const {
+ return data->start.isValid();
+}
+bool OTodo::hasCompletedDate()const {
+ return data->completed.isValid();
+}
+int OTodo::priority()const
+{
+ return data->priority;
+}
+QString OTodo::summary() const
+{
+ return data->sum;
+}
+ushort OTodo::progress() const
+{
+ return data->prog;
+}
+QDate OTodo::dueDate()const
+{
+ return data->date;
+}
+QDate OTodo::startDate()const {
+ return data->start;
+}
+QDate OTodo::completedDate()const {
+ return data->completed;
+}
+QString OTodo::description()const
+{
+ return data->desc;
+}
+bool OTodo::hasState() const{
+ if (!data->state ) return false;
+ return ( data->state->state() != OPimState::Undefined );
+}
+OPimState OTodo::state()const {
+ if (!data->state ) {
+ OPimState state;
+ return state;
+ }
+
+ return (*data->state);
+}
+bool OTodo::hasRecurrence()const {
+ if (!data->recur) return false;
+ return data->recur->doesRecur();
+}
+ORecur OTodo::recurrence()const {
+ if (!data->recur) return ORecur();
+
+ return (*data->recur);
+}
+bool OTodo::hasMaintainer()const {
+ if (!data->maintainer) return false;
+
+ return (data->maintainer->mode() != OPimMaintainer::Undefined );
+}
+OPimMaintainer OTodo::maintainer()const {
+ if (!data->maintainer) return OPimMaintainer();
+
+ return (*data->maintainer);
+}
+void OTodo::setCompleted( bool completed )
+{
+ changeOrModify();
+ data->isCompleted = completed;
+}
+void OTodo::setHasDueDate( bool hasDate )
+{
+ changeOrModify();
+ data->hasDate = hasDate;
+}
+void OTodo::setDescription(const QString &desc )
+{
+// qWarning( "desc " + desc );
+ changeOrModify();
+ data->desc = Qtopia::simplifyMultiLineSpace(desc );
+}
+void OTodo::setSummary( const QString& sum )
+{
+ changeOrModify();
+ data->sum = sum;
+}
+void OTodo::setPriority(int prio )
+{
+ changeOrModify();
+ data->priority = prio;
+}
+void OTodo::setDueDate( const QDate& date )
+{
+ changeOrModify();
+ data->date = date;
+}
+void OTodo::setStartDate( const QDate& date ) {
+ changeOrModify();
+ data->start = date;
+}
+void OTodo::setCompletedDate( const QDate& date ) {
+ changeOrModify();
+ data->completed = date;
+}
+void OTodo::setState( const OPimState& state ) {
+ changeOrModify();
+ if (data->state )
+ (*data->state) = state;
+ else
+ data->state = new OPimState( state );
+}
+void OTodo::setRecurrence( const ORecur& rec) {
+ changeOrModify();
+ if (data->recur )
+ (*data->recur) = rec;
+ else
+ data->recur = new ORecur( rec );
+}
+void OTodo::setMaintainer( const OPimMaintainer& pim ) {
+ changeOrModify();
+
+ if (data->maintainer )
+ (*data->maintainer) = pim;
+ else
+ data->maintainer = new OPimMaintainer( pim );
+}
+bool OTodo::isOverdue( )
+{
+ if( data->hasDate && !data->isCompleted)
+ return QDate::currentDate() > data->date;
+ return false;
+}
+void OTodo::setProgress(ushort progress )
+{
+ changeOrModify();
+ data->prog = progress;
+}
+QString OTodo::toShortText() const {
+ return summary();
+}
+/*!
+ Returns a richt text string
+*/
+QString OTodo::toRichText() const
+{
+ QString text;
+ QStringList catlist;
+
+ // summary
+ text += "<b><h3><img src=\"todo/TodoList\"> ";
+ if ( !summary().isEmpty() ) {
+ text += Qtopia::escapeString(summary() ).replace(QRegExp( "[\n]"), "" );
+ }
+ text += "</h3></b><br><hr><br>";
+
+ // description
+ if( !description().isEmpty() ){
+ text += "<b>" + QObject::tr( "Description:" ) + "</b><br>";
+ text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
+ }
+
+ // priority
+ int priorityval = priority();
+ text += "<b>" + QObject::tr( "Priority:") +" </b><img src=\"todo/priority" +
+ QString::number( priorityval ) + "\"> ";
+
+ switch ( priorityval )
+ {
+ case 1 : text += QObject::tr( "Very high" );
+ break;
+ case 2 : text += QObject::tr( "High" );
+ break;
+ case 3 : text += QObject::tr( "Normal" );
+ break;
+ case 4 : text += QObject::tr( "Low" );
+ break;
+ case 5 : text += QObject::tr( "Very low" );
+ break;
+ };
+ text += "<br>";
+
+ // progress
+ text += "<b>" + QObject::tr( "Progress:") + " </b>"
+ + QString::number( progress() ) + " %<br>";
+
+ // due date
+ if (hasDueDate() ){
+ QDate dd = dueDate();
+ int off = QDate::currentDate().daysTo( dd );
+
+ text += "<b>" + QObject::tr( "Deadline:" ) + " </b><font color=\"";
+ if ( off < 0 )
+ text += "#FF0000";
+ else if ( off == 0 )
+ text += "#FFFF00";
+ else if ( off > 0 )
+ text += "#00FF00";
+
+ text += "\">" + dd.toString() + "</font><br>";
+ }
+
+ // categories
+ text += "<b>" + QObject::tr( "Category:") + "</b> ";
+ text += categoryNames( "Todo List" ).join(", ");
+ text += "<br>";
+
+ return text;
+}
+bool OTodo::hasNotifiers()const {
+ if (!data->notifiers) return false;
+ return !data->notifiers->isEmpty();
+}
+OPimNotifyManager& OTodo::notifiers() {
+ if (!data->notifiers )
+ data->notifiers = new OPimNotifyManager;
+ return (*data->notifiers);
+}
+const OPimNotifyManager& OTodo::notifiers()const{
+ if (!data->notifiers )
+ data->notifiers = new OPimNotifyManager;
+
+ return (*data->notifiers);
+}
+
+bool OTodo::operator<( const OTodo &toDoEvent )const{
+ if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
+ if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
+ if( hasDueDate() && toDoEvent.hasDueDate() ){
+ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
+ return priority() < toDoEvent.priority();
+ }else{
+ return dueDate() < toDoEvent.dueDate();
+ }
+ }
+ return false;
+}
+bool OTodo::operator<=(const OTodo &toDoEvent )const
+{
+ if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
+ if( !hasDueDate() && toDoEvent.hasDueDate() ) return true;
+ if( hasDueDate() && toDoEvent.hasDueDate() ){
+ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
+ return priority() <= toDoEvent.priority();
+ }else{
+ return dueDate() <= toDoEvent.dueDate();
+ }
+ }
+ return true;
+}
+bool OTodo::operator>(const OTodo &toDoEvent )const
+{
+ if( !hasDueDate() && !toDoEvent.hasDueDate() ) return false;
+ if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
+ if( hasDueDate() && toDoEvent.hasDueDate() ){
+ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
+ return priority() > toDoEvent.priority();
+ }else{
+ return dueDate() > toDoEvent.dueDate();
+ }
+ }
+ return false;
+}
+bool OTodo::operator>=(const OTodo &toDoEvent )const
+{
+ if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
+ if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
+ if( hasDueDate() && toDoEvent.hasDueDate() ){
+ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
+ return priority() > toDoEvent.priority();
+ }else{
+ return dueDate() > toDoEvent.dueDate();
+ }
+ }
+ return true;
+}
+bool OTodo::operator==(const OTodo &toDoEvent )const
+{
+ if ( data->priority != toDoEvent.data->priority ) return false;
+ if ( data->priority != toDoEvent.data->prog ) return false;
+ if ( data->isCompleted != toDoEvent.data->isCompleted ) return false;
+ if ( data->hasDate != toDoEvent.data->hasDate ) return false;
+ if ( data->date != toDoEvent.data->date ) return false;
+ if ( data->sum != toDoEvent.data->sum ) return false;
+ if ( data->desc != toDoEvent.data->desc ) return false;
+ if ( data->maintainer != toDoEvent.data->maintainer )
+ return false;
+
+ return OPimRecord::operator==( toDoEvent );
+}
+void OTodo::deref() {
+
+// qWarning("deref in ToDoEvent");
+ if ( data->deref() ) {
+// qWarning("deleting");
+ delete data;
+ data= 0;
+ }
+}
+OTodo &OTodo::operator=(const OTodo &item )
+{
+ if ( this == &item ) return *this;
+
+ OPimRecord::operator=( item );
+ //qWarning("operator= ref ");
+ item.data->ref();
+ deref();
+ data = item.data;
+
+ return *this;
+}
+
+QMap<int, QString> OTodo::toMap() const {
+ QMap<int, QString> map;
+
+ map.insert( Uid, QString::number( uid() ) );
+ map.insert( Category, idsToString( categories() ) );
+ map.insert( HasDate, QString::number( data->hasDate ) );
+ map.insert( Completed, QString::number( data->isCompleted ) );
+ map.insert( Description, data->desc );
+ map.insert( Summary, data->sum );
+ map.insert( Priority, QString::number( data->priority ) );
+ map.insert( DateDay, QString::number( data->date.day() ) );
+ map.insert( DateMonth, QString::number( data->date.month() ) );
+ map.insert( DateYear, QString::number( data->date.year() ) );
+ map.insert( Progress, QString::number( data->prog ) );
+// map.insert( CrossReference, crossToString() );
+ /* FIXME!!! map.insert( State, );
+ map.insert( Recurrence, );
+ map.insert( Reminders, );
+ map.
+ */
+ return map;
+}
+
+/**
+ * change or modify looks at the ref count and either
+ * creates a new QShared Object or it can modify it
+ * right in place
+ */
+void OTodo::changeOrModify() {
+ if ( data->count != 1 ) {
+ qWarning("changeOrModify");
+ data->deref();
+ OTodoData* d2 = new OTodoData();
+ copy(data, d2 );
+ data = d2;
+ }
+}
+// WATCHOUT
+/*
+ * if you add something to the Data struct
+ * be sure to copy it here
+ */
+void OTodo::copy( OTodoData* src, OTodoData* dest ) {
+ dest->date = src->date;
+ dest->isCompleted = src->isCompleted;
+ dest->hasDate = src->hasDate;
+ dest->priority = src->priority;
+ dest->desc = src->desc;
+ dest->sum = src->sum;
+ dest->extra = src->extra;
+ dest->prog = src->prog;
+
+ if (src->state )
+ dest->state = new OPimState( *src->state );
+
+ if (src->recur )
+ dest->recur = new ORecur( *src->recur );
+
+ if (src->maintainer )
+ dest->maintainer = new OPimMaintainer( *src->maintainer )
+ ;
+ dest->start = src->start;
+ dest->completed = src->completed;
+
+ if (src->notifiers )
+ dest->notifiers = new OPimNotifyManager( *src->notifiers );
+}
+QString OTodo::type() const {
+ return QString::fromLatin1("OTodo");
+}
+QString OTodo::recordField(int /*id*/ )const {
+ return QString::null;
+}
+
+int OTodo::rtti(){
+ return OPimResolver::TodoList;
+}
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 @@
+
+#ifndef OPIE_TODO_EVENT_H
+#define OPIE_TODO_EVENT_H
+
+
+#include <qarray.h>
+#include <qmap.h>
+#include <qregexp.h>
+#include <qstringlist.h>
+#include <qdatetime.h>
+#include <qvaluelist.h>
+
+#include <qpe/recordfields.h>
+#include <qpe/palmtopuidgen.h>
+
+#include <opie/opimrecord.h>
+
+
+class OPimState;
+class ORecur;
+class OPimMaintainer;
+class OPimNotifyManager;
+class OTodo : public OPimRecord {
+public:
+ typedef QValueList<OTodo> ValueList;
+ enum RecordFields {
+ Uid = Qtopia::UID_ID,
+ Category = Qtopia::CATEGORY_ID,
+ HasDate,
+ Completed,
+ Description,
+ Summary,
+ Priority,
+ DateDay,
+ DateMonth,
+ DateYear,
+ Progress,
+ CrossReference,
+ State,
+ Recurrence,
+ Alarms,
+ Reminders,
+ Notifiers,
+ Maintainer,
+ StartDate,
+ CompletedDate
+ };
+ public:
+ // priorities from Very low to very high
+ enum TaskPriority { VeryHigh=1, High, Normal, Low, VeryLow };
+
+ /* Constructs a new ToDoEvent
+ @param completed Is the TodoEvent completed
+ @param priority What is the priority of this ToDoEvent
+ @param category Which category does it belong( uid )
+ @param summary A small summary of the todo
+ @param description What is this ToDoEvent about
+ @param hasDate Does this Event got a deadline
+ @param date what is the deadline?
+ @param uid what is the UUID of this Event
+ **/
+ OTodo( bool completed = false, int priority = Normal,
+ const QStringList &category = QStringList(),
+ const QString &summary = QString::null ,
+ const QString &description = QString::null,
+ ushort progress = 0,
+ bool hasDate = false, QDate date = QDate::currentDate(),
+ int uid = 0 /*empty*/ );
+
+ OTodo( bool completed, int priority,
+ const QArray<int>& category,
+ const QString& summary = QString::null,
+ const QString& description = QString::null,
+ ushort progress = 0,
+ bool hasDate = false, QDate date = QDate::currentDate(),
+ int uid = 0 /* empty */ );
+
+ /** Copy c'tor
+ *
+ */
+ OTodo(const OTodo & );
+
+ /**
+ *destructor
+ */
+ ~OTodo();
+
+ /**
+ * Is this event completed?
+ */
+ bool isCompleted() const;
+
+ /**
+ * Does this Event have a deadline
+ */
+ bool hasDueDate() const;
+ bool hasStartDate()const;
+ bool hasCompletedDate()const;
+
+ /**
+ * What is the priority?
+ */
+ int priority()const ;
+
+ /**
+ * progress as ushort 0, 20, 40, 60, 80 or 100%
+ */
+ ushort progress() const;
+
+ /**
+ * The due Date
+ */
+ QDate dueDate()const;
+
+ /**
+ * When did it start?
+ */
+ QDate startDate()const;
+
+ /**
+ * When was it completed?
+ */
+ QDate completedDate()const;
+
+ /**
+ * does it have a state?
+ */
+ bool hasState()const;
+
+ /**
+ * What is the state of this OTodo?
+ */
+ OPimState state()const;
+
+ /**
+ * has recurrence?
+ */
+ bool hasRecurrence()const;
+
+ /**
+ * the recurrance of this
+ */
+ ORecur recurrence()const;
+
+ /**
+ * does this OTodo have a maintainer?
+ */
+ bool hasMaintainer()const;
+
+ /**
+ * the Maintainer of this OTodo
+ */
+ OPimMaintainer maintainer()const;
+
+ /**
+ * The description of the todo
+ */
+ QString description()const;
+
+ /**
+ * A small summary of the todo
+ */
+ QString summary() const;
+
+ /**
+ * @reimplemented
+ * Return this todoevent in a RichText formatted QString
+ */
+ QString toRichText() const;
+
+ bool hasNotifiers()const;
+ /*
+ * FIXME check if the sharing is still fine!! -zecke
+ * ### CHECK If API is fine
+ */
+ /**
+ * return a reference to our notifiers...
+ */
+ OPimNotifyManager &notifiers();
+
+ /**
+ *
+ */
+ const OPimNotifyManager &notifiers()const;
+
+ /**
+ * reimplementations
+ */
+ QString type()const;
+ QString toShortText()const;
+ QString recordField(int id )const;
+
+ /**
+ * toMap puts all data into the map. int relates
+ * to ToDoEvent RecordFields enum
+ */
+ QMap<int, QString> toMap()const;
+
+ /**
+ * Set if this Todo is completed
+ */
+ void setCompleted(bool completed );
+
+ /**
+ * set if this todo got an end data
+ */
+ void setHasDueDate( bool hasDate );
+ // FIXME we do not have these for start, completed
+ // cause we'll use the isNull() of QDate for figuring
+ // out if it's has a date...
+ // decide what to do here? -zecke
+
+ /**
+ * Set the priority of the Todo
+ */
+ void setPriority(int priority );
+
+ /**
+ * Set the progress.
+ */
+ void setProgress( ushort progress );
+
+ /**
+ * set the end date
+ */
+ void setDueDate( const QDate& date );
+
+ /**
+ * set the start date
+ */
+ void setStartDate( const QDate& date );
+
+ /**
+ * set the completed date
+ */
+ void setCompletedDate( const QDate& date );
+
+ void setRecurrence( const ORecur& );
+
+ void setDescription(const QString& );
+ void setSummary(const QString& );
+
+ /**
+ * set the state of a Todo
+ * @param state State what the todo should take
+ */
+ void setState( const OPimState& state);
+
+ /**
+ * set the Maintainer Mode
+ */
+ void setMaintainer( const OPimMaintainer& );
+
+ bool isOverdue();
+
+
+ virtual bool match( const QRegExp &r )const;
+
+ bool operator<(const OTodo &toDoEvent )const;
+ bool operator<=(const OTodo &toDoEvent )const;
+ bool operator!=(const OTodo &toDoEvent )const;
+ bool operator>(const OTodo &toDoEvent )const;
+ bool operator>=(const OTodo &toDoEvent)const;
+ bool operator==(const OTodo &toDoEvent )const;
+ OTodo &operator=(const OTodo &toDoEvent );
+
+ static int rtti();
+
+ private:
+ class OTodoPrivate;
+ struct OTodoData;
+
+ void deref();
+ inline void changeOrModify();
+ void copy( OTodoData* src, OTodoData* dest );
+ OTodoPrivate *d;
+ OTodoData *data;
+
+};
+inline bool OTodo::operator!=(const OTodo &toDoEvent )const {
+ return !(*this == toDoEvent);
+}
+
+
+#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 @@
+#include <qdatetime.h>
+
+#include <qpe/alarmserver.h>
+
+// #include "otodoaccesssql.h"
+#include "otodoaccess.h"
+#include "obackendfactory.h"
+
+OTodoAccess::OTodoAccess( OTodoAccessBackend* end, enum Access )
+ : QObject(), OPimAccessTemplate<OTodo>( end ), m_todoBackEnd( end )
+{
+// if (end == 0l )
+// m_todoBackEnd = new OTodoAccessBackendSQL( QString::null);
+
+ // Zecke: Du musst hier noch für das XML-Backend einen Appnamen übergeben !
+ if (end == 0l )
+ m_todoBackEnd = OBackendFactory<OTodoAccessBackend>::Default ("todo", QString::null);
+
+ setBackEnd( m_todoBackEnd );
+}
+OTodoAccess::~OTodoAccess() {
+// qWarning("~OTodoAccess");
+}
+void OTodoAccess::mergeWith( const QValueList<OTodo>& list ) {
+ QValueList<OTodo>::ConstIterator it;
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ replace( (*it) );
+ }
+}
+OTodoAccess::List OTodoAccess::effectiveToDos( const QDate& start,
+ const QDate& end,
+ bool includeNoDates ) {
+ QArray<int> ints = m_todoBackEnd->effectiveToDos( start, end, includeNoDates );
+
+ List lis( ints, this );
+ return lis;
+}
+OTodoAccess::List OTodoAccess::effectiveToDos( const QDate& start,
+ bool includeNoDates ) {
+ return effectiveToDos( start, QDate::currentDate(),
+ includeNoDates );
+}
+OTodoAccess::List OTodoAccess::overDue() {
+ List lis( m_todoBackEnd->overDue(), this );
+ return lis;
+}
+/* sort order */
+OTodoAccess::List OTodoAccess::sorted( bool ascending, int sort,int filter, int cat ) {
+ QArray<int> ints = m_todoBackEnd->sorted( ascending, sort,
+ filter, cat );
+ OTodoAccess::List list( ints, this );
+ return list;
+}
+void OTodoAccess::removeAllCompleted() {
+ m_todoBackEnd->removeAllCompleted();
+}
+QBitArray OTodoAccess::backendSupport( const QString& ) const{
+ return m_todoBackEnd->supports();
+}
+bool OTodoAccess::backendSupports( int attr, const QString& ar) const{
+ return backendSupport(ar).testBit( attr );
+}
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 @@
+#ifndef OPIE_TODO_ACCESS_H
+#define OPIE_TODO_ACCESS_H
+
+#include <qobject.h>
+#include <qvaluelist.h>
+
+#include "otodo.h"
+#include "otodoaccessbackend.h"
+#include "opimaccesstemplate.h"
+
+
+/**
+ * OTodoAccess
+ * the class to get access to
+ * the todolist
+ */
+class OTodoAccess : public QObject, public OPimAccessTemplate<OTodo> {
+ Q_OBJECT
+public:
+ enum SortOrder { Completed = 0,
+ Priority,
+ Description,
+ Deadline };
+ enum SortFilter{ Category =1,
+ OnlyOverDue= 2,
+ DoNotShowCompleted =4 };
+ /**
+ * if you use 0l
+ * the default resource will be
+ * picked up
+ */
+ OTodoAccess( OTodoAccessBackend* = 0l, enum Access acc = Random );
+ ~OTodoAccess();
+
+
+ /* our functions here */
+ /**
+ * include todos from start to end
+ * includeNoDates whether or not to include
+ * events with no dates
+ */
+ List effectiveToDos( const QDate& start,
+ const QDate& end,
+ bool includeNoDates = true );
+
+ /**
+ * start
+ * end date taken from the currentDate()
+ */
+ List effectiveToDos( const QDate& start,
+ bool includeNoDates = true );
+
+
+ /**
+ * return overdue OTodos
+ */
+ List overDue();
+
+ /**
+ *
+ */
+ List sorted( bool ascending, int sortOrder, int sortFilter, int cat );
+
+ /**
+ * merge a list of OTodos into
+ * the resource
+ */
+ void mergeWith( const QValueList<OTodo>& );
+
+ /**
+ * delete all already completed items
+ */
+ void removeAllCompleted();
+
+ /**
+ * request information about what a backend supports.
+ * Supports in the sense of beeing able to store.
+ * This is related to the enum in OTodo
+ *
+ * @param backend Will be used in the future when we support multiple backend
+ */
+ QBitArray backendSupport( const QString& backend = QString::null )const;
+
+ /**
+ * see above but for a specefic attribute. This method was added for convience
+ * @param attr The attribute to be queried for
+ * @param backend Will be used in the future when we support multiple backends
+ */
+ bool backendSupports( int attr, const QString& backend = QString::null )const;
+signals:
+ /**
+ * if the OTodoAccess was changed
+ */
+ void changed( const OTodoAccess* );
+ void changed( const OTodoAccess*, int uid );
+ void added( const OTodoAccess*, int uid );
+ void removed( const OTodoAccess*, int uid );
+private:
+ int m_cat;
+ OTodoAccessBackend* m_todoBackEnd;
+ class OTodoAccessPrivate;
+ OTodoAccessPrivate* d;
+};
+
+#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 @@
+
+#include "otodoaccessbackend.h"
+
+OTodoAccessBackend::OTodoAccessBackend()
+ : OPimAccessBackend<OTodo>()
+{
+}
+OTodoAccessBackend::~OTodoAccessBackend() {
+
+}
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 @@
+#ifndef OPIE_TODO_ACCESS_BACKEND_H
+#define OPIE_TODO_ACCESS_BACKEND_H
+
+#include <qbitarray.h>
+
+#include "otodo.h"
+#include "opimaccessbackend.h"
+
+class OTodoAccessBackend : public OPimAccessBackend<OTodo> {
+public:
+ OTodoAccessBackend();
+ ~OTodoAccessBackend();
+ virtual QArray<int> effectiveToDos( const QDate& start,
+ const QDate& end,
+ bool includeNoDates ) = 0;
+ virtual QArray<int> overDue() = 0;
+ virtual QArray<int> sorted( bool asc, int sortOrder, int sortFilter,
+ int cat ) = 0;
+ virtual void removeAllCompleted() = 0;
+ virtual QBitArray supports()const = 0;
+
+private:
+ class Private;
+ Private *d;
+
+};
+
+#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 @@
+
+#include <qdatetime.h>
+
+#include <qpe/global.h>
+
+#include <opie2/osqldriver.h>
+#include <opie2/osqlresult.h>
+#include <opie2/osqlmanager.h>
+#include <opie2/osqlquery.h>
+
+#include "otodoaccesssql.h"
+#include "opimstate.h"
+#include "opimnotifymanager.h"
+#include "orecur.h"
+
+using namespace Opie::DB;
+/*
+ * first some query
+ * CREATE query
+ * LOAD query
+ * INSERT
+ * REMOVE
+ * CLEAR
+ */
+namespace {
+ /**
+ * CreateQuery for the Todolist Table
+ */
+ class CreateQuery : public OSQLQuery {
+ public:
+ CreateQuery();
+ ~CreateQuery();
+ QString query()const;
+ };
+
+ /**
+ * LoadQuery
+ * this one queries for all uids
+ */
+ class LoadQuery : public OSQLQuery {
+ public:
+ LoadQuery();
+ ~LoadQuery();
+ QString query()const;
+ };
+
+ /**
+ * inserts/adds a OTodo to the table
+ */
+ class InsertQuery : public OSQLQuery {
+ public:
+ InsertQuery(const OTodo& );
+ ~InsertQuery();
+ QString query()const;
+ private:
+ OTodo m_todo;
+ };
+
+ /**
+ * removes one from the table
+ */
+ class RemoveQuery : public OSQLQuery {
+ public:
+ RemoveQuery(int uid );
+ ~RemoveQuery();
+ QString query()const;
+ private:
+ int m_uid;
+ };
+
+ /**
+ * Clears (delete) a Table
+ */
+ class ClearQuery : public OSQLQuery {
+ public:
+ ClearQuery();
+ ~ClearQuery();
+ QString query()const;
+
+ };
+
+ /**
+ * a find query
+ */
+ class FindQuery : public OSQLQuery {
+ public:
+ FindQuery(int uid);
+ FindQuery(const QArray<int>& );
+ ~FindQuery();
+ QString query()const;
+ private:
+ QString single()const;
+ QString multi()const;
+ QArray<int> m_uids;
+ int m_uid;
+ };
+
+ /**
+ * overdue query
+ */
+ class OverDueQuery : public OSQLQuery {
+ public:
+ OverDueQuery();
+ ~OverDueQuery();
+ QString query()const;
+ };
+ class EffQuery : public OSQLQuery {
+ public:
+ EffQuery( const QDate&, const QDate&, bool inc );
+ ~EffQuery();
+ QString query()const;
+ private:
+ QString with()const;
+ QString out()const;
+ QDate m_start;
+ QDate m_end;
+ bool m_inc :1;
+ };
+
+
+ CreateQuery::CreateQuery() : OSQLQuery() {}
+ CreateQuery::~CreateQuery() {}
+ QString CreateQuery::query()const {
+ QString qu;
+ qu += "create table todolist( uid PRIMARY KEY, categories, completed, ";
+ qu += "description, summary, priority, DueDate, progress , state, ";
+ // This is the recurrance-stuff .. Exceptions are currently not supported (see ORecur.cpp) ! (eilers)
+ qu += "RType, RWeekdays, RPosition, RFreq, RHasEndDate, EndDate, Created, Exceptions, ";
+ qu += "reminders, alarms, maintainer, startdate, completeddate);";
+ qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );";
+ return qu;
+ }
+
+ LoadQuery::LoadQuery() : OSQLQuery() {}
+ LoadQuery::~LoadQuery() {}
+ QString LoadQuery::query()const {
+ QString qu;
+ // We do not need "distinct" here. The primary key is always unique..
+ //qu += "select distinct uid from todolist";
+ qu += "select uid from todolist";
+
+ return qu;
+ }
+
+ InsertQuery::InsertQuery( const OTodo& todo )
+ : OSQLQuery(), m_todo( todo ) {
+ }
+ InsertQuery::~InsertQuery() {
+ }
+ /*
+ * converts from a OTodo to a query
+ * we leave out X-Ref + Alarms
+ */
+ QString InsertQuery::query()const{
+
+ int year, month, day;
+ year = month = day = 0;
+ if (m_todo.hasDueDate() ) {
+ QDate date = m_todo.dueDate();
+ year = date.year();
+ month = date.month();
+ day = date.day();
+ }
+ int sYear = 0, sMonth = 0, sDay = 0;
+ if( m_todo.hasStartDate() ){
+ QDate sDate = m_todo.startDate();
+ sYear = sDate.year();
+ sMonth= sDate.month();
+ sDay = sDate.day();
+ }
+
+ int eYear = 0, eMonth = 0, eDay = 0;
+ if( m_todo.hasCompletedDate() ){
+ QDate eDate = m_todo.completedDate();
+ eYear = eDate.year();
+ eMonth= eDate.month();
+ eDay = eDate.day();
+ }
+ QString qu;
+ QMap<int, QString> recMap = m_todo.recurrence().toMap();
+ qu = "insert into todolist VALUES("
+ + QString::number( m_todo.uid() ) + ","
+ + "'" + m_todo.idsToString( m_todo.categories() ) + "'" + ","
+ + QString::number( m_todo.isCompleted() ) + ","
+ + "'" + m_todo.description() + "'" + ","
+ + "'" + m_todo.summary() + "'" + ","
+ + QString::number(m_todo.priority() ) + ","
+ + "'" + QString::number(year) + "-"
+ + QString::number(month)
+ + "-" + QString::number( day ) + "'" + ","
+ + QString::number( m_todo.progress() ) + ","
+ + QString::number( m_todo.state().state() ) + ","
+ + "'" + recMap[ ORecur::RType ] + "'" + ","
+ + "'" + recMap[ ORecur::RWeekdays ] + "'" + ","
+ + "'" + recMap[ ORecur::RPosition ] + "'" + ","
+ + "'" + recMap[ ORecur::RFreq ] + "'" + ","
+ + "'" + recMap[ ORecur::RHasEndDate ] + "'" + ","
+ + "'" + recMap[ ORecur::EndDate ] + "'" + ","
+ + "'" + recMap[ ORecur::Created ] + "'" + ","
+ + "'" + recMap[ ORecur::Exceptions ] + "'" + ",";
+
+ if ( m_todo.hasNotifiers() ) {
+ OPimNotifyManager manager = m_todo.notifiers();
+ qu += "'" + manager.remindersToString() + "'" + ","
+ + "'" + manager.alarmsToString() + "'" + ",";
+ }
+ else{
+ qu += QString( "''" ) + ","
+ + "''" + ",";
+ }
+
+ qu += QString( "''" ) + QString( "," ) // Maintainers (cur. not supported !)
+ + "'" + QString::number(sYear) + "-"
+ + QString::number(sMonth)
+ + "-" + QString::number(sDay) + "'" + ","
+ + "'" + QString::number(eYear) + "-"
+ + QString::number(eMonth)
+ + "-"+QString::number(eDay) + "'"
+ + ")";
+
+ qWarning("add %s", qu.latin1() );
+ return qu;
+ }
+
+ RemoveQuery::RemoveQuery(int uid )
+ : OSQLQuery(), m_uid( uid ) {}
+ RemoveQuery::~RemoveQuery() {}
+ QString RemoveQuery::query()const {
+ QString qu = "DELETE from todolist where uid = " + QString::number(m_uid);
+ return qu;
+ }
+
+
+ ClearQuery::ClearQuery()
+ : OSQLQuery() {}
+ ClearQuery::~ClearQuery() {}
+ QString ClearQuery::query()const {
+ QString qu = "drop table todolist";
+ return qu;
+ }
+ FindQuery::FindQuery(int uid)
+ : OSQLQuery(), m_uid(uid ) {
+ }
+ FindQuery::FindQuery(const QArray<int>& ints)
+ : OSQLQuery(), m_uids(ints){
+ }
+ FindQuery::~FindQuery() {
+ }
+ QString FindQuery::query()const{
+ if (m_uids.count() == 0 )
+ return single();
+ else
+ return multi();
+ }
+ QString FindQuery::single()const{
+ QString qu = "select * from todolist where uid = " + QString::number(m_uid);
+ return qu;
+ }
+ QString FindQuery::multi()const {
+ QString qu = "select * from todolist where ";
+ for (uint i = 0; i < m_uids.count(); i++ ) {
+ qu += " UID = " + QString::number( m_uids[i] ) + " OR";
+ }
+ qu.remove( qu.length()-2, 2 );
+ return qu;
+ }
+
+ OverDueQuery::OverDueQuery(): OSQLQuery() {}
+ OverDueQuery::~OverDueQuery() {}
+ QString OverDueQuery::query()const {
+ QDate date = QDate::currentDate();
+ QString str;
+ str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() );
+
+ return str;
+ }
+
+
+ EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc )
+ : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {}
+ EffQuery::~EffQuery() {}
+ QString EffQuery::query()const {
+ return m_inc ? with() : out();
+ }
+ QString EffQuery::with()const {
+ QString str;
+ str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ")
+ .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() )
+ .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() );
+ return str;
+ }
+ QString EffQuery::out()const {
+ QString str;
+ str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'")
+ .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() )
+ .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() );
+
+ return str;
+ }
+};
+
+OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file )
+ : OTodoAccessBackend(), m_dict(15), m_driver(NULL), m_dirty(true)
+{
+ QString fi = file;
+ if ( fi.isEmpty() )
+ fi = Global::applicationFileName( "todolist", "todolist.db" );
+ OSQLManager man;
+ m_driver = man.standard();
+ m_driver->setUrl(fi);
+ // fillDict();
+}
+
+OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){
+ if( m_driver )
+ delete m_driver;
+}
+
+bool OTodoAccessBackendSQL::load(){
+ if (!m_driver->open() )
+ return false;
+
+ CreateQuery creat;
+ OSQLResult res = m_driver->query(&creat );
+
+ m_dirty = true;
+ return true;
+}
+bool OTodoAccessBackendSQL::reload(){
+ return load();
+}
+
+bool OTodoAccessBackendSQL::save(){
+ return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
+}
+QArray<int> OTodoAccessBackendSQL::allRecords()const {
+ if (m_dirty )
+ update();
+
+ return m_uids;
+}
+QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){
+ QArray<int> ints(0);
+ return ints;
+}
+OTodo OTodoAccessBackendSQL::find(int uid ) const{
+ FindQuery query( uid );
+ return todo( m_driver->query(&query) );
+
+}
+OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints,
+ uint cur, Frontend::CacheDirection dir ) const{
+ uint CACHE = readAhead();
+ qWarning("searching for %d", uid );
+ QArray<int> search( CACHE );
+ uint size =0;
+ OTodo to;
+
+ // we try to cache CACHE items
+ switch( dir ) {
+ /* forward */
+ case 0: // FIXME: Not a good style to use magic numbers here (eilers)
+ for (uint i = cur; i < ints.count() && size < CACHE; i++ ) {
+ qWarning("size %d %d", size, ints[i] );
+ search[size] = ints[i];
+ size++;
+ }
+ break;
+ /* reverse */
+ case 1: // FIXME: Not a good style to use magic numbers here (eilers)
+ for (uint i = cur; i != 0 && size < CACHE; i-- ) {
+ search[size] = ints[i];
+ size++;
+ }
+ break;
+ }
+ search.resize( size );
+ FindQuery query( search );
+ OSQLResult res = m_driver->query( &query );
+ if ( res.state() != OSQLResult::Success )
+ return to;
+
+ return todo( res );
+}
+void OTodoAccessBackendSQL::clear() {
+ ClearQuery cle;
+ OSQLResult res = m_driver->query( &cle );
+ CreateQuery qu;
+ res = m_driver->query(&qu);
+}
+bool OTodoAccessBackendSQL::add( const OTodo& t) {
+ InsertQuery ins( t );
+ OSQLResult res = m_driver->query( &ins );
+
+ if ( res.state() == OSQLResult::Failure )
+ return false;
+ int c = m_uids.count();
+ m_uids.resize( c+1 );
+ m_uids[c] = t.uid();
+
+ return true;
+}
+bool OTodoAccessBackendSQL::remove( int uid ) {
+ RemoveQuery rem( uid );
+ OSQLResult res = m_driver->query(&rem );
+
+ if ( res.state() == OSQLResult::Failure )
+ return false;
+
+ m_dirty = true;
+ return true;
+}
+/*
+ * FIXME better set query
+ * but we need the cache for that
+ * now we remove
+ */
+bool OTodoAccessBackendSQL::replace( const OTodo& t) {
+ remove( t.uid() );
+ bool b= add(t);
+ m_dirty = false; // we changed some stuff but the UID stayed the same
+ return b;
+}
+QArray<int> OTodoAccessBackendSQL::overDue() {
+ OverDueQuery qu;
+ return uids( m_driver->query(&qu ) );
+}
+QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s,
+ const QDate& t,
+ bool u) {
+ EffQuery ef(s, t, u );
+ return uids (m_driver->query(&ef) );
+}
+/*
+ *
+ */
+QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder,
+ int sortFilter, int cat ) {
+ qWarning("sorted %d, %d", asc, sortOrder );
+ QString query;
+ query = "select uid from todolist WHERE ";
+
+ /*
+ * Sort Filter stuff
+ * not that straight forward
+ * FIXME: Replace magic numbers
+ *
+ */
+ /* Category */
+ if ( sortFilter & 1 ) {
+ QString str;
+ if (cat != 0 ) str = QString::number( cat );
+ query += " categories like '%" +str+"%' AND";
+ }
+ /* Show only overdue */
+ if ( sortFilter & 2 ) {
+ QDate date = QDate::currentDate();
+ QString due;
+ QString base;
+ base = QString("DueDate <= '%1-%2-%3' AND completed = 0").arg( date.year() ).arg( date.month() ).arg( date.day() );
+ query += " " + base + " AND";
+ }
+ /* not show completed */
+ if ( sortFilter & 4 ) {
+ query += " completed = 0 AND";
+ }else{
+ query += " ( completed = 1 OR completed = 0) AND";
+ }
+ /* srtip the end */
+ query = query.remove( query.length()-3, 3 );
+
+
+ /*
+ * sort order stuff
+ * quite straight forward
+ */
+ query += "ORDER BY ";
+ switch( sortOrder ) {
+ /* completed */
+ case 0:
+ query += "completed";
+ break;
+ case 1:
+ query += "priority";
+ break;
+ case 2:
+ query += "summary";
+ break;
+ case 3:
+ query += "DueDate";
+ break;
+ }
+
+ if ( !asc ) {
+ qWarning("not ascending!");
+ query += " DESC";
+ }
+
+ qWarning( query );
+ OSQLRawQuery raw(query );
+ return uids( m_driver->query(&raw) );
+}
+bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{
+ if ( str == "0-0-0" )
+ return false;
+ else{
+ int day, year, month;
+ QStringList list = QStringList::split("-", str );
+ year = list[0].toInt();
+ month = list[1].toInt();
+ day = list[2].toInt();
+ da.setYMD( year, month, day );
+ return true;
+ }
+}
+OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{
+ if ( res.state() == OSQLResult::Failure ) {
+ OTodo to;
+ return to;
+ }
+
+ OSQLResultItem::ValueList list = res.results();
+ OSQLResultItem::ValueList::Iterator it = list.begin();
+ qWarning("todo1");
+ OTodo to = todo( (*it) );
+ cache( to );
+ ++it;
+
+ for ( ; it != list.end(); ++it ) {
+ qWarning("caching");
+ cache( todo( (*it) ) );
+ }
+ return to;
+}
+OTodo OTodoAccessBackendSQL::todo( OSQLResultItem& item )const {
+ qWarning("todo");
+ bool hasDueDate = false; QDate dueDate = QDate::currentDate();
+ hasDueDate = date( dueDate, item.data("DueDate") );
+ QStringList cats = QStringList::split(";", item.data("categories") );
+
+ qWarning("Item is completed: %d", item.data("completed").toInt() );
+
+ OTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(),
+ cats, item.data("summary"), item.data("description"),
+ item.data("progress").toUShort(), hasDueDate, dueDate,
+ item.data("uid").toInt() );
+
+ bool isOk;
+ int prioInt = QString( item.data("priority") ).toInt( &isOk );
+ if ( isOk )
+ to.setPriority( prioInt );
+
+ bool hasStartDate = false; QDate startDate = QDate::currentDate();
+ hasStartDate = date( startDate, item.data("startdate") );
+ bool hasCompletedDate = false; QDate completedDate = QDate::currentDate();
+ hasCompletedDate = date( completedDate, item.data("completeddate") );
+
+ if ( hasStartDate )
+ to.setStartDate( startDate );
+ if ( hasCompletedDate )
+ to.setCompletedDate( completedDate );
+
+ OPimNotifyManager& manager = to.notifiers();
+ manager.alarmsFromString( item.data("alarms") );
+ manager.remindersFromString( item.data("reminders") );
+
+ OPimState pimState;
+ pimState.setState( QString( item.data("state") ).toInt() );
+ to.setState( pimState );
+
+ QMap<int, QString> recMap;
+ recMap.insert( ORecur::RType , item.data("RType") );
+ recMap.insert( ORecur::RWeekdays , item.data("RWeekdays") );
+ recMap.insert( ORecur::RPosition , item.data("RPosition") );
+ recMap.insert( ORecur::RFreq , item.data("RFreq") );
+ recMap.insert( ORecur::RHasEndDate, item.data("RHasEndDate") );
+ recMap.insert( ORecur::EndDate , item.data("EndDate") );
+ recMap.insert( ORecur::Created , item.data("Created") );
+ recMap.insert( ORecur::Exceptions , item.data("Exceptions") );
+
+ ORecur recur;
+ recur.fromMap( recMap );
+ to.setRecurrence( recur );
+
+ return to;
+}
+OTodo OTodoAccessBackendSQL::todo( int uid )const {
+ FindQuery find( uid );
+ return todo( m_driver->query(&find) );
+}
+/*
+ * update the dict
+ */
+void OTodoAccessBackendSQL::fillDict() {
+ /* initialize dict */
+ /*
+ * UPDATE dict if you change anything!!!
+ * FIXME: Isn't this dict obsolete ? (eilers)
+ */
+ m_dict.setAutoDelete( TRUE );
+ m_dict.insert("Categories" , new int(OTodo::Category) );
+ m_dict.insert("Uid" , new int(OTodo::Uid) );
+ m_dict.insert("HasDate" , new int(OTodo::HasDate) );
+ m_dict.insert("Completed" , new int(OTodo::Completed) );
+ m_dict.insert("Description" , new int(OTodo::Description) );
+ m_dict.insert("Summary" , new int(OTodo::Summary) );
+ m_dict.insert("Priority" , new int(OTodo::Priority) );
+ m_dict.insert("DateDay" , new int(OTodo::DateDay) );
+ m_dict.insert("DateMonth" , new int(OTodo::DateMonth) );
+ m_dict.insert("DateYear" , new int(OTodo::DateYear) );
+ m_dict.insert("Progress" , new int(OTodo::Progress) );
+ m_dict.insert("Completed", new int(OTodo::Completed) ); // Why twice ? (eilers)
+ m_dict.insert("CrossReference", new int(OTodo::CrossReference) );
+// m_dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); // old stuff (eilers)
+// m_dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); // old stuff (eilers)
+}
+/*
+ * need to be const so let's fool the
+ * compiler :(
+ */
+void OTodoAccessBackendSQL::update()const {
+ ((OTodoAccessBackendSQL*)this)->m_dirty = false;
+ LoadQuery lo;
+ OSQLResult res = m_driver->query(&lo);
+ if ( res.state() != OSQLResult::Success )
+ return;
+
+ ((OTodoAccessBackendSQL*)this)->m_uids = uids( res );
+}
+QArray<int> OTodoAccessBackendSQL::uids( const OSQLResult& res) const{
+
+ OSQLResultItem::ValueList list = res.results();
+ OSQLResultItem::ValueList::Iterator it;
+ QArray<int> ints(list.count() );
+ qWarning(" count = %d", list.count() );
+
+ int i = 0;
+ for (it = list.begin(); it != list.end(); ++it ) {
+ ints[i] = (*it).data("uid").toInt();
+ i++;
+ }
+ return ints;
+}
+
+QArray<int> OTodoAccessBackendSQL::matchRegexp( const QRegExp &r ) const
+{
+
+#warning OTodoAccessBackendSQL::matchRegexp() not implemented !!
+
+#if 0
+
+ Copied from xml-backend by not adapted to sql (eilers)
+
+ QArray<int> m_currentQuery( m_events.count() );
+ uint arraycounter = 0;
+
+
+
+ QMap<int, OTodo>::ConstIterator it;
+ for (it = m_events.begin(); it != m_events.end(); ++it ) {
+ if ( it.data().match( r ) )
+ m_currentQuery[arraycounter++] = it.data().uid();
+
+ }
+ // Shrink to fit..
+ m_currentQuery.resize(arraycounter);
+
+ return m_currentQuery;
+#endif
+ QArray<int> empty;
+ return empty;
+}
+QBitArray OTodoAccessBackendSQL::supports()const {
+
+ return sup();
+}
+
+QBitArray OTodoAccessBackendSQL::sup() const{
+
+ QBitArray ar( OTodo::CompletedDate + 1 );
+ ar.fill( true );
+ ar[OTodo::CrossReference] = false;
+ ar[OTodo::State ] = false;
+ ar[OTodo::Reminders] = false;
+ ar[OTodo::Notifiers] = false;
+ ar[OTodo::Maintainer] = false;
+
+ return ar;
+}
+
+void OTodoAccessBackendSQL::removeAllCompleted(){
+#warning OTodoAccessBackendSQL::removeAllCompleted() not implemented !!
+
+}
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 @@
+#ifndef OPIE_PIM_ACCESS_SQL_H
+#define OPIE_PIM_ACCESS_SQL_H
+
+#include <qasciidict.h>
+
+#include "otodoaccessbackend.h"
+
+namespace Opie{
+namespace DB {
+class OSQLDriver;
+class OSQLResult;
+class OSQLResultItem;
+}
+}
+
+class OTodoAccessBackendSQL : public OTodoAccessBackend {
+public:
+ OTodoAccessBackendSQL( const QString& file );
+ ~OTodoAccessBackendSQL();
+
+ bool load();
+ bool reload();
+ bool save();
+ QArray<int> allRecords()const;
+
+ QArray<int> queryByExample( const OTodo& t, int settings, const QDateTime& d = QDateTime() );
+ OTodo find(int uid)const;
+ OTodo find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
+ void clear();
+ bool add( const OTodo& t );
+ bool remove( int uid );
+ bool replace( const OTodo& t );
+
+ QArray<int> overDue();
+ QArray<int> effectiveToDos( const QDate& start,
+ const QDate& end, bool includeNoDates );
+ QArray<int> sorted(bool asc, int sortOrder, int sortFilter, int cat );
+
+ QBitArray supports()const;
+ QArray<int> matchRegexp( const QRegExp &r ) const;
+ void removeAllCompleted();
+
+
+private:
+ void update()const;
+ void fillDict();
+ inline bool date( QDate& date, const QString& )const;
+ inline OTodo todo( const Opie::DB::OSQLResult& )const;
+ inline OTodo todo( Opie::DB::OSQLResultItem& )const;
+ inline QArray<int> uids( const Opie::DB::OSQLResult& )const;
+ OTodo todo( int uid )const;
+ QBitArray sup() const;
+
+ QAsciiDict<int> m_dict;
+ Opie::DB::OSQLDriver* m_driver;
+ QArray<int> m_uids;
+ bool m_dirty : 1;
+};
+
+
+#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 @@
+#include <qfile.h>
+
+#include <qtopia/private/vobject_p.h>
+#include <qtopia/timeconversion.h>
+#include <qtopia/private/qfiledirect_p.h>
+
+#include "otodoaccessvcal.h"
+
+namespace {
+ static OTodo eventByVObj( VObject *obj ){
+ OTodo event;
+ VObject *ob;
+ QCString name;
+ // no uid, attendees, ... and no fun
+ // description
+ if( ( ob = isAPropertyOf( obj, VCDescriptionProp )) != 0 ){
+ name = vObjectStringZValue( ob );
+#if 0
+ event.setDescription( name );
+#else
+ event.setSummary( name );
+#endif
+ }
+ // summary
+ if ( ( ob = isAPropertyOf( obj, VCSummaryProp ) ) != 0 ) {
+ name = vObjectStringZValue( ob );
+#if 0
+ event.setSummary( name );
+#else
+ event.setDescription( name );
+#endif
+ }
+ // completed
+ if( ( ob = isAPropertyOf( obj, VCStatusProp )) != 0 ){
+ name = vObjectStringZValue( ob );
+ if( name == "COMPLETED" ){
+ event.setCompleted( true );
+ }else{
+ event.setCompleted( false );
+ }
+ }else
+ event.setCompleted( false );
+ // priority
+ if ((ob = isAPropertyOf(obj, VCPriorityProp))) {
+ name = vObjectStringZValue( ob );
+ bool ok;
+ event.setPriority(name.toInt(&ok) );
+ }
+ //due date
+ if((ob = isAPropertyOf(obj, VCDueProp)) ){
+ event.setHasDueDate( true );
+ name = vObjectStringZValue( ob );
+ event.setDueDate( TimeConversion::fromISO8601( name).date() );
+ }
+ // categories
+ if((ob = isAPropertyOf( obj, VCCategoriesProp )) != 0 ){
+ name = vObjectStringZValue( ob );
+ qWarning("Categories:%s", name.data() );
+ }
+
+ event.setUid( 1 );
+ return event;
+ };
+ static VObject *vobjByEvent( const OTodo &event ) {
+ VObject *task = newVObject( VCTodoProp );
+ if( task == 0 )
+ return 0l;
+
+ if( event.hasDueDate() ) {
+ QTime time(0, 0, 0);
+ QDateTime date(event.dueDate(), time );
+ addPropValue( task, VCDueProp,
+ TimeConversion::toISO8601( date ) );
+ }
+
+ if( event.isCompleted() )
+ addPropValue( task, VCStatusProp, "COMPLETED");
+
+ QString string = QString::number(event.priority() );
+ addPropValue( task, VCPriorityProp, string.local8Bit() );
+
+ addPropValue( task, VCCategoriesProp,
+ event.idsToString( event.categories() ).local8Bit() );
+
+#if 0
+
+ // There seems a misrepresentation between summary in otodoevent
+ // and summary in vcard.
+ // The same with description..
+ // Description is summary and vice versa.. Argh.. (eilers)
+
+
+ addPropValue( task, VCDescriptionProp,
+ event.description().local8Bit() );
+
+ addPropValue( task, VCSummaryProp,
+ event.summary().local8Bit() );
+
+#else
+ addPropValue( task, VCDescriptionProp,
+ event.summary().local8Bit() );
+
+ addPropValue( task, VCSummaryProp,
+ event.description().local8Bit() );
+#endif
+ return task;
+};
+}
+
+OTodoAccessVCal::OTodoAccessVCal( const QString& path )
+ : m_dirty(false), m_file( path )
+{
+}
+OTodoAccessVCal::~OTodoAccessVCal() {
+}
+bool OTodoAccessVCal::load() {
+ m_map.clear();
+ m_dirty = false;
+
+ VObject* vcal = 0l;
+ vcal = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
+ if (!vcal )
+ return false;
+
+ // Iterate over the list
+ VObjectIterator it;
+ VObject* vobj;
+
+ initPropIterator(&it, vcal);
+
+ while( moreIteration( &it ) ) {
+ vobj = ::nextVObject( &it );
+ QCString name = ::vObjectName( vobj );
+ if( name == VCTodoProp ){
+ OTodo to = eventByVObj( vobj );
+ m_map.insert( to.uid(), to );
+ }
+ }
+
+ // Should I do a delete vcal?
+
+ return true;
+}
+bool OTodoAccessVCal::reload() {
+ return load();
+}
+bool OTodoAccessVCal::save() {
+ if (!m_dirty )
+ return true;
+
+ QFileDirect file( m_file );
+ if (!file.open(IO_WriteOnly ) )
+ return false;
+
+ VObject *obj;
+ obj = newVObject( VCCalProp );
+ addPropValue( obj, VCVersionProp, "1.0" );
+ VObject *vo;
+ for(QMap<int, OTodo>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
+ vo = vobjByEvent( it.data() );
+ addVObjectProp(obj, vo );
+ }
+ writeVObject( file.directHandle(), obj );
+ cleanVObject( obj );
+ cleanStrTbl();
+
+ m_dirty = false;
+ return true;
+}
+void OTodoAccessVCal::clear() {
+ m_map.clear();
+ m_dirty = true;
+}
+bool OTodoAccessVCal::add( const OTodo& to ) {
+ m_map.insert( to.uid(), to );
+ m_dirty = true;
+ return true;
+}
+bool OTodoAccessVCal::remove( int uid ) {
+ m_map.remove( uid );
+ m_dirty = true;
+ return true;
+}
+void OTodoAccessVCal::removeAllCompleted() {
+ for ( QMap<int, OTodo>::Iterator it = m_map.begin(); it != m_map.end(); ++it ) {
+ if ( (*it).isCompleted() )
+ m_map.remove( it );
+ }
+}
+bool OTodoAccessVCal::replace( const OTodo& to ) {
+ m_map.replace( to.uid(), to );
+ m_dirty = true;
+ return true;
+}
+OTodo OTodoAccessVCal::find(int uid )const {
+ return m_map[uid];
+}
+QArray<int> OTodoAccessVCal::sorted( bool, int, int, int ) {
+ QArray<int> ar(0);
+ return ar;
+}
+QArray<int> OTodoAccessVCal::allRecords()const {
+ QArray<int> ar( m_map.count() );
+ QMap<int, OTodo>::ConstIterator it;
+ int i = 0;
+ for ( it = m_map.begin(); it != m_map.end(); ++it ) {
+ ar[i] = it.key();
+ i++;
+ }
+ return ar;
+}
+QArray<int> OTodoAccessVCal::matchRegexp(const QRegExp& /* r */)const {
+ QArray<int> ar(0);
+ return ar;
+}
+QArray<int> OTodoAccessVCal::queryByExample( const OTodo&, int, const QDateTime& ) {
+ QArray<int> ar(0);
+ return ar;
+}
+QArray<int> OTodoAccessVCal::effectiveToDos( const QDate& ,
+ const QDate& ,
+ bool ) {
+ QArray<int> ar(0);
+ return ar;
+}
+QArray<int> OTodoAccessVCal::overDue() {
+ QArray<int> ar(0);
+ return ar;
+}
+QBitArray OTodoAccessVCal::supports()const {
+ static QBitArray ar = sup();
+
+ return ar;
+}
+QBitArray OTodoAccessVCal::sup() {
+ QBitArray ar ( OTodo::CompletedDate +1 );
+ ar.fill( true );
+
+ ar[OTodo::CrossReference] = false;
+ ar[OTodo::State ] = false;
+ ar[OTodo::Reminders] = false;
+ ar[OTodo::Notifiers] = false;
+ ar[OTodo::Maintainer] = false;
+ ar[OTodo::Progress] = false;
+ ar[OTodo::Alarms ] = false;
+ ar[OTodo::Recurrence] = false;
+
+ return ar;
+}
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 @@
+#ifndef OPIE_OTODO_ACCESS_VCAL_H
+#define OPIE_OTODO_ACCESS_VCAL_H
+
+#include "otodoaccessbackend.h"
+
+class OTodoAccessVCal : public OTodoAccessBackend {
+public:
+ OTodoAccessVCal(const QString& );
+ ~OTodoAccessVCal();
+
+ bool load();
+ bool reload();
+ bool save();
+
+ QArray<int> allRecords()const;
+ QArray<int> matchRegexp(const QRegExp &r) const;
+ QArray<int> queryByExample( const OTodo& t, int sort, const QDateTime& d = QDateTime() );
+ QArray<int> effectiveToDos( const QDate& start,
+ const QDate& end,
+ bool includeNoDates );
+ QArray<int> overDue();
+ QArray<int> sorted( bool asc, int sortOrder, int sortFilter,
+ int cat );
+ OTodo find(int uid)const;
+ void clear();
+ bool add( const OTodo& );
+ bool remove( int uid );
+ bool replace( const OTodo& );
+
+ void removeAllCompleted();
+ virtual QBitArray supports()const;
+
+private:
+ static QBitArray sup();
+ bool m_dirty : 1;
+ QString m_file;
+ QMap<int, OTodo> m_map;
+};
+
+#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 @@
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <unistd.h>
+
+
+#include <qfile.h>
+#include <qvector.h>
+
+#include <qpe/global.h>
+#include <qpe/stringutil.h>
+#include <qpe/timeconversion.h>
+
+#include "oconversion.h"
+#include "opimstate.h"
+#include "otimezone.h"
+#include "opimnotifymanager.h"
+#include "orecur.h"
+#include "otodoaccessxml.h"
+
+namespace {
+ time_t rp_end;
+ ORecur* rec;
+ ORecur *recur() {
+ if (!rec ) rec = new ORecur;
+ return rec;
+ }
+ int snd;
+ enum MoreAttributes {
+ FRType = OTodo::CompletedDate + 2,
+ FRWeekdays,
+ FRPosition,
+ FRFreq,
+ FRHasEndDate,
+ FREndDate,
+ FRStart,
+ FREnd
+ };
+ // FROM TT again
+char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
+{
+ char needleChar;
+ char haystackChar;
+ if (!needle || !haystack || !hLen || !nLen)
+ return 0;
+
+ const char* hsearch = haystack;
+
+ if ((needleChar = *needle++) != 0) {
+ nLen--; //(to make up for needle++)
+ do {
+ do {
+ if ((haystackChar = *hsearch++) == 0)
+ return (0);
+ if (hsearch >= haystack + hLen)
+ return (0);
+ } while (haystackChar != needleChar);
+ } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
+ hsearch--;
+ }
+ return ((char *)hsearch);
+}
+}
+
+
+OTodoAccessXML::OTodoAccessXML( const QString& appName,
+ const QString& fileName )
+ : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
+{
+ if (!fileName.isEmpty() )
+ m_file = fileName;
+ else
+ m_file = Global::applicationFileName( "todolist", "todolist.xml" );
+}
+OTodoAccessXML::~OTodoAccessXML() {
+
+}
+bool OTodoAccessXML::load() {
+ rec = 0;
+ m_opened = true;
+ m_changed = false;
+ /* initialize dict */
+ /*
+ * UPDATE dict if you change anything!!!
+ */
+ QAsciiDict<int> dict(26);
+ dict.setAutoDelete( TRUE );
+ dict.insert("Categories" , new int(OTodo::Category) );
+ dict.insert("Uid" , new int(OTodo::Uid) );
+ dict.insert("HasDate" , new int(OTodo::HasDate) );
+ dict.insert("Completed" , new int(OTodo::Completed) );
+ dict.insert("Description" , new int(OTodo::Description) );
+ dict.insert("Summary" , new int(OTodo::Summary) );
+ dict.insert("Priority" , new int(OTodo::Priority) );
+ dict.insert("DateDay" , new int(OTodo::DateDay) );
+ dict.insert("DateMonth" , new int(OTodo::DateMonth) );
+ dict.insert("DateYear" , new int(OTodo::DateYear) );
+ dict.insert("Progress" , new int(OTodo::Progress) );
+ dict.insert("CompletedDate", new int(OTodo::CompletedDate) );
+ dict.insert("StartDate", new int(OTodo::StartDate) );
+ dict.insert("CrossReference", new int(OTodo::CrossReference) );
+ dict.insert("State", new int(OTodo::State) );
+ dict.insert("Alarms", new int(OTodo::Alarms) );
+ dict.insert("Reminders", new int(OTodo::Reminders) );
+ dict.insert("Notifiers", new int(OTodo::Notifiers) );
+ dict.insert("Maintainer", new int(OTodo::Maintainer) );
+ dict.insert("rtype", new int(FRType) );
+ dict.insert("rweekdays", new int(FRWeekdays) );
+ dict.insert("rposition", new int(FRPosition) );
+ dict.insert("rfreq", new int(FRFreq) );
+ dict.insert("start", new int(FRStart) );
+ dict.insert("rhasenddate", new int(FRHasEndDate) );
+ dict.insert("enddt", new int(FREndDate) );
+
+ // here the custom XML parser from TT it's GPL
+ // but we want to push OpiePIM... to TT.....
+ // mmap part from zecke :)
+ int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY );
+ struct stat attribut;
+ if ( fd < 0 ) return false;
+
+ if ( fstat(fd, &attribut ) == -1 ) {
+ ::close( fd );
+ return false;
+ }
+ void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 );
+ if ( map_addr == ( (caddr_t)-1) ) {
+ ::close(fd );
+ return false;
+ }
+ /* advise the kernel who we want to read it */
+ ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL );
+ /* we do not the file any more */
+ ::close( fd );
+
+ char* dt = (char*)map_addr;
+ int len = attribut.st_size;
+ int i = 0;
+ char *point;
+ const char* collectionString = "<Task ";
+ int strLen = strlen(collectionString);
+ while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) {
+ i = point -dt;
+ i+= strLen;
+ qWarning("Found a start at %d %d", i, (point-dt) );
+
+ OTodo ev;
+ m_year = m_month = m_day = 0;
+
+ while ( TRUE ) {
+ while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
+ ++i;
+ if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
+ break;
+
+ // we have another attribute, read it.
+ int j = i;
+ while ( j < len && dt[j] != '=' )
+ ++j;
+ QCString attr( dt+i, j-i+1);
+
+ i = ++j; // skip =
+
+ // find the start of quotes
+ while ( i < len && dt[i] != '"' )
+ ++i;
+ j = ++i;
+
+ bool haveUtf = FALSE;
+ bool haveEnt = FALSE;
+ while ( j < len && dt[j] != '"' ) {
+ if ( ((unsigned char)dt[j]) > 0x7f )
+ haveUtf = TRUE;
+ if ( dt[j] == '&' )
+ haveEnt = TRUE;
+ ++j;
+ }
+ if ( i == j ) {
+ // empty value
+ i = j + 1;
+ continue;
+ }
+
+ QCString value( dt+i, j-i+1 );
+ i = j + 1;
+
+ QString str = (haveUtf ? QString::fromUtf8( value )
+ : QString::fromLatin1( value ) );
+ if ( haveEnt )
+ str = Qtopia::plainString( str );
+
+ /*
+ * add key + value
+ */
+ todo( &dict, ev, attr, str );
+
+ }
+ /*
+ * now add it
+ */
+ qWarning("End at %d", i );
+ if (m_events.contains( ev.uid() ) || ev.uid() == 0) {
+ ev.setUid( 1 );
+ m_changed = true;
+ }
+ if ( ev.hasDueDate() ) {
+ ev.setDueDate( QDate(m_year, m_month, m_day) );
+ }
+ if ( rec && rec->doesRecur() ) {
+ OTimeZone utc = OTimeZone::utc();
+ ORecur recu( *rec ); // call copy c'tor
+ recu.setEndDate( utc.fromUTCDateTime( rp_end ).date() );
+ recu.setStart( ev.dueDate() );
+ ev.setRecurrence( recu );
+ }
+ m_events.insert(ev.uid(), ev );
+ m_year = m_month = m_day = -1;
+ delete rec;
+ rec = 0;
+ }
+
+ munmap(map_addr, attribut.st_size );
+
+ qWarning("counts %d records loaded!", m_events.count() );
+ return true;
+}
+bool OTodoAccessXML::reload() {
+ m_events.clear();
+ return load();
+}
+bool OTodoAccessXML::save() {
+// qWarning("saving");
+ if (!m_opened || !m_changed ) {
+// qWarning("not saving");
+ return true;
+ }
+ QString strNewFile = m_file + ".new";
+ QFile f( strNewFile );
+ if (!f.open( IO_WriteOnly|IO_Raw ) )
+ return false;
+
+ int written;
+ QString out;
+ out = "<!DOCTYPE Tasks>\n<Tasks>\n";
+
+ // for all todos
+ QMap<int, OTodo>::Iterator it;
+ for (it = m_events.begin(); it != m_events.end(); ++it ) {
+ out+= "<Task " + toString( (*it) ) + " />\n";
+ QCString cstr = out.utf8();
+ written = f.writeBlock( cstr.data(), cstr.length() );
+
+ /* less written then we wanted */
+ if ( written != (int)cstr.length() ) {
+ f.close();
+ QFile::remove( strNewFile );
+ return false;
+ }
+ out = QString::null;
+ }
+
+ out += "</Tasks>";
+ QCString cstr = out.utf8();
+ written = f.writeBlock( cstr.data(), cstr.length() );
+
+ if ( written != (int)cstr.length() ) {
+ f.close();
+ QFile::remove( strNewFile );
+ return false;
+ }
+ /* flush before renaming */
+ f.close();
+
+ if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
+// qWarning("error renaming");
+ QFile::remove( strNewFile );
+ }
+
+ m_changed = false;
+ return true;
+}
+QArray<int> OTodoAccessXML::allRecords()const {
+ QArray<int> ids( m_events.count() );
+ QMap<int, OTodo>::ConstIterator it;
+ int i = 0;
+
+ for ( it = m_events.begin(); it != m_events.end(); ++it ) {
+ ids[i] = it.key();
+ i++;
+ }
+ return ids;
+}
+QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int, const QDateTime& ) {
+ QArray<int> ids(0);
+ return ids;
+}
+OTodo OTodoAccessXML::find( int uid )const {
+ OTodo todo;
+ todo.setUid( 0 ); // isEmpty()
+ QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
+ if ( it != m_events.end() )
+ todo = it.data();
+
+ return todo;
+}
+void OTodoAccessXML::clear() {
+ if (m_opened )
+ m_changed = true;
+
+ m_events.clear();
+}
+bool OTodoAccessXML::add( const OTodo& todo ) {
+// qWarning("add");
+ m_changed = true;
+ m_events.insert( todo.uid(), todo );
+
+ return true;
+}
+bool OTodoAccessXML::remove( int uid ) {
+ m_changed = true;
+ m_events.remove( uid );
+
+ return true;
+}
+bool OTodoAccessXML::replace( const OTodo& todo) {
+ m_changed = true;
+ m_events.replace( todo.uid(), todo );
+
+ return true;
+}
+QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
+ const QDate& end,
+ bool includeNoDates ) {
+ QArray<int> ids( m_events.count() );
+ QMap<int, OTodo>::Iterator it;
+
+ int i = 0;
+ for ( it = m_events.begin(); it != m_events.end(); ++it ) {
+ if ( !it.data().hasDueDate() ) {
+ if ( includeNoDates ) {
+ ids[i] = it.key();
+ i++;
+ }
+ }else if ( it.data().dueDate() >= start &&
+ it.data().dueDate() <= end ) {
+ ids[i] = it.key();
+ i++;
+ }
+ }
+ ids.resize( i );
+ return ids;
+}
+QArray<int> OTodoAccessXML::overDue() {
+ QArray<int> ids( m_events.count() );
+ int i = 0;
+
+ QMap<int, OTodo>::Iterator it;
+ for ( it = m_events.begin(); it != m_events.end(); ++it ) {
+ if ( it.data().isOverdue() ) {
+ ids[i] = it.key();
+ i++;
+ }
+ }
+ ids.resize( i );
+ return ids;
+}
+
+
+/* private */
+void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
+ const QCString& attr, const QString& val) {
+// qWarning("parse to do from XMLElement" );
+
+ int *find=0;
+
+ find = (*dict)[ attr.data() ];
+ if (!find ) {
+// qWarning("Unknown option" + it.key() );
+ ev.setCustomField( attr, val );
+ return;
+ }
+
+ switch( *find ) {
+ case OTodo::Uid:
+ ev.setUid( val.toInt() );
+ break;
+ case OTodo::Category:
+ ev.setCategories( ev.idsFromString( val ) );
+ break;
+ case OTodo::HasDate:
+ ev.setHasDueDate( val.toInt() );
+ break;
+ case OTodo::Completed:
+ ev.setCompleted( val.toInt() );
+ break;
+ case OTodo::Description:
+ ev.setDescription( val );
+ break;
+ case OTodo::Summary:
+ ev.setSummary( val );
+ break;
+ case OTodo::Priority:
+ ev.setPriority( val.toInt() );
+ break;
+ case OTodo::DateDay:
+ m_day = val.toInt();
+ break;
+ case OTodo::DateMonth:
+ m_month = val.toInt();
+ break;
+ case OTodo::DateYear:
+ m_year = val.toInt();
+ break;
+ case OTodo::Progress:
+ ev.setProgress( val.toInt() );
+ break;
+ case OTodo::CompletedDate:
+ ev.setCompletedDate( OConversion::dateFromString( val ) );
+ break;
+ case OTodo::StartDate:
+ ev.setStartDate( OConversion::dateFromString( val ) );
+ break;
+ case OTodo::State:
+ ev.setState( val.toInt() );
+ break;
+ case OTodo::Alarms:{
+ OPimNotifyManager &manager = ev.notifiers();
+ QStringList als = QStringList::split(";", val );
+ for (QStringList::Iterator it = als.begin(); it != als.end(); ++it ) {
+ QStringList alarm = QStringList::split(":", (*it), TRUE ); // allow empty
+ qWarning("alarm: %s", alarm.join("___").latin1() );
+ qWarning("alarm[0]: %s %s", alarm[0].latin1(), OConversion::dateTimeFromString( alarm[0] ).toString().latin1() );
+ OPimAlarm al( alarm[2].toInt(), OConversion::dateTimeFromString( alarm[0] ), alarm[1].toInt() );
+ manager.add( al );
+ }
+ }
+ break;
+ case OTodo::Reminders:{
+ OPimNotifyManager &manager = ev.notifiers();
+ QStringList rems = QStringList::split(";", val );
+ for (QStringList::Iterator it = rems.begin(); it != rems.end(); ++it ) {
+ OPimReminder rem( (*it).toInt() );
+ manager.add( rem );
+ }
+ }
+ break;
+ case OTodo::CrossReference:
+ {
+ /*
+ * A cross refernce looks like
+ * appname,id;appname,id
+ * we need to split it up
+ */
+ QStringList refs = QStringList::split(';', val );
+ QStringList::Iterator strIt;
+ for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
+ int pos = (*strIt).find(',');
+ if ( pos > -1 )
+ ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() );
+
+ }
+ break;
+ }
+ /* Recurrence stuff below + post processing later */
+ case FRType:
+ if ( val == "Daily" )
+ recur()->setType( ORecur::Daily );
+ else if ( val == "Weekly" )
+ recur()->setType( ORecur::Weekly);
+ else if ( val == "MonthlyDay" )
+ recur()->setType( ORecur::MonthlyDay );
+ else if ( val == "MonthlyDate" )
+ recur()->setType( ORecur::MonthlyDate );
+ else if ( val == "Yearly" )
+ recur()->setType( ORecur::Yearly );
+ else
+ recur()->setType( ORecur::NoRepeat );
+ break;
+ case FRWeekdays:
+ recur()->setDays( val.toInt() );
+ break;
+ case FRPosition:
+ recur()->setPosition( val.toInt() );
+ break;
+ case FRFreq:
+ recur()->setFrequency( val.toInt() );
+ break;
+ case FRHasEndDate:
+ recur()->setHasEndDate( val.toInt() );
+ break;
+ case FREndDate: {
+ rp_end = (time_t) val.toLong();
+ break;
+ }
+ default:
+ ev.setCustomField( attr, val );
+ break;
+ }
+}
+
+// from PalmtopRecord... GPL ### FIXME
+namespace {
+QString customToXml(const QMap<QString, QString>& customMap )
+{
+ //qWarning(QString("writing custom %1").arg(customMap.count()));
+ QString buf(" ");
+ for ( QMap<QString, QString>::ConstIterator cit = customMap.begin();
+ cit != customMap.end(); ++cit) {
+// qWarning(".ITEM.");
+ buf += cit.key();
+ buf += "=\"";
+ buf += Qtopia::escapeString(cit.data());
+ buf += "\" ";
+ }
+ return buf;
+}
+
+
+}
+
+QString OTodoAccessXML::toString( const OTodo& ev )const {
+ QString str;
+
+ str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
+ str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
+ str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
+ str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
+
+ str += "Categories=\"" + toString( ev.categories() ) + "\" ";
+ str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
+ str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
+
+ if ( ev.hasDueDate() ) {
+ str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
+ str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
+ str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
+ }
+// qWarning( "Uid %d", ev.uid() );
+ str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
+
+// append the extra options
+ /* FIXME Qtopia::Record this is currently not
+ * possible you can set custom fields
+ * but don' iterate over the list
+ * I may do #define private protected
+ * for this case - cough --zecke
+ */
+ /*
+ QMap<QString, QString> extras = ev.extras();
+ QMap<QString, QString>::Iterator extIt;
+ for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
+ str += extIt.key() + "=\"" + extIt.data() + "\" ";
+ */
+ // cross refernce
+ if ( ev.hasRecurrence() ) {
+ str += ev.recurrence().toString();
+ }
+ if ( ev.hasStartDate() )
+ str += "StartDate=\""+ OConversion::dateToString( ev.startDate() ) +"\" ";
+ if ( ev.hasCompletedDate() )
+ str += "CompletedDate=\""+ OConversion::dateToString( ev.completedDate() ) +"\" ";
+ if ( ev.hasState() )
+ str += "State=\""+QString::number( ev.state().state() )+"\" ";
+
+ /*
+ * save reminders and notifiers!
+ * DATE_TIME:DURATION:SOUND:NOT_USED_YET;OTHER_DATE_TIME:OTHER_DURATION:SOUND:....
+ */
+ if ( ev.hasNotifiers() ) {
+ OPimNotifyManager manager = ev.notifiers();
+ OPimNotifyManager::Alarms alarms = manager.alarms();
+ if (!alarms.isEmpty() ) {
+ QStringList als;
+ OPimNotifyManager::Alarms::Iterator it = alarms.begin();
+ for ( ; it != alarms.end(); ++it ) {
+ /* only if time is valid */
+ if ( (*it).dateTime().isValid() ) {
+ als << OConversion::dateTimeToString( (*it).dateTime() )
+ + ":" + QString::number( (*it).duration() )
+ + ":" + QString::number( (*it).sound() )
+ + ":";
+ }
+ }
+ // now write the list
+ qWarning("als: %s", als.join("____________").latin1() );
+ str += "Alarms=\""+als.join(";") +"\" ";
+ }
+
+ /*
+ * now the same for reminders but more easy. We just save the uid of the OEvent.
+ */
+ OPimNotifyManager::Reminders reminders = manager.reminders();
+ if (!reminders.isEmpty() ) {
+ OPimNotifyManager::Reminders::Iterator it = reminders.begin();
+ QStringList records;
+ for ( ; it != reminders.end(); ++it ) {
+ records << QString::number( (*it).recordUid() );
+ }
+ str += "Reminders=\""+ records.join(";") +"\" ";
+ }
+ }
+ str += customToXml( ev.toExtraMap() );
+
+
+ return str;
+}
+QString OTodoAccessXML::toString( const QArray<int>& ints ) const {
+ return Qtopia::Record::idsToString( ints );
+}
+
+/* internal class for sorting
+ *
+ * Inspired by todoxmlio.cpp from TT
+ */
+
+struct OTodoXMLContainer {
+ OTodo todo;
+};
+
+namespace {
+ inline QString string( const OTodo& todo) {
+ return todo.summary().isEmpty() ?
+ todo.description().left(20 ) :
+ todo.summary();
+ }
+ inline int completed( const OTodo& todo1, const OTodo& todo2) {
+ int ret = 0;
+ if ( todo1.isCompleted() ) ret++;
+ if ( todo2.isCompleted() ) ret--;
+ return ret;
+ }
+ inline int priority( const OTodo& t1, const OTodo& t2) {
+ return ( t1.priority() - t2.priority() );
+ }
+ inline int description( const OTodo& t1, const OTodo& t2) {
+ return QString::compare( string(t1), string(t2) );
+ }
+ inline int deadline( const OTodo& t1, const OTodo& t2) {
+ int ret = 0;
+ if ( t1.hasDueDate() &&
+ t2.hasDueDate() )
+ ret = t2.dueDate().daysTo( t1.dueDate() );
+ else if ( t1.hasDueDate() )
+ ret = -1;
+ else if ( t2.hasDueDate() )
+ ret = 1;
+ else
+ ret = 0;
+
+ return ret;
+ }
+
+};
+
+/*
+ * Returns:
+ * 0 if item1 == item2
+ *
+ * non-zero if item1 != item2
+ *
+ * This function returns int rather than bool so that reimplementations
+ * can return one of three values and use it to sort by:
+ *
+ * 0 if item1 == item2
+ *
+ * > 0 (positive integer) if item1 > item2
+ *
+ * < 0 (negative integer) if item1 < item2
+ *
+ */
+class OTodoXMLVector : public QVector<OTodoXMLContainer> {
+public:
+ OTodoXMLVector(int size, bool asc, int sort)
+ : QVector<OTodoXMLContainer>( size )
+ {
+ setAutoDelete( true );
+ m_asc = asc;
+ m_sort = sort;
+ }
+ /* return the summary/description */
+ QString string( const OTodo& todo) {
+ return todo.summary().isEmpty() ?
+ todo.description().left(20 ) :
+ todo.summary();
+ }
+ /**
+ * we take the sortorder( switch on it )
+ *
+ */
+ int compareItems( Item d1, Item d2 ) {
+ bool seComp, sePrio, seDesc, seDeadline;
+ seComp = sePrio = seDeadline = seDesc = false;
+ int ret =0;
+ OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1;
+ OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2;
+
+ /* same item */
+ if ( con1->todo.uid() == con2->todo.uid() )
+ return 0;
+
+ switch ( m_sort ) {
+ /* completed */
+ case 0: {
+ ret = completed( con1->todo, con2->todo );
+ seComp = TRUE;
+ break;
+ }
+ /* priority */
+ case 1: {
+ ret = priority( con1->todo, con2->todo );
+ sePrio = TRUE;
+ break;
+ }
+ /* description */
+ case 2: {
+ ret = description( con1->todo, con2->todo );
+ seDesc = TRUE;
+ break;
+ }
+ /* deadline */
+ case 3: {
+ ret = deadline( con1->todo, con2->todo );
+ seDeadline = TRUE;
+ break;
+ }
+ default:
+ ret = 0;
+ break;
+ };
+ /*
+ * FIXME do better sorting if the first sort criteria
+ * ret equals 0 start with complete and so on...
+ */
+
+ /* twist it we're not ascending*/
+ if (!m_asc)
+ ret = ret * -1;
+
+ if ( ret )
+ return ret;
+
+ // default did not gave difference let's try it other way around
+ /*
+ * General try if already checked if not test
+ * and return
+ * 1.Completed
+ * 2.Priority
+ * 3.Description
+ * 4.DueDate
+ */
+ if (!seComp ) {
+ if ( (ret = completed( con1->todo, con2->todo ) ) ) {
+ if (!m_asc ) ret *= -1;
+ return ret;
+ }
+ }
+ if (!sePrio ) {
+ if ( (ret = priority( con1->todo, con2->todo ) ) ) {
+ if (!m_asc ) ret *= -1;
+ return ret;
+ }
+ }
+ if (!seDesc ) {
+ if ( (ret = description(con1->todo, con2->todo ) ) ) {
+ if (!m_asc) ret *= -1;
+ return ret;
+ }
+ }
+ if (!seDeadline) {
+ if ( (ret = deadline( con1->todo, con2->todo ) ) ) {
+ if (!m_asc) ret *= -1;
+ return ret;
+ }
+ }
+
+ return 0;
+ }
+ private:
+ bool m_asc;
+ int m_sort;
+
+};
+
+QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder,
+ int sortFilter, int cat ) {
+ OTodoXMLVector vector(m_events.count(), asc,sortOrder );
+ QMap<int, OTodo>::Iterator it;
+ int item = 0;
+
+ bool bCat = sortFilter & 1 ? true : false;
+ bool bOnly = sortFilter & 2 ? true : false;
+ bool comp = sortFilter & 4 ? true : false;
+ for ( it = m_events.begin(); it != m_events.end(); ++it ) {
+
+ /* show category */
+ /* -1 == unfiled */
+ if ( bCat && cat == -1 ) {
+ if(!(*it).categories().isEmpty() )
+ continue;
+ }else if ( bCat && cat != 0)
+ if (!(*it).categories().contains( cat ) ) {
+ continue;
+ }
+ /* isOverdue but we should not show overdue - why?*/
+/* if ( (*it).isOverdue() && !bOnly ) {
+ qWarning("item is overdue but !bOnly");
+ continue;
+ }
+*/
+ if ( !(*it).isOverdue() && bOnly ) {
+ continue;
+ }
+
+ if ((*it).isCompleted() && comp ) {
+ continue;
+ }
+
+
+ OTodoXMLContainer* con = new OTodoXMLContainer();
+ con->todo = (*it);
+ vector.insert(item, con );
+ item++;
+ }
+ vector.resize( item );
+ /* sort it now */
+ vector.sort();
+ /* now get the uids */
+ QArray<int> array( vector.count() );
+ for (uint i= 0; i < vector.count(); i++ ) {
+ array[i] = ( vector.at(i) )->todo.uid();
+ }
+ return array;
+};
+void OTodoAccessXML::removeAllCompleted() {
+ QMap<int, OTodo> events = m_events;
+ for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) {
+ if ( (*it).isCompleted() )
+ events.remove( it.key() );
+ }
+ m_events = events;
+}
+QBitArray OTodoAccessXML::supports()const {
+ static QBitArray ar = sup();
+ return ar;
+}
+QBitArray OTodoAccessXML::sup() {
+ QBitArray ar( OTodo::CompletedDate +1 );
+ ar.fill( true );
+ ar[OTodo::CrossReference] = false;
+ ar[OTodo::State ] = false;
+ ar[OTodo::Reminders] = false;
+ ar[OTodo::Notifiers] = false;
+ ar[OTodo::Maintainer] = false;
+
+ return ar;
+}
+QArray<int> OTodoAccessXML::matchRegexp( const QRegExp &r ) const
+{
+ QArray<int> m_currentQuery( m_events.count() );
+ uint arraycounter = 0;
+
+ QMap<int, OTodo>::ConstIterator it;
+ for (it = m_events.begin(); it != m_events.end(); ++it ) {
+ if ( it.data().match( r ) )
+ m_currentQuery[arraycounter++] = it.data().uid();
+
+ }
+ // Shrink to fit..
+ m_currentQuery.resize(arraycounter);
+
+ return m_currentQuery;
+}
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 @@
+#ifndef OPIE_TODO_ACCESS_XML_H
+#define OPIE_TODO_ACCESS_XML_H
+
+#include <qasciidict.h>
+#include <qmap.h>
+
+#include "otodoaccessbackend.h"
+
+namespace Opie {
+ class XMLElement;
+};
+
+class OTodoAccessXML : public OTodoAccessBackend {
+public:
+ /**
+ * fileName if Empty we will use the default path
+ */
+ OTodoAccessXML( const QString& appName,
+ const QString& fileName = QString::null );
+ ~OTodoAccessXML();
+
+ bool load();
+ bool reload();
+ bool save();
+
+ QArray<int> allRecords()const;
+ QArray<int> matchRegexp(const QRegExp &r) const;
+ QArray<int> queryByExample( const OTodo&, int querysettings, const QDateTime& d = QDateTime() );
+ OTodo find( int uid )const;
+ void clear();
+ bool add( const OTodo& );
+ bool remove( int uid );
+ void removeAllCompleted();
+ bool replace( const OTodo& );
+
+ /* our functions */
+ QArray<int> effectiveToDos( const QDate& start,
+ const QDate& end,
+ bool includeNoDates );
+ QArray<int> overDue();
+ QArray<int> sorted( bool asc, int sortOrder,
+ int sortFilter, int cat );
+ QBitArray supports()const;
+private:
+ static QBitArray sup();
+ void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& );
+ QString toString( const OTodo& )const;
+ QString toString( const QArray<int>& ints ) const;
+ QMap<int, OTodo> m_events;
+ QString m_file;
+ QString m_app;
+ bool m_opened : 1;
+ bool m_changed : 1;
+ class OTodoAccessXMLPrivate;
+ OTodoAccessXMLPrivate* d;
+ int m_year, m_month, m_day;
+
+};
+
+#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 @@
+/*
+ * This file contains hacks or workarounds, that make it possible to use a normal
+ * libopie arm build (iPAQ or OZ) directly on the Sharp retail ROM.
+ * This way, we only need one 'official' libopie binary for all platforms.
+ */
+
+
+// 1) Opie's libqpe.so has an additional function in Sound, which is utilized
+// in ODevice:
+
+// ok this is really evil ;), but Sound::isFinished is only needed in the
+// iPAQ part of ODevice, which is never called on Z's
+// we add a "weak" symbol here. This will be used, if ld.so does not find
+// a normal ("hard") symbol of the same name - hence only on the retail Z
+
+struct Sound { bool Sound::isFinished ( ) const __attribute__(( weak )); };
+bool Sound::isFinished ( ) const { return true; }
+
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 @@
+
+#ifndef CONFIG_WIDGET_H
+#define CONFIG_WIDGET_H
+
+
+/**
+ * A base class for all Today Config Widgets.
+ * This will let a Today plugin to add the possibility of configuration.
+ * Plugins need to inherit from this class and need to implement
+ * the pure virtual method to control configuration.
+ * The Plugin should read its configuration during creation of the Widget
+ *
+ *
+ * @author Maximilian Reiß
+ * @short base class of all today config widgets
+ */
+class TodayConfigWidget : public QWidget {
+
+
+public:
+
+ /**
+ * This will construct the widget. The widget gets deleted once the parent
+ * gets deleted as in any Qt application
+ *
+ * @param parent The parent of the widget
+ * @param name The name of the object
+ */
+ TodayConfigWidget( QWidget *parent, const char *name ) : QWidget( parent, name ) {} ;
+ virtual ~TodayConfigWidget() {};
+
+ /**
+ * Plugins need to reimplement this in the config widget
+ * Used when the config dialog is closed to write config stuff
+ */
+ virtual void writeConfig() = 0;
+};
+
+#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 @@
+/*
+                This file is part of the Opie Project
+ Copyright (c) 2002 Maximilian Reiss <max.reiss@gmx.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+
+#ifndef TODAY_PLUGIN_INTERFACE
+#define TODAY_PLUGIN_INTERFACE
+
+#include <qpe/qcom.h>
+#include "todayconfigwidget.h"
+
+class QString;
+class QWidget;
+
+#ifndef IID_TodayPluginInterface
+#define IID_TodayPluginInterface QUuid( 0x70481804, 0x2b50, 0x4fba, 0x80, 0xbb, 0x0b, 0xf8, 0xdc, 0x72, 0x04, 0x14)
+#endif
+
+/**
+ *
+ * A TodayPluginObject is the base for all Today Plugins.
+ * A plugin author needs to inherit this class and implement
+ * the pure virtual methods
+ *
+ * @short base class for today plugins
+ * @author Maximilian Reiss
+ *
+ */
+class TodayPluginObject {
+
+public:
+
+ virtual ~TodayPluginObject() {};
+
+ /**
+ * The name if the plugin
+ * @return The plugin should return its name here
+ */
+ virtual QString pluginName() const = 0;
+
+ /**
+ * Version numbering
+ * @return The plugin should return the version number
+ */
+ virtual double versionNumber() const = 0;
+
+
+ /**
+ * @return the pixmap name widget?! -- FIXME
+ */
+ virtual QString pixmapNameWidget() const = 0;
+
+ /**
+ * widget for the today view
+ * It _needs_ a parent here.
+ * Plugin authors need to take parent as parent!
+ */
+ virtual QWidget* widget( QWidget *parent ) = 0;
+
+ /**
+ * Pixmap used in the config widget
+ */
+ virtual QString pixmapNameConfig() const = 0;
+
+ /**
+ * Config plugin widget - optional
+ * If the plugin has a config widget, it _needs_ a parent here.
+ * may return 0 if no config widget is needed
+ */
+ virtual TodayConfigWidget* configWidget( QWidget * ) = 0;
+
+ /**
+ * The application that should be assigned to the button (pixmap)
+ * Today will show the plugin icon. On click it tries to execute the
+ * plugin related application.
+ */
+ virtual QString appName() const = 0;
+
+
+ /**
+ * If the plugin should take part in the periodic refresh
+ */
+ virtual bool excludeFromRefresh() const = 0;
+
+ /**
+ * Refresh that plugins view. For updating the plugins
+ */
+ virtual void refresh() {};
+
+ /**
+ * reread the plugins config and act apropiate
+ * This is for example used when returning from the config dialog
+ */
+ virtual void reinitialize() {};
+};
+
+/**
+ * This is part of the QCOM works. See example plugins how to do it right
+ */
+struct TodayPluginInterface : public QUnknownInterface {
+ /**
+ * return the TodayPluginObject implementation
+ */
+ virtual TodayPluginObject *guiPart() = 0;
+};
+
+#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 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <qpe/stringutil.h>
+#include <opie/xmltree.h>
+
+#include <qxml.h>
+
+#include <assert.h>
+
+using namespace Opie;
+
+XMLElement::XMLElement()
+ : m_parent( 0 ), m_next( 0 ), m_prev( 0 ), m_first( 0 ), m_last( 0 )
+{
+}
+
+XMLElement::~XMLElement()
+{
+ XMLElement *n = m_first;
+
+ while ( n )
+ {
+ XMLElement *tmp = n;
+ n = n->m_next;
+ delete tmp;
+ }
+}
+
+void XMLElement::appendChild( XMLElement *child )
+{
+ if ( child->m_parent )
+ child->m_parent->removeChild( child );
+
+ child->m_parent = this;
+
+ if ( m_last )
+ m_last->m_next = child;
+
+ child->m_prev = m_last;
+
+ if ( !m_first )
+ m_first = child;
+
+ m_last = child;
+}
+
+void XMLElement::insertAfter( XMLElement *newChild, XMLElement *refChild )
+{
+ assert( newChild != refChild );
+
+ if ( refChild == m_last )
+ {
+ appendChild( newChild );
+ return;
+ }
+
+ assert( refChild );
+ assert( refChild->m_parent );
+ assert( refChild->m_parent == this );
+
+ if ( newChild->m_parent && newChild != refChild )
+ newChild->m_parent->removeChild( newChild );
+
+ newChild->m_parent = this;
+
+ XMLElement *next = refChild->m_next;
+
+ refChild->m_next = newChild;
+
+ newChild->m_prev = refChild;
+ newChild->m_next = next;
+
+ if ( next )
+ next->m_prev = newChild;
+}
+
+QString XMLElement::attribute( const QString &attr ) const
+{
+ AttributeMap::ConstIterator it = m_attributes.find( attr );
+ if ( it == m_attributes.end() )
+ return QString::null;
+ return it.data();
+}
+
+void XMLElement::setAttribute( const QString &attr, const QString &value )
+{
+ m_attributes.replace( attr, value );
+}
+
+void XMLElement::insertBefore( XMLElement *newChild, XMLElement *refChild )
+{
+ assert( refChild );
+ assert( refChild->m_parent );
+ assert( refChild->m_parent == this );
+ assert( newChild != refChild );
+
+ if ( newChild->m_parent && newChild != refChild )
+ newChild->m_parent->removeChild( newChild );
+
+ newChild->m_parent = this;
+
+ XMLElement *prev = refChild->m_prev;
+
+ refChild->m_prev = newChild;
+
+ newChild->m_prev = prev;
+ newChild->m_next = refChild;
+
+ if ( prev )
+ prev->m_next = newChild;
+
+ if ( refChild == m_first )
+ m_first = newChild;
+}
+
+void XMLElement::removeChild( XMLElement *child )
+{
+ if ( child->m_parent != this )
+ return;
+
+ if ( m_first == child )
+ m_first = child->m_next;
+
+ if ( m_last == child )
+ m_last = child->m_prev;
+
+ if ( child->m_prev )
+ child->m_prev->m_next = child->m_next;
+
+ if ( child->m_next )
+ child->m_next->m_prev = child->m_prev;
+
+ child->m_parent = 0;
+ child->m_prev = 0;
+ child->m_next = 0;
+}
+
+void XMLElement::save( QTextStream &s, uint indent )
+{
+ if ( !m_value.isEmpty() )
+ {
+ s << Qtopia::escapeString( m_value );
+ return;
+ }
+
+ for ( uint i = 0; i < indent; ++i )
+ s << " ";
+
+ s << "<" << m_tag;
+
+ if ( !m_attributes.isEmpty() )
+ {
+ s << " ";
+ AttributeMap::ConstIterator it = m_attributes.begin();
+ AttributeMap::ConstIterator end = m_attributes.end();
+ for (; it != end; ++it )
+ {
+ s << it.key() << "=\"" << Qtopia::escapeString( it.data() ) << "\"";
+ s << " ";
+ }
+ }
+
+ if ( m_last )
+ {
+ if ( ( m_first && !m_first->value().isEmpty() ) || !m_parent )
+ s << ">";
+ else
+ s << ">" << endl;
+
+ int newIndent = indent;
+ if ( m_parent )
+ newIndent++;
+
+ XMLElement *n = m_first;
+ while ( n )
+ {
+ n->save( s, newIndent );
+ n = n->nextChild();
+ }
+
+ if ( m_last && m_last->value().isEmpty() && m_parent )
+ for ( uint i = 0; i < indent; ++i )
+ s << " ";
+
+ if ( m_parent )
+ s << "</" << m_tag << ">" << endl;
+ }
+ else
+ s << "/>" << endl;
+}
+
+class Handler : public QXmlDefaultHandler
+{
+public:
+ Handler() : m_node( 0 ), m_root( 0 ) {}
+
+ XMLElement *root() const { return m_root; }
+
+ virtual bool startDocument();
+ virtual bool endDocument();
+ virtual bool startElement( const QString &ns, const QString &ln, const QString &qName,
+ const QXmlAttributes &attr );
+ virtual bool endElement( const QString &ns, const QString &ln, const QString &qName );
+ virtual bool characters( const QString &ch );
+
+private:
+ XMLElement *m_node;
+ XMLElement *m_root;
+};
+
+bool Handler::startDocument()
+{
+ m_root = m_node = new XMLElement;
+
+ return true;
+}
+
+bool Handler::endDocument()
+{
+ return m_root == m_node;
+}
+
+bool Handler::startElement( const QString &, const QString &, const QString &qName,
+ const QXmlAttributes &attr )
+{
+ XMLElement *bm = new XMLElement;
+
+ XMLElement::AttributeMap attributes;
+ for ( int i = 0; i < attr.length(); ++i )
+ attributes[ attr.qName( i ) ] = attr.value( i );
+
+ bm->setAttributes( attributes );
+
+ bm->setTagName( qName );
+
+ m_node->appendChild( bm );
+ m_node = bm;
+
+ return true;
+}
+
+bool Handler::endElement( const QString &, const QString &, const QString & )
+{
+ if ( m_node == m_root )
+ return false;
+
+ m_node = m_node->parent();
+ return true;
+}
+
+bool Handler::characters( const QString &ch )
+{
+ XMLElement *textNode = new XMLElement;
+ textNode->setValue( ch );
+ m_node->appendChild( textNode );
+ return true;
+}
+
+XMLElement *XMLElement::namedItem( const QString &name )
+{
+ XMLElement *e = m_first;
+
+ for (; e; e = e->nextChild() )
+ if ( e->tagName() == name )
+ return e;
+
+ return 0;
+}
+
+XMLElement *XMLElement::clone() const
+{
+ XMLElement *res = new XMLElement;
+
+ res->setTagName( m_tag );
+ res->setValue( m_value );
+ res->setAttributes( m_attributes );
+
+ XMLElement *e = m_first;
+ for (; e; e = e->m_next )
+ res->appendChild( e->clone() );
+
+ return res;
+}
+
+XMLElement *XMLElement::load( const QString &fileName )
+{
+ QFile f( fileName );
+ if ( !f.open( IO_ReadOnly ) )
+ return 0;
+
+ QTextStream stream( &f );
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+ QXmlInputSource src( stream );
+ QXmlSimpleReader reader;
+ Handler handler;
+
+ reader.setFeature( "http://trolltech.com/xml/features/report-whitespace-only-CharData", false );
+ reader.setContentHandler( &handler );
+ reader.parse( src );
+
+ return handler.root();;
+}
+
+/* vim: et sw=4
+ */
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 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000,2001 Simon Hausmann <hausmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __bookmarks_h__
+#define __bookmarks_h__
+
+#include <qstring.h>
+#include <qmap.h>
+#include <qtextstream.h>
+
+namespace Opie
+{
+
+/**
+ * A small xml lib written by Simon Hausmann.
+ */
+class XMLElement
+{
+public:
+ typedef QMap<QString, QString> AttributeMap;
+
+ /**
+ * The constructor of XMLElement
+ */
+ XMLElement();
+ ~XMLElement();
+
+ /** appendChild appends a child to the XMLElement behind the last element.
+ * The ownership of the child get's transfered to the
+ * this XMLElement.
+ * If child is already the child of another parent
+ * it's get removed from the other parent first.
+ */
+ void appendChild( XMLElement *child );
+
+ /** inserts newChild after refChild. If newChild is the child
+ * of another parent the child will get removed.
+ * The ownership of child gets transfered.
+ *
+ */
+ void insertAfter( XMLElement *newChild, XMLElement *refChild );
+
+ /** same as insertAfter but the element get's inserted before refChild.
+ *
+ */
+ void insertBefore( XMLElement *newChild, XMLElement *refChild );
+
+ /** removeChild removes the child from the XMLElement.
+ * The ownership gets dropped. You need to delete the
+ * child yourself.
+ */
+ void removeChild( XMLElement *child );
+
+ /** parent() returns the parent of this XMLElement
+ * If there is no parent 0l gets returned
+ */
+ XMLElement *parent() const { return m_parent; }
+ XMLElement *firstChild() const { return m_first; }
+ XMLElement *nextChild() const { return m_next; }
+ XMLElement *prevChild() const { return m_prev; }
+ XMLElement *lastChild() const { return m_last; }
+
+ void setTagName( const QString &tag ) { m_tag = tag; }
+ QString tagName() const { return m_tag; }
+
+ void setValue( const QString &val ) { m_value = val; }
+ QString value() const { return m_value; }
+
+ void setAttributes( const AttributeMap &attrs ) { m_attributes = attrs; }
+ AttributeMap attributes() const { return m_attributes; }
+ AttributeMap &attributes() { return m_attributes; }
+
+ QString attribute( const QString & ) const;
+ void setAttribute( const QString &attr, const QString &value );
+ void save( QTextStream &stream, uint indent = 0 );
+
+ XMLElement *namedItem( const QString &name );
+
+ XMLElement *clone() const;
+
+ static XMLElement *load( const QString &fileName );
+
+private:
+ QString m_tag;
+ QString m_value;
+ AttributeMap m_attributes;
+
+ XMLElement *m_parent;
+ XMLElement *m_next;
+ XMLElement *m_prev;
+ XMLElement *m_first;
+ XMLElement *m_last;
+
+ XMLElement( const XMLElement &rhs );
+ XMLElement &operator=( const XMLElement &rhs );
+ class Private;
+ Private* d;
+};
+
+} // namespace Opie
+
+#endif