summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/big-screen/omodalhelper.cpp7
-rw-r--r--libopie/big-screen/omodalhelper.h377
2 files changed, 346 insertions, 38 deletions
diff --git a/libopie/big-screen/omodalhelper.cpp b/libopie/big-screen/omodalhelper.cpp
index e3d1c70..c5a47b3 100644
--- a/libopie/big-screen/omodalhelper.cpp
+++ b/libopie/big-screen/omodalhelper.cpp
@@ -75,9 +75,9 @@ QDialog* OModalHelperControler::dialog()const {
75void OModalHelperControler::done( int result ) { 75void OModalHelperControler::done( int result ) {
76 if ( sender() && !sender()->isA("OModalQueuedDialog") ) 76 if ( sender() && !sender()->isA("OModalQueuedDialog") )
77 m_dia = static_cast<QDialog*>( sender() ); 77 m_dia = static_cast<QDialog*>( sender() );
78 78
79 m_base->done( m_id ); 79 m_base->done( result, m_id );
80} 80}
81 81
82void OModalHelperControler::next() { 82void OModalHelperControler::next() {
83 m_base->next( m_id ); 83 m_base->next( m_id );
@@ -154,7 +154,12 @@ void OModalQueuedDialog::setRecord( int record, int count ) {
154 return; 154 return;
155 }else 155 }else
156 show(); 156 show();
157 157
158 if ( count > 1 )
159 m_bar->show();
160 else
161 m_bar->hide();
162
158 m_bar->setText( tr("Editing record %1 out of %2", 163 m_bar->setText( tr("Editing record %1 out of %2",
159 "Shows the current edited record out of an array of records").arg( record ). arg( count ) ); 164 "Shows the current edited record out of an array of records").arg( record ). arg( count ) );
160} 165}
diff --git a/libopie/big-screen/omodalhelper.h b/libopie/big-screen/omodalhelper.h
index bc20d10..78a2ac9 100644
--- a/libopie/big-screen/omodalhelper.h
+++ b/libopie/big-screen/omodalhelper.h
@@ -32,17 +32,18 @@
32#include <qdialog.h> 32#include <qdialog.h>
33#include <qwidget.h> 33#include <qwidget.h>
34#include <qvaluelist.h> 34#include <qvaluelist.h>
35#include <qmap.h> 35#include <qmap.h>
36#include <qvariant.h>
36 37
37typedef int TransactionID; 38typedef int TransactionID;
38 39
39class OModalHelperControler; 40class OModalHelperControler;
40class OModalHelperSignal; 41class OModalHelperSignal;
41class QDialog; 42class QDialog;
42 43
43struct OModalHelperBase { 44struct OModalHelperBase {
44 virtual void done( TransactionID ) = 0; 45 virtual void done( int status, TransactionID ) = 0;
45 virtual void next( TransactionID ) = 0; 46 virtual void next( TransactionID ) = 0;
46 virtual void prev( TransactionID ) = 0; 47 virtual void prev( TransactionID ) = 0;
47}; 48};
48 49
@@ -83,8 +84,10 @@ public:
83 84
84 bool handles( Id id)const; 85 bool handles( Id id)const;
85 TransactionID transactionID( Id id)const; 86 TransactionID transactionID( Id id)const;
86 87
88 void suspend( bool = true );
89
87 void cancel(); 90 void cancel();
88 void cancel( TransactionID ); 91 void cancel( TransactionID );
89 92
90 void connectDone( QObject* rec, const char* slot ); 93 void connectDone( QObject* rec, const char* slot );
@@ -92,19 +95,21 @@ public:
92 void connectRejected( QObject* rec, const char* slot ); 95 void connectRejected( QObject* rec, const char* slot );
93 96
94 TransactionID handle( Id id, const Record& rec = Record() ); 97 TransactionID handle( Id id, const Record& rec = Record() );
95 98
96 void edited( TransactionID, int what, const QString& data ); 99 void edited( Id, int what, const QVariant& data );
97 100
98 Record record( TransactionID )const; 101 Record record( TransactionID )const;
99 RecordList done()const; 102 RecordList recordsDone()const;
100private: 103private:
101 virtual void done( TransactionID ); 104 virtual void done( int, TransactionID );
102 virtual void next( TransactionID ); 105 virtual void next( TransactionID );
103 virtual void prev( TransactionID ); 106 virtual void prev( TransactionID );
104 107
105 Record nextRecord( TransactionID, int * )const; 108 Record nextRecord( TransactionID &, int & )const;
106 Record prevRecord( TransactionID, int * )const; 109 Record prevRecord( TransactionID &, int & )const;
110 int pos( TransactionID )const;
111 Dialog* newDialogRecord( const Record& );
107 112
108private: 113private:
109 OModalHelperDialog *queuedDialog()const; // generate or recycle 114 OModalHelperDialog *queuedDialog()const; // generate or recycle
110 OModalHelperDialog *m_dialog; 115 OModalHelperDialog *m_dialog;
@@ -115,8 +120,9 @@ private:
115 TransactionMap m_transactions; // activate transactions 120 TransactionMap m_transactions; // activate transactions
116 TransactionMap m_done; // done and waiting for getting picked 121 TransactionMap m_done; // done and waiting for getting picked
117 DialogMap m_editing; // only used for New Mode 122 DialogMap m_editing; // only used for New Mode
118 enum Mode m_mode; // the mode we're in 123 enum Mode m_mode; // the mode we're in
124 bool m_disabled :1;
119}; 125};
120 126
121 127
122 128
@@ -204,12 +210,12 @@ private:
204 * @param parent The parent QObject of this helper. 210 * @param parent The parent QObject of this helper.
205 */ 211 */
206template<class Dialog, class Record, typename Id> 212template<class Dialog, class Record, typename Id>
207OModalHelper<Dialog, Record, Id>::OModalHelper( enum Mode mode, QObject* parent ) { 213OModalHelper<Dialog, Record, Id>::OModalHelper( enum Mode mode, QObject* parent ) {
214 m_disabled = false;
208 m_mode = mode; 215 m_mode = mode;
209 m_signal = new OModalHelperSignal( this, parent ); 216 m_signal = new OModalHelperSignal( this, parent );
210 m_controler = new OModalHelperControler( this, m_signal ); 217 m_controler = new OModalHelperControler( this, m_signal );
211
212} 218}
213 219
214 220
215/** 221/**
@@ -239,17 +245,36 @@ bool OModalHelper<Dialog, Record, Id>::handles( Id id )const {
239 * just like handles( Id ) but returns the TransactionId 245 * just like handles( Id ) but returns the TransactionId
240 */ 246 */
241template<class Dialog, class Record, typename Id> 247template<class Dialog, class Record, typename Id>
242TransactionID OModalHelper<Dialog, Record, Id>::transactionID( Id id)const { 248TransactionID OModalHelper<Dialog, Record, Id>::transactionID( Id id)const {
243 if ( m_transactions.isEmpty() ) 249 if ( m_transactions.isEmpty() || !m_ids.contains( id ) )
244 return false; 250 return 0;
245 251
246 TransactionMap::ConstIterator it = m_transactions.begin(); 252 TransactionMap::ConstIterator it = m_transactions.begin();
247 for ( ; it != m_transactions.end(); ++it ) 253 for ( ; it != m_transactions.end(); ++it )
248 if ( it.data() == id ) 254 if ( it.data() == id )
249 return true; 255 return it.key();
250 256
251 return false; 257 return 0;
258}
259
260/**
261 * If you're requested to flush your data and you do not want
262 * to call cancel with this method you can disable and enabled
263 * all dialogs.
264 * The state gets saved so if you want to handle a new record the dialog
265 * will be disabled as well.
266 *
267 * @param sus If true setDisabled(TRUE) will be called otherwise FALSE
268 */
269template<class Dialog, class Record, typename Id>
270void OModalHelper<Dialog, Record, Id>::suspend(bool sus) {
271 m_disabled = sus;
272 if (m_mode == New )
273 for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it )
274 it.key()->setDisabled( sus );
275 else if (m_dialog )
276 queuedDialog()->setDisabled( sus );
252} 277}
253 278
254/** 279/**
255 * Cancel will cancel all current operations and clear the list 280 * Cancel will cancel all current operations and clear the list
@@ -267,13 +292,14 @@ void OModalHelper<Dialog, Record, Id>::cancel() {
267 /* and hide the queue dialog if present */ 292 /* and hide the queue dialog if present */
268 if (m_mode == New && !m_editing.isEmpty() ) { 293 if (m_mode == New && !m_editing.isEmpty() ) {
269 for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it ) 294 for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it )
270 delete it.key(); 295 delete it.key();
296
271 m_editing.clear(); 297 m_editing.clear();
272 }else if (m_dialog ) 298 }else if (m_dialog )
273 queuedDialog()->setRecord( 0, 0 ); 299 queuedDialog()->setRecord( 0, 0 );
274 300
275 m_controler->setTransactionID( -1 ); 301 m_controler->setTransactionID( 0 );
276} 302}
277 303
278 304
279/** 305/**
@@ -294,36 +320,18 @@ void OModalHelper::cancel( TransactionID tid ) {
294 delete it.key(); 320 delete it.key();
295 it = m_editing.remove( it ); 321 it = m_editing.remove( it );
296 break; 322 break;
297 } 323 }
298 else if ( m_transactions.contains( tid ) ) {
299 /* need to stop editing from the queue block */
300 /* if we're currently editing actiavte the previous */
301#if 0
302 if (tid == m_controler->transactionID() ) {
303 324
304 }
305#endif
306 /* now either activate the previous again or hide */
307 if (! m_transactions.count() -1 )
308 queuedDialog()->setRecord( 0, 0 );
309 else {
310 int pos;
311 Record rec = prevRecord( tid, &pos );
312 static_cast<Dialog*>( queuedDialog()->centerDialog() )->setRecord( rec );
313 queuedDialog()->setRecord( pos, m_transactions.count() );
314 m_controler->setTransactionID( tid );
315 }
316 }
317 /* now remove from the various maps done and currently editing map*/ 325 /* now remove from the various maps done and currently editing map*/
318 if (m_transactions.contains( tid ) ) 326 if (m_transactions.contains( tid ) )
319 m_ids.remove( m_transactions[tid] ); 327 m_ids.remove( m_transactions[tid] );
320 if (m_done.contains( tid ) ) 328 if (m_done.contains( tid ) )
321 m_doneIds.remove( m_done[tid ] ); 329 m_doneIds.remove( m_done[tid ] );
322
323
324 m_done.remove( tid ); 330 m_done.remove( tid );
325 m_transactions.remove( tid ); 331 m_transactions.remove( tid );
332
333 next( 0 );
326} 334}
327 335
328/** 336/**
329 * Connect to the done Signal. SIGNAL( done(int, TransactionID ) ) 337 * Connect to the done Signal. SIGNAL( done(int, TransactionID ) )
@@ -382,24 +390,319 @@ void OModalHelper<Dialog, Record, Id>::connectRejected( QObject* rec, const char
382 */ 390 */
383template<class Dialog, class Record, typename Id> 391template<class Dialog, class Record, typename Id>
384TransactionID OModalHelper<Dialog, Record, Id>::handle( Id id, const Record& rec ) { 392TransactionID OModalHelper<Dialog, Record, Id>::handle( Id id, const Record& rec ) {
385 static TransactionID t_id = 0; 393 static TransactionID t_id = 0;
386 t_id++;
387 /* 394 /*
388 *this method consists out of two parts divided each into New and Queued Mode. 395 *this method consists out of two parts divided each into New and Queued Mode.
389 * Either we have the dialog already, in this case we need to highlight the widget 396 * Either we have the dialog already, in this case we need to highlight the widget
390 * Or we need to add it. 397 * Or we need to add it.
391 */ 398 */
392 TransactionID tid = 0; 399 TransactionID tid = 0;
393 /* we already have the record lets see if it was done or not */ 400 /* we already have the record lets see if it was done or not */
394 if ( m_ids.contains( id ) ) { 401 if ( !(tid = transactionID( id ) ) ) {
402 if (m_mode == New ) {
403 /* lets find the dialog and show it need to reverse map*/
404 for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it )
405 if ( it.data() == tid )
406 it.key()->show();
407 }else if (m_controler->transactionID() != tid ) {
408 int po = pos( tid );
409 m_controler->setTransactionID( tid );
410 static_cast<Dialog*>( queuedDialog()->centerDialog() )->setRecord( m_ids[ m_transactions[tid] ] );
411 queuedDialog()->setRecord( po, m_transactions.count() );
412 }
413 }else {
414 tid = ++t_id;
415 m_transactions.insert( tid, id );
416 m_ids.insert( id, rec );
417
418 if (m_mode == New )
419 m_editing.insert( newDialogRecord( rec ), tid );
420 else{
421 m_controler->setTransactionID( tid );
422 static_cast<Dialog*>( queuedDialog()->centerDialog() )->setRecord( rec );
423 queuedDialog()->setRecord( m_transactions.count(), m_transactions.count() );
424 }
425 }
426 return tid;
427}
395 428
429/**
430 * The goal of this helper is to help you to create non blocking
431 * GUIs. In the example of the todolist you can have the edit dialog
432 * but still change the priority or completion inline even if you currently
433 * edit the record.
434 * Your Dialog needs to have a Method setData(int,const QVariant& ) which will be called
435 * in these cases.
436 * If you edit anything while a record is edited call this function to merge the
437 * change in. Note if the record is not handled here we will ignore the request
438 *
439 */
440template<class Dialog, class Record, typename Id>
441void OModalHelper<Dialog, Record, Id>::edited( Id id, int what, const QVariant& data ) {
442 int tid;
443 if (!( tid = transactionID( id ) ) )
444 return;
445
446 if (m_mode == New ) {
447 for (DialogMap::Iterator it= m_editing.begin(); it != m_editing.end(); ++it )
448 if ( it.data() == tid )
449 it.key()->setData( what, data );
450 }else{
451 int po = pos( tid );
452 Dialog* dia = static_cast<Dialog*>( queuedDialog()->centerDialog() );
453 dia->setRecord( m_ids[id] );
454 dia->setData( what, data );
455 queuedDialog()->setRecord( pos, m_transactions.count() );
456 }
457}
458
459/**
460 * This functions either returns the unedited record the done record
461 * or a new empty Record using Record().
462 * If a done record is retrieved all traces are removed inside this class. This
463 * is what was called popping a record. This means when you call this function
464 * with the same TransactionID an Empty record is retrieved.
465 *
466 */
467template<class Dialog, class Record, typename Id>
468Record OModalHelper<Dialog, Record, Id>::record( TransactionID tid)const {
469 if (m_transactions.contains( tid ) )
470 return m_ids[ m_transactions[tid] ];
471 else if (m_done.contains( tid ) ) {
472 Record rec = m_doneIds[ m_done[ tid] ];
473 m_doneIds.remove( m_done[ tid ] );
474 m_done.remove( tid );
475 return rec;
476 }else
477 return Record();
478}
479
480/**
481 * Returns all done Records and removes all references to them internally. A 2nd call to this will
482 * only contain done record that where edited past the point
483 */
484template<class Dialog, class Record, typename Id>
485OModalHelper<Dialog,Record,Id>::RecordList OModalHelper<Dialog, Record, Id>::recordsDone()const {
486 RecordList list;
487
488 for (IdMap::ConstIterator it = m_doneIds.begin(); it != m_doneIds.end(); ++it )
489 list.append( it.data() );
490
491 /* clean up */
492 m_done.clear();
493 m_doneIds.clear();
494
495 return list;
496}
497
498
499/**
500 * @internal
501 */
502template<class Dialog, class Record, typename Id>
503void OModalHelper<Dialog, Record, Id>::done( int status, TransactionID tid) {
504/* If we're in New mode the transaction Id does not count */
505 Record rec;
506
507 if (m_mode == New ) {
508 Dialog *dia = static_cast<Dialog*>( m_controler->dialog() );
509 m_controler->setTransactionID( 0 ); // set the internal dialog to 0l again
510 tid = m_editing[ dia ];
511 m_editing.remove( dia );
512 rec = dia->record();
513 delete dia;
514 }else
515 rec = queuedDialog()->record();
516
517 Id id = m_transactions[ tid ];
518 if (result == QDialog::Accept ) {
519 m_doneIds.insert( is, rec );
520 m_done.insert( tid, id );
396 } 521 }
397 522
398 /* fall through if the record is in the done list */ 523 m_transactions.remove( tid );
399 tid = t_id; 524 m_ids.remove( id );
525
400 526
527 if (status == QDialog::Accept )
528 emit m_signal->accepted( tid );
529 else
530 emit m_signal->rejected( tid );
401 531
402 return; 532 emit m_signal->done( result, tid );
533
534 next( 0 );
535}
536
537/**
538 * @internal
539 */
540template<class Dialog, class Record, typename Id>
541void OModalHelper<Dialog, Record, Id>::next( TransactionID tid) {
542 if (m_mode == New )
543 return;
544
545 if (! (m_transactions.count() ) ) {
546 m_controler->setTransactionID( 0 );
547 queuedDialog()->setRecord( 0, 0 );
548 return;
549 }
550
551 int next;
552 Record rec;
553
554 /* save the maybe edited record before switching */
555 Dialog *dia = static_cast<Dialog*>( queuedDialog()->centerDialog() );
556 rec = dia->record();
557 m_ids.replace( m_transactions[tid], rec );
558
559 rec = nextRecord( tid, next );
560 queuedDialog()->setRecord( next, m_transactions.count() );
561 dia->setRecord( rec );
562
563 m_controler->setTransactionID( tid ); // was changed during the next call
564}
565
566/**
567 * @internal
568 */
569/*
570 * code duplication should create a template fcuntion
571 * which takes a pointer to a function ( next, prev ) function
572 */
573template<class Dialog, class Record, typename Id>
574void OModalHelper<Dialog, Record, Id>::prev( TransactionID tid ) {
575 if (m_mode == New )
576 return;
577
578 if (! (m_transactions.count()) ) {
579 m_controler->setTransactionID( 0 );
580 queuedDialog()->setRecord( 0, 0 );
581 return;
582 }
583
584 int prev;
585 Record rec;
586
587 /* save the maybe edited record before switching */
588 Dialog *dia = static_cast<Dialog*>( queuedDialog()->centerDialog() );
589 rec = dia->record();
590 m_ids.replace( m_transactions[tid], rec );
591
592 rec = prevRecord( tid, prev );
593 queuedDialog()->setRecord( prev, m_transactions.count() );
594 dia->setRecord( rec );
595
596 m_controler->setTransactionID( tid ); // was changed during the next call
597}
598
599/**
600 * @internal
601 */
602template<class Dialog, class Record, typename Id>
603Record OModalHelper<Dialog, Record, Id>::nextRecord( TransactionID &tid, int &po ) {
604 /* if tid is == 0 we will take the first one */
605 /* pos starts at 1 here */
606 /* we know we're only called if there are records */
607 Record rec;
608 TransactionMap::Iterator it;
609 if (!tid ) {
610 po = 1;
611 TransactionMap::Iterator it = m_transactions.begin();
612 }else{
613 po = pos( tid );
614 /* if it is the last take the first as next */
615 if ( po == m_transactions.count() ) {
616 po = 1;
617 it = m_transactions.begin();
618 }else {
619 /* we know we're not the last and there is one after us */
620 it = m_transactions.find( tid );
621 ++it; ++po;
622 }
623 }
624
625 tid = it.key();
626 rec = m_ids[ tid ];
627 return rec;
628}
629
630/**
631 * @internal
632 */
633template<class Dialog, class Record, typename Id>
634Record OModalHelper<Dialog, Record, Id>::prevRecord( TransactionID& tid, int& pos ) {
635 /* if tid is == 0 we will take the first one */
636 /* pos starts at 1 here */
637 /* we know we're only called if there are records */
638 Record rec;
639 TransactionMap::Iterator it;
640 if (!tid ) {
641 po = 1;
642 TransactionMap::Iterator it = m_transactions.begin();
643 }else{
644 po = pos( tid );
645 /* if it is the last take the first as next */
646 if ( po == 1 ) {
647 po = m_transactions.count();
648 it = m_transactions.end();
649 --it;
650 }else {
651 /* we know we're not the first and there is one before us */
652 it = m_transactions.find( tid );
653 --it; --po;
654 }
655 }
656
657 tid = it.key();
658 rec = m_ids[ tid ];
659 return rec;
660}
661
662/**
663 * @internal
664 */
665template<class Dialog, class Record, typename Id>
666int OModalHelper<Dialog, Record, Id>::pos( TransactionID id)const {
667 int i = 1;
668 for ( TransactionMap::ConstIterator it = m_transactions.begin(); it != m_transactions.end(); ++it, i++ )
669 if ( it.key() == id )
670 return i;
671
672
673 return 0;
674}
675
676/**
677 * @internal
678 */
679template<class Dialog, class Record, typename Id>
680Dialog* OModalHelper<Dialog, Record, Id>::newDialogRecord( const Record& rec ) {
681 Dialog* dia = new Dialog;
682 dia->setRecord( rec );
683 dia->setDisabled( m_disabled );
684
685 QObject::connect(dia, SIGNAL(done(int) ),
686 m_controler, SLOT(done(int) ) );
687
688 /* FIXME big screen QPEApplication needs fixed*/
689 dia->show();
690}
691
692template<class Record, class Dialog, typename Id>
693OModalHelperDialog* OModalHelper<Record, Dialog, Id>::queuedDialog()const{
694 if (!m_dialog ) {
695 m_dialog = new OModalHelperDialog;
696 m_dialog->setEnabled( m_disabled );
697
698 QObject::connect(m_dialog, SIGNAL(done(int) ),
699 m_controler, SLOT(done(int) ) );
700 QObject::connect(m_dialog, SIGNAL(next() ),
701 m_controler, SLOT(next() ) );
702 QObject::connect(m_dialog, SIGNAL(prev() ),
703 m_controler, SLOT(prev() ) );
704 }
705 return m_dialog;
403} 706}
404 707
405#endif 708#endif