00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef OMODALHELPER_H
00030 #define OMODALHELPER_H
00031
00032
00033 #include <qdialog.h>
00034 #include <qwidget.h>
00035 #include <qvaluelist.h>
00036 #include <qmap.h>
00037 #include <qvariant.h>
00038
00039 typedef int TransactionID;
00040
00041 class QDialog;
00042
00043 namespace Opie
00044 {
00045
00046 class OModalHelperControler;
00047 class OModalHelperSignal;
00048
00049 struct OModalHelperBase
00050 {
00051 virtual void done( int status, TransactionID ) = 0;
00052 virtual void next( TransactionID ) = 0;
00053 virtual void prev( TransactionID ) = 0;
00054 };
00055
00079 template<class Dialog, class Record, typename Id = int>
00080 class OModalHelper : private OModalHelperBase
00081 {
00082 friend class OModalHelperSignal;
00083 friend class OModalHelperControler;
00084 public:
00085 typedef QValueList<Record> RecordList;
00086 typedef QMap<Id, Record> IdMap;
00087 typedef QMap<TransactionID, Id> TransactionMap;
00088 typedef QMap<QDialog*, TransactionID> DialogMap
00089 enum Mode { Queue, New };
00090 OModalHelper(enum Mode mode, QObject* parnet );
00091
00092 bool handles( Id id)const;
00093 TransactionID transactionID( Id id)const;
00094
00095 void suspend( bool = true );
00096
00097 void cancel();
00098 void cancel( TransactionID );
00099
00100 void connectDone( QObject* rec, const char* slot );
00101 void connectAccepted( QObject* rec, const char* slot );
00102 void connectRejected( QObject* rec, const char* slot );
00103
00104 TransactionID handle( Id id, const Record& rec = Record() );
00105
00106 void edited( Id, int what, const QVariant& data );
00107
00108 Record record( TransactionID )const;
00109 RecordList recordsDone()const;
00110 private:
00111 virtual void done( int, TransactionID );
00112 virtual void next( TransactionID );
00113 virtual void prev( TransactionID );
00114
00115 Record nextRecord( TransactionID &, int & )const;
00116 Record prevRecord( TransactionID &, int & )const;
00117 int pos( TransactionID )const;
00118 Dialog* newDialogRecord( const Record& );
00119
00120 private:
00121 OModalHelperDialog *queuedDialog()const;
00122 OModalHelperDialog *m_dialog;
00123 OModalHelperSignal *m_signal;
00124 OModalHelperControler *m_controler;
00125 IdMap m_ids;
00126 IdMap m_doneIds;
00127 TransactionMap m_transactions;
00128 TransactionMap m_done;
00129 DialogMap m_editing;
00130 enum Mode m_mode;
00131 bool m_disabled :1;
00132 };
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 class OModalHelperSignal : public QObject
00151 {
00152 Q_OBJECT
00153 public:
00154 OModalHelperSignal(OModalHelperBase* base, QObject* parent);
00155 ~OModalHelperSignal();
00156
00157 signals:
00158 done( int status, TransactionID transaction );
00159 accepted( TransactionID transaction );
00160 rejected( TransactionID transaction );
00161
00162 private:
00163 OModalHelperBase* m_base;
00164 };
00165
00166
00167 class OModalHelperControler : public QObject
00168 {
00169 Q_OBJECT
00170 public:
00171 OModalHelperControler( OModalHelperBase* , QObject* parent);
00172 virtual TransactionID transactionID()const;
00173 void setTransactionID( TransactionID id );
00174 QDialog* dialog()const;
00175
00176 public slots:
00177 virtual void done(int result );
00178 virtual void next();
00179 virtual void prev();
00180 private:
00181 QDialog *m_dia;
00182 TransactionID m_id;
00183 OModalHelperBase *m_base;
00184 }
00185
00186 struct OModalQueueBar;
00187 class OModalQueuedDialog : public QDialog
00188 {
00189 Q_OBJECT
00190 public:
00191 OModalQueuedDialog(QDialog *mainWidget);
00192 ~OModalQueuedDialog();
00193
00194 QDialog* centerDialog()const;
00195
00196 void setQueueBarEnabled( bool = true );
00197 void setRecord( int record, int count );
00198
00199 signals:
00200 void next();
00201 void prev();
00202
00203 private:
00204 OModalQueueBar *m_bar;
00205 QDialog *m_center;
00206 };
00207
00208
00209
00210
00211
00212
00222 template<class Dialog, class Record, typename Id>
00223 OModalHelper<Dialog, Record, Id>::OModalHelper( enum Mode mode, QObject* parent )
00224 {
00225 m_disabled = false;
00226 m_mode = mode;
00227 m_signal = new OModalHelperSignal( this, parent );
00228 m_controler = new OModalHelperControler( this, m_signal );
00229 }
00230
00231
00241 template<class Dialog, class Record, typename Id>
00242 bool OModalHelper<Dialog, Record, Id>::handles( Id id )const
00243 {
00244 if ( m_transactions.isEmpty() )
00245 return false;
00246
00247 TransactionMap::ConstIterator it = m_transactions.begin();
00248 for ( ; it != m_transactions.end(); ++it )
00249 if ( it.data() == id )
00250 return true;
00251
00252 return false;
00253 }
00254
00255
00259 template<class Dialog, class Record, typename Id>
00260 TransactionID OModalHelper<Dialog, Record, Id>::transactionID( Id id)const
00261 {
00262 if ( m_transactions.isEmpty() || !m_ids.contains( id ) )
00263 return 0;
00264
00265 TransactionMap::ConstIterator it = m_transactions.begin();
00266 for ( ; it != m_transactions.end(); ++it )
00267 if ( it.data() == id )
00268 return it.key();
00269
00270 return 0;
00271 }
00272
00282 template<class Dialog, class Record, typename Id>
00283 void OModalHelper<Dialog, Record, Id>::suspend(bool sus)
00284 {
00285 m_disabled = sus;
00286 if (m_mode == New )
00287 for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it )
00288 it.key()->setDisabled( sus );
00289 else if (m_dialog )
00290 queuedDialog()->setDisabled( sus );
00291 }
00292
00298 template<class Dialog, class Record, typename Id>
00299 void OModalHelper<Dialog, Record, Id>::cancel()
00300 {
00301 m_ids.clear();
00302 m_doneIds.clear();
00303 m_done.clear();
00304 m_transactions.clear();
00305
00306
00307
00308 if (m_mode == New && !m_editing.isEmpty() )
00309 {
00310 for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it )
00311 delete it.key();
00312
00313 m_editing.clear();
00314 }
00315 else if (m_dialog )
00316 queuedDialog()->setRecord( 0, 0 );
00317
00318 m_controler->setTransactionID( 0 );
00319 }
00320
00321
00326 template<class Dialog, class Record, typename Id>
00327 void OModalHelper::cancel( TransactionID tid )
00328 {
00329
00330 if (!m_transactions.contains( tid ) && !m_done.contains( tid) )
00331 return;
00332
00333 if (m_mode == New )
00334
00335 for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it )
00336 if ( it.data() == tid )
00337 {
00338 it.key()->hide();
00339 delete it.key();
00340 it = m_editing.remove( it );
00341 break;
00342 }
00343
00344
00345 if (m_transactions.contains( tid ) )
00346 m_ids.remove( m_transactions[tid] );
00347 if (m_done.contains( tid ) )
00348 m_doneIds.remove( m_done[tid ] );
00349 m_done.remove( tid );
00350 m_transactions.remove( tid );
00351
00352 next( 0 );
00353 }
00354
00362 template<class Dialog, class Record, typename Id>
00363 void OModalHelper<Dialog, Record, Id>::connectDone( QObject* rec, const char* slot )
00364 {
00365 QObject::connect(m_signal, SIGNAL(done(int, TransactionID) ),
00366 rec, slot );
00367 }
00368
00376 template<class Dialog, class Record, typename Id>
00377 void OModalHelper<Dialog, Record, Id>::connectAccepted( QObject* rec, const char* slot )
00378 {
00379 QObject::connect(m_signal, SIGNAL(accepted(TransactionID) ),
00380 rec, slot );
00381 }
00382
00391 template<class Dialog, class Record, typename Id>
00392 void OModalHelper<Dialog, Record, Id>::connectRejected( QObject* rec, const char* slot )
00393 {
00394 QObject::connect(m_signal, SIGNAL(rejected(TransactionID) ),
00395 rec, slot );
00396 }
00397
00413 template<class Dialog, class Record, typename Id>
00414 TransactionID OModalHelper<Dialog, Record, Id>::handle( Id id, const Record& rec )
00415 {
00416 static TransactionID t_id = 0;
00417
00418
00419
00420
00421
00422 TransactionID tid = 0;
00423
00424 if ( !(tid = transactionID( id ) ) )
00425 {
00426 if (m_mode == New )
00427 {
00428
00429 for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it )
00430 if ( it.data() == tid )
00431 it.key()->show();
00432 }
00433 else if (m_controler->transactionID() != tid )
00434 {
00435 int po = pos( tid );
00436 m_controler->setTransactionID( tid );
00437 static_cast<Dialog*>( queuedDialog()->centerDialog() )->setRecord( m_ids[ m_transactions[tid] ] );
00438 queuedDialog()->setRecord( po, m_transactions.count() );
00439 }
00440 }
00441 else
00442 {
00443 tid = ++t_id;
00444 m_transactions.insert( tid, id );
00445 m_ids.insert( id, rec );
00446
00447 if (m_mode == New )
00448 m_editing.insert( newDialogRecord( rec ), tid );
00449 else
00450 {
00451 m_controler->setTransactionID( tid );
00452 static_cast<Dialog*>( queuedDialog()->centerDialog() )->setRecord( rec );
00453 queuedDialog()->setRecord( m_transactions.count(), m_transactions.count() );
00454 }
00455 }
00456 return tid;
00457 }
00458
00470 template<class Dialog, class Record, typename Id>
00471 void OModalHelper<Dialog, Record, Id>::edited( Id id, int what, const QVariant& data )
00472 {
00473 int tid;
00474 if (!( tid = transactionID( id ) ) )
00475 return;
00476
00477 if (m_mode == New )
00478 {
00479 for (DialogMap::Iterator it= m_editing.begin(); it != m_editing.end(); ++it )
00480 if ( it.data() == tid )
00481 it.key()->setData( what, data );
00482 }
00483 else
00484 {
00485 int po = pos( tid );
00486 Dialog* dia = static_cast<Dialog*>( queuedDialog()->centerDialog() );
00487 dia->setRecord( m_ids[id] );
00488 dia->setData( what, data );
00489 queuedDialog()->setRecord( pos, m_transactions.count() );
00490 }
00491 }
00492
00501 template<class Dialog, class Record, typename Id>
00502 Record OModalHelper<Dialog, Record, Id>::record( TransactionID tid)const
00503 {
00504 if (m_transactions.contains( tid ) )
00505 return m_ids[ m_transactions[tid] ];
00506 else if (m_done.contains( tid ) )
00507 {
00508 Record rec = m_doneIds[ m_done[ tid] ];
00509 m_doneIds.remove( m_done[ tid ] );
00510 m_done.remove( tid );
00511 return rec;
00512 }
00513 else
00514 return Record();
00515 }
00516
00521 template<class Dialog, class Record, typename Id>
00522 OModalHelper<Dialog,Record,Id>::RecordList OModalHelper<Dialog, Record, Id>::recordsDone()const
00523 {
00524 RecordList list;
00525
00526 for (IdMap::ConstIterator it = m_doneIds.begin(); it != m_doneIds.end(); ++it )
00527 list.append( it.data() );
00528
00529
00530 m_done.clear();
00531 m_doneIds.clear();
00532
00533 return list;
00534 }
00535
00536
00540 template<class Dialog, class Record, typename Id>
00541 void OModalHelper<Dialog, Record, Id>::done( int status, TransactionID tid)
00542 {
00543
00544 Record rec;
00545
00546 if (m_mode == New )
00547 {
00548 Dialog *dia = static_cast<Dialog*>( m_controler->dialog() );
00549 m_controler->setTransactionID( 0 );
00550 tid = m_editing[ dia ];
00551 m_editing.remove( dia );
00552 rec = dia->record();
00553 delete dia;
00554 }
00555 else
00556 rec = queuedDialog()->record();
00557
00558 Id id = m_transactions[ tid ];
00559 if (result == QDialog::Accept )
00560 {
00561 m_doneIds.insert( is, rec );
00562 m_done.insert( tid, id );
00563 }
00564
00565 m_transactions.remove( tid );
00566 m_ids.remove( id );
00567
00568
00569 if (status == QDialog::Accept )
00570 emit m_signal->accepted( tid );
00571 else
00572 emit m_signal->rejected( tid );
00573
00574 emit m_signal->done( result, tid );
00575
00576 next( 0 );
00577 }
00578
00582 template<class Dialog, class Record, typename Id>
00583 void OModalHelper<Dialog, Record, Id>::next( TransactionID tid)
00584 {
00585 if (m_mode == New )
00586 return;
00587
00588 if (! (m_transactions.count() ) )
00589 {
00590 m_controler->setTransactionID( 0 );
00591 queuedDialog()->setRecord( 0, 0 );
00592 return;
00593 }
00594
00595 int next;
00596 Record rec;
00597
00598
00599 Dialog *dia = static_cast<Dialog*>( queuedDialog()->centerDialog() );
00600 rec = dia->record();
00601 m_ids.replace( m_transactions[tid], rec );
00602
00603 rec = nextRecord( tid, next );
00604 queuedDialog()->setRecord( next, m_transactions.count() );
00605 dia->setRecord( rec );
00606
00607 m_controler->setTransactionID( tid );
00608 }
00609
00613
00614
00615
00616
00617 template<class Dialog, class Record, typename Id>
00618 void OModalHelper<Dialog, Record, Id>::prev( TransactionID tid )
00619 {
00620 if (m_mode == New )
00621 return;
00622
00623 if (! (m_transactions.count()) )
00624 {
00625 m_controler->setTransactionID( 0 );
00626 queuedDialog()->setRecord( 0, 0 );
00627 return;
00628 }
00629
00630 int prev;
00631 Record rec;
00632
00633
00634 Dialog *dia = static_cast<Dialog*>( queuedDialog()->centerDialog() );
00635 rec = dia->record();
00636 m_ids.replace( m_transactions[tid], rec );
00637
00638 rec = prevRecord( tid, prev );
00639 queuedDialog()->setRecord( prev, m_transactions.count() );
00640 dia->setRecord( rec );
00641
00642 m_controler->setTransactionID( tid );
00643 }
00644
00648 template<class Dialog, class Record, typename Id>
00649 Record OModalHelper<Dialog, Record, Id>::nextRecord( TransactionID &tid, int &po )
00650 {
00651
00652
00653
00654 Record rec;
00655 TransactionMap::Iterator it;
00656 if (!tid )
00657 {
00658 po = 1;
00659 TransactionMap::Iterator it = m_transactions.begin();
00660 }
00661 else
00662 {
00663 po = pos( tid );
00664
00665 if ( po == m_transactions.count() )
00666 {
00667 po = 1;
00668 it = m_transactions.begin();
00669 }
00670 else
00671 {
00672
00673 it = m_transactions.find( tid );
00674 ++it; ++po;
00675 }
00676 }
00677
00678 tid = it.key();
00679 rec = m_ids[ tid ];
00680 return rec;
00681 }
00682
00686 template<class Dialog, class Record, typename Id>
00687 Record OModalHelper<Dialog, Record, Id>::prevRecord( TransactionID& tid, int& pos )
00688 {
00689
00690
00691
00692 Record rec;
00693 TransactionMap::Iterator it;
00694 if (!tid )
00695 {
00696 po = 1;
00697 TransactionMap::Iterator it = m_transactions.begin();
00698 }
00699 else
00700 {
00701 po = pos( tid );
00702
00703 if ( po == 1 )
00704 {
00705 po = m_transactions.count();
00706 it = m_transactions.end();
00707 --it;
00708 }
00709 else
00710 {
00711
00712 it = m_transactions.find( tid );
00713 --it; --po;
00714 }
00715 }
00716
00717 tid = it.key();
00718 rec = m_ids[ tid ];
00719 return rec;
00720 }
00721
00725 template<class Dialog, class Record, typename Id>
00726 int OModalHelper<Dialog, Record, Id>::pos( TransactionID id)const
00727 {
00728 int i = 1;
00729 for ( TransactionMap::ConstIterator it = m_transactions.begin(); it != m_transactions.end(); ++it, i++ )
00730 if ( it.key() == id )
00731 return i;
00732
00733
00734 return 0;
00735 }
00736
00740 template<class Dialog, class Record, typename Id>
00741 Dialog* OModalHelper<Dialog, Record, Id>::newDialogRecord( const Record& rec )
00742 {
00743 Dialog* dia = new Dialog;
00744 dia->setRecord( rec );
00745 dia->setDisabled( m_disabled );
00746
00747 QObject::connect(dia, SIGNAL(done(int) ),
00748 m_controler, SLOT(done(int) ) );
00749
00750
00751 dia->show();
00752 }
00753
00754 template<class Record, class Dialog, typename Id>
00755 OModalHelperDialog* OModalHelper<Record, Dialog, Id>::queuedDialog()const
00756 {
00757 if (!m_dialog )
00758 {
00759 m_dialog = new OModalHelperDialog;
00760 m_dialog->setEnabled( m_disabled );
00761
00762 QObject::connect(m_dialog, SIGNAL(done(int) ),
00763 m_controler, SLOT(done(int) ) );
00764 QObject::connect(m_dialog, SIGNAL(next() ),
00765 m_controler, SLOT(next() ) );
00766 QObject::connect(m_dialog, SIGNAL(prev() ),
00767 m_controler, SLOT(prev() ) );
00768 }
00769 return m_dialog;
00770 }
00771
00772 };
00773
00774 #endif