Diffstat (limited to 'libopie/big-screen/omodalhelper.h') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libopie/big-screen/omodalhelper.h | 708 |
1 files changed, 0 insertions, 708 deletions
diff --git a/libopie/big-screen/omodalhelper.h b/libopie/big-screen/omodalhelper.h deleted file mode 100644 index 78a2ac9..0000000 --- a/libopie/big-screen/omodalhelper.h +++ b/dev/null @@ -1,708 +0,0 @@ -/* - =. This file is part of the OPIE Project - .=l. Copyright (c) 2003 hOlgAr <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 HAZE_OMODAL_HELPER_H -#define HAZE_OMODAL_HELPER_H - -#include <qdialog.h> -#include <qwidget.h> -#include <qvaluelist.h> -#include <qmap.h> -#include <qvariant.h> - -typedef int TransactionID; - -class OModalHelperControler; -class OModalHelperSignal; -class QDialog; - -struct OModalHelperBase { - virtual void done( int status, TransactionID ) = 0; - virtual void next( TransactionID ) = 0; - virtual void prev( TransactionID ) = 0; -}; - -/** - * Modality sucks! ;) But it is easy to work with - * do exec() on a dialog and you know everything is funky. - * You only need to have one Dialog loaded and so on. - * This class helps you to work like with modality and help - * you to keep things in sync - * It's a template class but it sends signals once one Item is ready - * the signals contains the status and id of the item and then you - * need fetch it. - * Handled Records will stay available until the first call to retrieve - * either the record via the TransactionID or via the QValueList<Record>. Note - * that most functions do not take handled records into account. - * Also if you edit an record external you can tell this class and it'll - * call the merge() function of your widget to maybe merge in these changes. - * It also supports multiple modes. Either it can create new dialogs - * for each item or it can queue them depending on your usage. But it is - * so smart that if only one item is shown that the queue bar is not shown - * See the example for simple usage. - * - * @short helps to life without modaility - * @author hOlgAr - * @version 0.01 - */ -template<class Dialog, class Record, typename Id = int> -class OModalHelper : private OModalHelperBase{ - friend class OModalHelperSignal; - friend class OModalHelperControler; -public: - typedef QValueList<Record> RecordList; - typedef QMap<Id, Record> IdMap; - typedef QMap<TransactionID, Id> TransactionMap; - typedef QMap<QDialog*, TransactionID> DialogMap - enum Mode { Queue, New }; - OModalHelper(enum Mode mode, QObject* parnet ); - - bool handles( Id id)const; - TransactionID transactionID( Id id)const; - - void suspend( bool = true ); - - void cancel(); - void cancel( TransactionID ); - - void connectDone( QObject* rec, const char* slot ); - void connectAccepted( QObject* rec, const char* slot ); - void connectRejected( QObject* rec, const char* slot ); - - TransactionID handle( Id id, const Record& rec = Record() ); - - void edited( Id, int what, const QVariant& data ); - - Record record( TransactionID )const; - RecordList recordsDone()const; -private: - virtual void done( int, TransactionID ); - virtual void next( TransactionID ); - virtual void prev( TransactionID ); - - Record nextRecord( TransactionID &, int & )const; - Record prevRecord( TransactionID &, int & )const; - int pos( TransactionID )const; - Dialog* newDialogRecord( const Record& ); - -private: - OModalHelperDialog *queuedDialog()const; // generate or recycle - OModalHelperDialog *m_dialog; - OModalHelperSignal *m_signal; // our signal - OModalHelperControler *m_controler; - IdMap m_ids; // maps ids (uids) to a record - IdMap m_doneIds; - TransactionMap m_transactions; // activate transactions - TransactionMap m_done; // done and waiting for getting picked - DialogMap m_editing; // only used for New Mode - enum Mode m_mode; // the mode we're in - bool m_disabled :1; -}; - - - -/* ### FIXME use namespace with Qt3 */ - -/* - * A note on flow. The Signal is used for QT Signals when - * a record is done. - * There is either one controler and this controler slot will - * be connected to a dialog signal. - * In Queue we get the next and prev signals and call the Helper. - * this then changes the Record of the dialog and sets the transactionId - * of the controler. - * For the new mode - * - */ - -class OModalHelperSignal : public QObject { - Q_OBJECT -public: - OModalHelperSignal(OModalHelperBase* base, QObject* parent); - ~OModalHelperSignal(); - -signals: - done( int status, TransactionID transaction ); - accepted( TransactionID transaction ); - rejected( TransactionID transaction ); - -private: - OModalHelperBase* m_base; -}; - - -class OModalHelperControler : public QObject { - Q_OBJECT -public: - OModalHelperControler( OModalHelperBase* , QObject* parent); - virtual TransactionID transactionID()const; - void setTransactionID( TransactionID id ); - QDialog* dialog()const; - -public slots: - virtual void done(int result ); - virtual void next(); - virtual void prev(); -private: - QDialog *m_dia; - TransactionID m_id; - OModalHelperBase *m_base; -} - -struct OModalQueueBar; -class OModalQueuedDialog : public QDialog { - Q_OBJECT -public: - OModalQueuedDialog(QDialog *mainWidget); - ~OModalQueuedDialog(); - - QDialog* centerDialog()const; - - void setQueueBarEnabled( bool = true ); - void setRecord( int record, int count ); - -signals: - void next(); - void prev(); - -private: - OModalQueueBar *m_bar; - QDialog *m_center; -}; - - -/* - * Tcpp Template Implementation - */ - -/** - * This is the simple Template c'tor. It takes the mode - * this helper should operate in and the parent object. - * This helper will be deleted when the parent gets deleted - * or you delete it yourself. - * - * @param mode The mode this dialog should be in - * @param parent The parent QObject of this helper. - */ -template<class Dialog, class Record, typename Id> -OModalHelper<Dialog, Record, Id>::OModalHelper( enum Mode mode, QObject* parent ) { - m_disabled = false; - m_mode = mode; - m_signal = new OModalHelperSignal( this, parent ); - m_controler = new OModalHelperControler( this, m_signal ); -} - - -/** - * This functions looks for your record and sees if it is - * handled with this helper. Note that done records - * will not be returned. - * - * @return true if the record is currenlty edited otherwise false - * - * @param Id The id which might be handled - */ -template<class Dialog, class Record, typename Id> -bool OModalHelper<Dialog, Record, Id>::handles( Id id )const { - if ( m_transactions.isEmpty() ) - return false; - - TransactionMap::ConstIterator it = m_transactions.begin(); - for ( ; it != m_transactions.end(); ++it ) - if ( it.data() == id ) - return true; - - return false; -} - - -/** - * just like handles( Id ) but returns the TransactionId - */ -template<class Dialog, class Record, typename Id> -TransactionID OModalHelper<Dialog, Record, Id>::transactionID( Id id)const { - if ( m_transactions.isEmpty() || !m_ids.contains( id ) ) - return 0; - - TransactionMap::ConstIterator it = m_transactions.begin(); - for ( ; it != m_transactions.end(); ++it ) - if ( it.data() == id ) - return it.key(); - - return 0; -} - -/** - * If you're requested to flush your data and you do not want - * to call cancel with this method you can disable and enabled - * all dialogs. - * The state gets saved so if you want to handle a new record the dialog - * will be disabled as well. - * - * @param sus If true setDisabled(TRUE) will be called otherwise FALSE - */ -template<class Dialog, class Record, typename Id> -void OModalHelper<Dialog, Record, Id>::suspend(bool sus) { - m_disabled = sus; - if (m_mode == New ) - for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it ) - it.key()->setDisabled( sus ); - else if (m_dialog ) - queuedDialog()->setDisabled( sus ); -} - -/** - * Cancel will cancel all current operations and clear the list - * of done operations as well. - * This also clears all done operations you did not popped - */ -template<class Dialog, class Record, typename Id> -void OModalHelper<Dialog, Record, Id>::cancel() { - m_ids.clear(); - m_doneIds.clear(); - m_done.clear(); - m_transactions.clear(); - - /* we also need to remove the QDialogs */ - /* and hide the queue dialog if present */ - if (m_mode == New && !m_editing.isEmpty() ) { - for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it ) - delete it.key(); - - m_editing.clear(); - }else if (m_dialog ) - queuedDialog()->setRecord( 0, 0 ); - - m_controler->setTransactionID( 0 ); -} - - -/** - * This cancels editing of the record behind the Transaction Number - * Note that if editing is already done it will also be removed from this list - */ -template<class Dialog, class Record, typename Id> -void OModalHelper::cancel( TransactionID tid ) { - /* wrong tid */ - if (!m_transactions.contains( tid ) && !m_done.contains( tid) ) - return; - - if (m_mode == New ) - /* reverse map eek */ - for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it ) - if ( it.data() == tid ) { - it.key()->hide(); - delete it.key(); - it = m_editing.remove( it ); - break; - } - - /* now remove from the various maps done and currently editing map*/ - if (m_transactions.contains( tid ) ) - m_ids.remove( m_transactions[tid] ); - if (m_done.contains( tid ) ) - m_doneIds.remove( m_done[tid ] ); - m_done.remove( tid ); - m_transactions.remove( tid ); - - next( 0 ); -} - -/** - * Connect to the done Signal. SIGNAL( done(int, TransactionID ) ) - * This signal gets emitted whenever a Record was accepted or rejected - * - * @param rec The object where the slot belongs to - * @param slot The slot which should be called. See the needed parameter above - */ -template<class Dialog, class Record, typename Id> -void OModalHelper<Dialog, Record, Id>::connectDone( QObject* rec, const char* slot ) { - QObject::connect(m_signal, SIGNAL(done(int, TransactionID) ), - rec, slot ); -} - -/** - * Connect to the accepted Signal. SIGNAL( accepted(TransactionID ) ) - * This signal gets emitted whenever a Record was accepted - * - * @param rec The object where the slot belongs to - * @param slot The slot which should be called. See the needed parameter above - */ -template<class Dialog, class Record, typename Id> -void OModalHelper<Dialog, Record, Id>::connectAccepted( QObject* rec, const char* slot ) { - QObject::connect(m_signal, SIGNAL(accepted(TransactionID) ), - rec, slot ); -} - -/** - * Same as the accepted method but this one gets emitted if the dialog - * got rejected. - * SIGNAL( rejected(TransactionID) ) - * - * @param rec The QObject of the slot - * @param slot The slot make sure the signature is correct - */ -template<class Dialog, class Record, typename Id> -void OModalHelper<Dialog, Record, Id>::connectRejected( QObject* rec, const char* slot ) { - QObject::connect(m_signal, SIGNAL(rejected(TransactionID) ), - rec, slot ); -} - -/** - * Tell the helper to handle a record. If the record is currently handled - * it will be made active. - * Already handled record which are waiting getting popped are not taken into account - * Otherwise this helpers make the record editable. - * The record supplied needs to have a valid copy operator and constructor. - * In the case where the record is already present the parameter gets discarded. - * If you want the new record to be taken you need to cancel the Transaction first - * - * @param id The Identification of the Record. For PIM it would uid() - * @param rec The record we want to be edited - * - * @returns This functions returns the TransactionId assigned to the record - * - */ -template<class Dialog, class Record, typename Id> -TransactionID OModalHelper<Dialog, Record, Id>::handle( Id id, const Record& rec ) { - static TransactionID t_id = 0; - /* - *this method consists out of two parts divided each into New and Queued Mode. - * Either we have the dialog already, in this case we need to highlight the widget - * Or we need to add it. - */ - TransactionID tid = 0; - /* we already have the record lets see if it was done or not */ - if ( !(tid = transactionID( id ) ) ) { - if (m_mode == New ) { - /* lets find the dialog and show it need to reverse map*/ - for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it ) - if ( it.data() == tid ) - it.key()->show(); - }else if (m_controler->transactionID() != tid ) { - int po = pos( tid ); - m_controler->setTransactionID( tid ); - static_cast<Dialog*>( queuedDialog()->centerDialog() )->setRecord( m_ids[ m_transactions[tid] ] ); - queuedDialog()->setRecord( po, m_transactions.count() ); - } - }else { - tid = ++t_id; - m_transactions.insert( tid, id ); - m_ids.insert( id, rec ); - - if (m_mode == New ) - m_editing.insert( newDialogRecord( rec ), tid ); - else{ - m_controler->setTransactionID( tid ); - static_cast<Dialog*>( queuedDialog()->centerDialog() )->setRecord( rec ); - queuedDialog()->setRecord( m_transactions.count(), m_transactions.count() ); - } - } - return tid; -} - -/** - * The goal of this helper is to help you to create non blocking - * GUIs. In the example of the todolist you can have the edit dialog - * but still change the priority or completion inline even if you currently - * edit the record. - * Your Dialog needs to have a Method setData(int,const QVariant& ) which will be called - * in these cases. - * If you edit anything while a record is edited call this function to merge the - * change in. Note if the record is not handled here we will ignore the request - * - */ -template<class Dialog, class Record, typename Id> -void OModalHelper<Dialog, Record, Id>::edited( Id id, int what, const QVariant& data ) { - int tid; - if (!( tid = transactionID( id ) ) ) - return; - - if (m_mode == New ) { - for (DialogMap::Iterator it= m_editing.begin(); it != m_editing.end(); ++it ) - if ( it.data() == tid ) - it.key()->setData( what, data ); - }else{ - int po = pos( tid ); - Dialog* dia = static_cast<Dialog*>( queuedDialog()->centerDialog() ); - dia->setRecord( m_ids[id] ); - dia->setData( what, data ); - queuedDialog()->setRecord( pos, m_transactions.count() ); - } -} - -/** - * This functions either returns the unedited record the done record - * or a new empty Record using Record(). - * If a done record is retrieved all traces are removed inside this class. This - * is what was called popping a record. This means when you call this function - * with the same TransactionID an Empty record is retrieved. - * - */ -template<class Dialog, class Record, typename Id> -Record OModalHelper<Dialog, Record, Id>::record( TransactionID tid)const { - if (m_transactions.contains( tid ) ) - return m_ids[ m_transactions[tid] ]; - else if (m_done.contains( tid ) ) { - Record rec = m_doneIds[ m_done[ tid] ]; - m_doneIds.remove( m_done[ tid ] ); - m_done.remove( tid ); - return rec; - }else - return Record(); -} - -/** - * Returns all done Records and removes all references to them internally. A 2nd call to this will - * only contain done record that where edited past the point - */ -template<class Dialog, class Record, typename Id> -OModalHelper<Dialog,Record,Id>::RecordList OModalHelper<Dialog, Record, Id>::recordsDone()const { - RecordList list; - - for (IdMap::ConstIterator it = m_doneIds.begin(); it != m_doneIds.end(); ++it ) - list.append( it.data() ); - - /* clean up */ - m_done.clear(); - m_doneIds.clear(); - - return list; -} - - -/** - * @internal - */ -template<class Dialog, class Record, typename Id> -void OModalHelper<Dialog, Record, Id>::done( int status, TransactionID tid) { -/* If we're in New mode the transaction Id does not count */ - Record rec; - - if (m_mode == New ) { - Dialog *dia = static_cast<Dialog*>( m_controler->dialog() ); - m_controler->setTransactionID( 0 ); // set the internal dialog to 0l again - tid = m_editing[ dia ]; - m_editing.remove( dia ); - rec = dia->record(); - delete dia; - }else - rec = queuedDialog()->record(); - - Id id = m_transactions[ tid ]; - if (result == QDialog::Accept ) { - m_doneIds.insert( is, rec ); - m_done.insert( tid, id ); - } - - m_transactions.remove( tid ); - m_ids.remove( id ); - - - if (status == QDialog::Accept ) - emit m_signal->accepted( tid ); - else - emit m_signal->rejected( tid ); - - emit m_signal->done( result, tid ); - - next( 0 ); -} - -/** - * @internal - */ -template<class Dialog, class Record, typename Id> -void OModalHelper<Dialog, Record, Id>::next( TransactionID tid) { - if (m_mode == New ) - return; - - if (! (m_transactions.count() ) ) { - m_controler->setTransactionID( 0 ); - queuedDialog()->setRecord( 0, 0 ); - return; - } - - int next; - Record rec; - - /* save the maybe edited record before switching */ - Dialog *dia = static_cast<Dialog*>( queuedDialog()->centerDialog() ); - rec = dia->record(); - m_ids.replace( m_transactions[tid], rec ); - - rec = nextRecord( tid, next ); - queuedDialog()->setRecord( next, m_transactions.count() ); - dia->setRecord( rec ); - - m_controler->setTransactionID( tid ); // was changed during the next call -} - -/** - * @internal - */ -/* - * code duplication should create a template fcuntion - * which takes a pointer to a function ( next, prev ) function - */ -template<class Dialog, class Record, typename Id> -void OModalHelper<Dialog, Record, Id>::prev( TransactionID tid ) { - if (m_mode == New ) - return; - - if (! (m_transactions.count()) ) { - m_controler->setTransactionID( 0 ); - queuedDialog()->setRecord( 0, 0 ); - return; - } - - int prev; - Record rec; - - /* save the maybe edited record before switching */ - Dialog *dia = static_cast<Dialog*>( queuedDialog()->centerDialog() ); - rec = dia->record(); - m_ids.replace( m_transactions[tid], rec ); - - rec = prevRecord( tid, prev ); - queuedDialog()->setRecord( prev, m_transactions.count() ); - dia->setRecord( rec ); - - m_controler->setTransactionID( tid ); // was changed during the next call -} - -/** - * @internal - */ -template<class Dialog, class Record, typename Id> -Record OModalHelper<Dialog, Record, Id>::nextRecord( TransactionID &tid, int &po ) { - /* if tid is == 0 we will take the first one */ - /* pos starts at 1 here */ - /* we know we're only called if there are records */ - Record rec; - TransactionMap::Iterator it; - if (!tid ) { - po = 1; - TransactionMap::Iterator it = m_transactions.begin(); - }else{ - po = pos( tid ); - /* if it is the last take the first as next */ - if ( po == m_transactions.count() ) { - po = 1; - it = m_transactions.begin(); - }else { - /* we know we're not the last and there is one after us */ - it = m_transactions.find( tid ); - ++it; ++po; - } - } - - tid = it.key(); - rec = m_ids[ tid ]; - return rec; -} - -/** - * @internal - */ -template<class Dialog, class Record, typename Id> -Record OModalHelper<Dialog, Record, Id>::prevRecord( TransactionID& tid, int& pos ) { - /* if tid is == 0 we will take the first one */ - /* pos starts at 1 here */ - /* we know we're only called if there are records */ - Record rec; - TransactionMap::Iterator it; - if (!tid ) { - po = 1; - TransactionMap::Iterator it = m_transactions.begin(); - }else{ - po = pos( tid ); - /* if it is the last take the first as next */ - if ( po == 1 ) { - po = m_transactions.count(); - it = m_transactions.end(); - --it; - }else { - /* we know we're not the first and there is one before us */ - it = m_transactions.find( tid ); - --it; --po; - } - } - - tid = it.key(); - rec = m_ids[ tid ]; - return rec; -} - -/** - * @internal - */ -template<class Dialog, class Record, typename Id> -int OModalHelper<Dialog, Record, Id>::pos( TransactionID id)const { - int i = 1; - for ( TransactionMap::ConstIterator it = m_transactions.begin(); it != m_transactions.end(); ++it, i++ ) - if ( it.key() == id ) - return i; - - - return 0; -} - -/** - * @internal - */ -template<class Dialog, class Record, typename Id> -Dialog* OModalHelper<Dialog, Record, Id>::newDialogRecord( const Record& rec ) { - Dialog* dia = new Dialog; - dia->setRecord( rec ); - dia->setDisabled( m_disabled ); - - QObject::connect(dia, SIGNAL(done(int) ), - m_controler, SLOT(done(int) ) ); - - /* FIXME big screen QPEApplication needs fixed*/ - dia->show(); -} - -template<class Record, class Dialog, typename Id> -OModalHelperDialog* OModalHelper<Record, Dialog, Id>::queuedDialog()const{ - if (!m_dialog ) { - m_dialog = new OModalHelperDialog; - m_dialog->setEnabled( m_disabled ); - - QObject::connect(m_dialog, SIGNAL(done(int) ), - m_controler, SLOT(done(int) ) ); - QObject::connect(m_dialog, SIGNAL(next() ), - m_controler, SLOT(next() ) ); - QObject::connect(m_dialog, SIGNAL(prev() ), - m_controler, SLOT(prev() ) ); - } - return m_dialog; -} - -#endif |