Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

simple.cpp

Go to the documentation of this file.
00001 /* We use a sane order of include files, from the most special to the least special
00002    That helps to reduce the number of implicit includes hence increases the reuse */
00003 
00004 /* First the local include files */
00005 #include "simple.h"
00006 
00007 /* Then the Ope include files.
00008 This includes qpe stuff which will eventually be merged with libopie2 */
00009 #include <opie2/odebug.h> // for odebug streams
00010 #include <opie2/oapplicationfactory.h> // a template + macro to save the main method and allow quick launching
00011 #include <opie2/oresource.h>
00012 #include <opie2/otabwidget.h>
00013 #include <opie2/owait.h>
00014 #include <qpe/qpeapplication.h> // the QPEApplication
00015 #include <qpe/sound.h>
00016 #include <qpe/qcopenvelope_qws.h>
00017 #include <qpe/datebookmonth.h>
00018 #include <qpe/timestring.h>
00019 using namespace Opie::Core;
00020 
00021 /* Now the Qt includes */
00022 #include <qaction.h> // action
00023 #include <qmenubar.h> // menubar
00024 #include <qtoolbar.h> // toolbar
00025 #include <qlabel.h> // a label
00026 #include <qpushbutton.h> // the header file for the QPushButton
00027 #include <qlayout.h>
00028 #include <qtimer.h> // we use it for the singleShot
00029 #include <qdatetime.h> // for QDate
00030 #include <qtextview.h> // a rich text widget
00031 #include <qdialog.h>
00032 #include <qwhatsthis.h> // for whats this
00033 
00034 /* Add standard includes here if you need some
00035    Examples are: stdlib.h, socket.h, etc. */
00036 
00037 /*
00038  * implementation of simple
00039  */
00040 
00041 /*
00042  * The factory is used for quicklaunching
00043  * It needs a constructor ( c'tor ) with at least QWidget, const char* and WFlags as parameter and a static QString appName() matching the TARGET of the .pro
00044  *
00045  * Depending on the global quick launch setting this will create
00046  * either a main method or one for our component plugin system
00047  */
00048 
00049 OPIE_EXPORT_APP( OApplicationFactory<MainWindow> )
00050 
00051 MainWindow::MainWindow(QWidget *parent,  const char* name, WFlags fl )
00052     : QMainWindow( parent, name, fl ) {
00053     setCaption(tr("My MainWindow") );
00054 
00055     m_desktopChannel = 0;
00056     m_loading = 0;
00057 
00058     initUI();
00059 
00060 
00061     /*
00062      * Tab widget as central
00063      */
00064     m_tab = new Opie::Ui::OTabWidget(this);
00065 
00066     setCentralWidget( m_tab );
00067 
00068     m_todoView = new PIMListView(m_tab, "Todo view" );
00069     m_tab->addTab( m_todoView,"todo/TodoList", tr("Todos") );
00070 
00071     m_dateView = new PIMListView(m_tab, "Datebook view" );
00072     m_tab->addTab( m_dateView, "datebook/DateBook", tr("Events") );
00073 
00074     /* now connect the actions */
00075     /*
00076      * we connect the activated to our show
00077      * and on activation we will show a detailed
00078      * summary of the record
00079      */
00080     connect(m_fire, SIGNAL(activated() ),
00081             this, SLOT(slotShow() ) );
00082 
00083     /*
00084      * We will change the date
00085      */
00086     connect(m_dateAction, SIGNAL(activated() ),
00087             this, SLOT(slotDate() ) );
00088 
00089     /*
00090      * connect the show signal of the PIMListView
00091      * to a slot to show a dialog
00092      */
00093     connect(m_todoView, SIGNAL(showRecord(const Opie::OPimRecord&) ),
00094             this, SLOT(slotShowRecord(const Opie::OPimRecord&) ) );
00095     connect(m_dateView, SIGNAL(showRecord(const Opie::OPimRecord&) ),
00096             this, SLOT(slotShowRecord(const Opie::OPimRecord&) ) );
00097 
00098     /*
00099      * Now comes the important lines of code for this example
00100      * We do not directly call load but delay loading until
00101      * all Events are dispatches and handled.
00102      * SO we will load once our window is mapped to screen
00103      * to achieve that we use a QTimer::singleShot
00104      * After 10 milli seconds the timer fires and on TimerEvent
00105      * out slot slotLoad will be called
00106      * Remember this a Constructor to construct your object and not
00107      * to load
00108      */
00109     QTimer::singleShot( 10, this, SLOT(slotLoad() ) );
00110 }
00111 
00112 MainWindow::~MainWindow() {
00113     // again nothing to delete because Qt takes care
00114 }
00115 
00116 
00117 void MainWindow::setDocument( const QString& /*str*/ ) {
00118 }
00119 
00120 
00121 void MainWindow::initUI() {
00122 
00123     setToolBarsMovable( false );
00124 
00125     QToolBar *menuBarHolder = new QToolBar( this );
00126 
00127     menuBarHolder->setHorizontalStretchable( true );
00128     QMenuBar *mb = new QMenuBar( menuBarHolder );
00129     QToolBar *tb = new QToolBar( this );
00130 
00131     QPopupMenu *fileMenu = new QPopupMenu( this );
00132 
00133 
00134     QAction *a = new QAction( tr("Quit"), Opie::Core::OResource::loadPixmap("quit_icon", Opie::Core::OResource::SmallIcon),
00135                               QString::null, 0, this, "quit_action" );
00136     /*
00137      * Connect quit to the QApplication quit slot
00138      */
00139     connect(a, SIGNAL(activated() ),
00140             qApp, SLOT(quit() ) );
00141     a->addTo( fileMenu );
00142 
00143     a =  new QAction(tr("View Current"),
00144                      Opie::Core::OResource::loadPixmap("zoom", Opie::Core::OResource::SmallIcon),
00145                      QString::null, 0, this, "view current");
00146     /* a simple whats this online explanation of out button */
00147     a->setWhatsThis(tr("Views the current record")  );
00148     /* or QWhatsThis::add(widget, "description" ); */
00149 
00150     /* see  the power? */
00151     a->addTo( fileMenu );
00152     a->addTo( tb );
00153     m_fire = a;
00154 
00155     a = new QAction(tr("Choose Date"),
00156                     Opie::Core::OResource::loadPixmap("day", Opie::Core::OResource::SmallIcon),
00157                     QString::null, 0, this, "choose date" );
00158     a->addTo( fileMenu );
00159     a->addTo( tb );
00160     m_dateAction = a;
00161 
00162     mb->insertItem(tr("File"), fileMenu );
00163 
00164 }
00165 
00166 void MainWindow::slotLoad() {
00167     /*
00168      * There is no real shared access in the PIM API
00169      * It wasn't finish cause of health problems of one
00170      * of the authors so we do something fancy and use QCOP
00171      * the IPC system to get a current copy
00172      */
00173     /* NOTES to QCOP: QCOP operates over channels and use QDataStream
00174      * to send data. You can check if a channel isRegistered or hook
00175      * yourself to that channel. A Channel is QCString and normally
00176      * prefix with QPE/ and then the system in example QPE/System,
00177      * QPE/Desktop a special channel is the application channel
00178      * it QPE/Application/appname this channel gets created on app
00179      * startup by QPEApplication. QCOP is asynchronous
00180      *
00181      * To send you'll use QCopEnevelope
00182      *
00183      */
00184     /*
00185      * What we will do is first is get to know if either
00186      * datebook or todolist are running if so we will kindly
00187      * asked to save the data for us.
00188      * If neither are running we can load directly
00189      */
00190     if (!QCopChannel::isRegistered("QPE/Application/todolist") &&
00191         !QCopChannel::isRegistered("QPE/Application/datebook") ) {
00192         m_db.load();
00193         m_tb.load();
00194         return slotLoadForDay( QDate::currentDate() );
00195     }
00196 
00197     /*
00198      * prepare our answer machine the QCopChannel
00199      * QPE/Desktop will send "flushDone(QString)" when
00200      * the flush is done it emits a signal on receive
00201      */
00202     m_desktopChannel = new QCopChannel("QPE/Desktop");
00203     connect(m_desktopChannel, SIGNAL(received(const QCString&,const QByteArray&) ),
00204             this, SLOT(slotDesktopReceive(const QCString&,const QByteArray&) ) );
00205     /* the numberof synced channels will be set to zero */
00206     m_synced = 0;
00207 
00208     /*
00209      * We use {} around the QCopEnvelope because it sends its
00210      * data on destruction of QCopEnvelope with
00211      */
00212     /* check again  if not present increment synced*/
00213     if ( QCopChannel::isRegistered("QPE/Application/todolist") ) {
00214         QCopEnvelope env("QPE/Application/todolist", "flush()" );
00215         // env << data; but we do not have any parameters here
00216     }else
00217         m_synced++;
00218 
00219     if ( QCopChannel::isRegistered("QPE/Application/datebook") ) {
00220         QCopEnvelope env("QPE/Application/datebook", "flush()" );
00221     }else
00222         m_synced++;
00223 
00224     /* we will provide a wait scrren */
00225     m_loading = new Opie::Ui::OWait(this, "wait screen" );
00226 }
00227 
00228 void MainWindow::slotDesktopReceive(const QCString& cmd, const QByteArray& data ) {
00229     /* the bytearray was filled with the QDataStream now
00230      * we open it read only to get the value(s)
00231      */
00232     QDataStream stream(data, IO_ReadOnly );
00233     /*
00234      * we're only interested in the flushDone
00235      */
00236     if ( cmd == "flushDone(QString)" ) {
00237         QString appname;
00238         stream >> appname; // get the first argument out of stream
00239         if (appname == QString::fromLatin1("datebook") ||
00240             appname == QString::fromLatin1("todolist") )
00241             m_synced++;
00242     }
00243 
00244     /*
00245      * If we synced both we can go ahead
00246      * In future this is not needed anymore when we finally
00247      * implemented X-Ref and other PIM features
00248      */
00249     if (m_synced >= 2 ) {
00250         delete m_loading;
00251         delete m_desktopChannel;
00252         /* now we finally can start doing the actual loading */
00253         m_tb.load();
00254         m_db.load();
00255         {
00256             /* tell the applications to reload */
00257             QCopEnvelope("QPE/Application/todolist", "reload()");
00258             QCopEnvelope("QPE/Application/datebook", "reload()");
00259         }
00260         slotLoadForDay( QDate::currentDate() );
00261     }
00262 
00263 }
00264 
00265 /* overloaded member for shortcoming of libqpe */
00266 void MainWindow::slotLoadForDay(int y, int m, int d) {
00267     /* year,month, day */
00268     slotLoadForDay( QDate(y, m, d ) );
00269 }
00270 
00271 void MainWindow::slotLoadForDay(const QDate& date) {
00272 
00273 
00274     /* all todos for today including the ones without dueDate */
00275     m_todoView->set( m_tb.effectiveToDos(date, date ) );
00276     m_dateView->set( m_db.occurrences( date, date ) );
00277 }
00278 
00279 /* we want to show the current record */
00280 void MainWindow::slotShow() {
00281     /* we only added PIMListViews so we can safely cast */
00282     PIMListView *view = static_cast<PIMListView*>(m_tab->currentWidget() );
00283 
00284     /* ask the view to send a signal */
00285     view->showCurrentRecord();
00286 
00287 }
00288 
00289 /* as answer this slot will be called */
00290 void MainWindow::slotShowRecord( const Opie::OPimRecord& rec) {
00291     /* got a parent but still is a toplevel MODAL dialog */
00292     QDialog* dia = new QDialog(this,"dialog",TRUE );
00293     QVBoxLayout *box = new QVBoxLayout( dia );
00294     dia->setCaption( tr("View Record") );
00295 
00296 
00297     QTextView *view = new QTextView(dia );
00298     view->setText( rec.toRichText() );
00299     box->addWidget( view );
00300     /*
00301      * execute via QPEApplication
00302      * this allows QPEApplication to make a sane decision
00303      * on the size
00304      */
00305     dia->showMaximized();
00306     QPEApplication::execDialog( dia );
00307     delete dia;
00308 }
00309 
00310 
00311 void MainWindow::slotDate() {
00312     /*
00313      * called by the action we will show a Popup
00314      * at the current mouse position with a DateChooser
00315      * to select the day
00316      */
00317     odebug << "slot Date" << oendl;
00318     QPopupMenu *menu = new QPopupMenu();
00319     /* A Month to select a date from TRUE for auto close */
00320     DateBookMonth *month = new DateBookMonth(menu, 0, true );
00321     connect(month, SIGNAL(dateClicked(int,int,int) ),
00322             this, SLOT(slotLoadForDay(int,int,int) ) );
00323 
00324     menu->insertItem( month );
00325 
00326     menu->exec( QCursor::pos() );
00327 
00328     /*
00329      * we do not need to delete month because
00330      * we delete its parent menu
00331      */
00332 
00333     delete menu;
00334 }
00335 
00336 /*
00337  * An anonymous namespace this symbol is only available here
00338  * so truely private
00339  */
00340 namespace {
00341     /* not static cause namespace does that what static would do */
00342     const int RTTI = 5050;
00343     /*
00344      * every ListView got Items. we've special pim items
00345      * holding ownership and the pointer to a pim record
00346      * it can't hold a pimrecord directly because this
00347      * would introduce slicing... any break
00348      */
00349     /*
00350      * A struct is a special class. Everything is public by
00351      * default.
00352      */
00353     struct PIMListViewItem : public QListViewItem {
00354         /*
00355          *currently no hierachies are planed for the example
00356          * so only one constructor with a QListView as parent
00357          */
00358         PIMListViewItem( QListView*, Opie::OPimRecord* record );
00359         ~PIMListViewItem();
00360 
00361         /* used by the QListViewItem to easily allow identifiying of different
00362          * items. Values greater than 1000 should be used */
00363         int rtti()const;
00364         Opie::OPimRecord* record()const;
00365 
00366     private:
00367         Opie::OPimRecord* m_record;
00368     };
00369 
00370     PIMListViewItem::PIMListViewItem( QListView *p, Opie::OPimRecord* rec )
00371         : QListViewItem(p), m_record( rec ) {
00372     }
00373 
00374     PIMListViewItem::~PIMListViewItem() {
00375         /* we've the onwership so we need to delete it */
00376         delete m_record;
00377     }
00378 
00379     Opie::OPimRecord* PIMListViewItem::record()const {
00380         return m_record;
00381     }
00382 
00383 }
00384 
00385 
00386 PIMListView::PIMListView( QWidget* widget, const char* name, WFlags fl  )
00387     : QListView(widget, name, fl )
00388 {
00389     addColumn("Summary");
00390 }
00391 
00392 PIMListView::~PIMListView() {
00393 
00394 }
00395 
00396 void PIMListView::set( Opie::OPimTodoAccess::List list ) {
00397     /* clear first and then add new items */
00398     clear();
00399 
00400     Opie::OPimTodoAccess::List::Iterator it;
00401     for (it = list.begin(); it != list.end(); ++it ) {
00402         /*
00403          * make a new item which automatically gets added to the listview
00404          * and call the copy c'tor to create a new OPimTodo
00405          */
00406         PIMListViewItem *i = new PIMListViewItem(this, new Opie::OPimTodo( *it ) );
00407         i->setText(0, (*it).summary() );
00408     }
00409 }
00410 
00411 void PIMListView::set( const Opie::OPimOccurrence::List& lst ) {
00412     /* clear first and then add items */
00413     clear();
00414 
00415     Opie::OPimOccurrence::List::ConstIterator it;
00416     for ( it = lst.begin(); it != lst.end(); ++it ) {
00417         PIMListViewItem *i = new PIMListViewItem(this, new Opie::OPimEvent( (*it).toEvent() ) );
00418         i->setText( 0, PIMListView::makeString( (*it) ) );
00419     }
00420 
00421 }
00422 
00423 void PIMListView::showCurrentRecord() {
00424     /* it could be possible that their is no currentItem */
00425     if (!currentItem() )
00426         return;
00427 
00428     /*
00429      * we only add PIMListViewItems so it is save
00430      * to do this case. If this would not be the case
00431      * use rtti() to check in a switch() case
00432      */
00433     PIMListViewItem *item = static_cast<PIMListViewItem*>( currentItem() );
00434 
00435     /* finally you see how to emit a signal */
00436     emit showRecord( (*item->record() ) );
00437 }
00438 
00439 QString PIMListView::makeString( const Opie::OPimOccurrence& _ev ) {
00440     QString str;
00441     str += _ev.summary();
00442     
00443     Opie::OPimEvent ev = _ev.toEvent();
00444     if ( !ev.isAllDay() ) {
00445 #if 0    
00446         if ( ev.startDate() != ev.endDate() ) {
00447             str += tr("Start ") + TimeString::timeString( ev.startDateTime().time() );
00448             str += " - " + TimeString::longDateString( ev.startDateTime().date() );
00449             str +=  tr("End ") + TimeString::timeString( ev.endDateTime().time() );
00450             str += " - " + TimeString::longDateString( ev.endDateTime().date() );
00451         }else
00452 #endif  
00453         {
00454             str += tr("Time ") + TimeString::timeString( _ev.startTime() );
00455             str += " - " + TimeString::timeString( _ev.endTime() );
00456         }
00457     }else
00458         str += tr(" This is an All-Day Event");
00459 
00460     return str;
00461 }

Generated on Sat Nov 5 16:15:59 2005 for OPIE by  doxygen 1.4.2