summaryrefslogtreecommitdiff
authorzecke <zecke>2003-09-13 15:04:36 (UTC)
committer zecke <zecke>2003-09-13 15:04:36 (UTC)
commit6b4c7e5d9f5c21bf044afb260fcfa066e86c12a1 (patch) (unidiff)
tree736f68df631447b88768cb8f080306e78ae3cd20
parent14db240e82c6208277946c6a76fe1d41615d6804 (diff)
downloadopie-6b4c7e5d9f5c21bf044afb260fcfa066e86c12a1.zip
opie-6b4c7e5d9f5c21bf044afb260fcfa066e86c12a1.tar.gz
opie-6b4c7e5d9f5c21bf044afb260fcfa066e86c12a1.tar.bz2
The rest of the implementation.
Theoretically you could use it, now writing the example and then finally compile that sucker for the 1st time
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
@@ -55,49 +55,49 @@ OModalHelperControler::OModalHelperControler( OModalHelperBase* base, QObject* p
55{ 55{
56} 56}
57 57
58TransactionID OModalHelperControler::transactionID()const { 58TransactionID OModalHelperControler::transactionID()const {
59 return m_id; 59 return m_id;
60} 60}
61 61
62void OModalHelperControler::setTransactionID( TransactionID id ) { 62void OModalHelperControler::setTransactionID( TransactionID id ) {
63 m_dia = 0; 63 m_dia = 0;
64 m_id = id; 64 m_id = id;
65} 65}
66 66
67QDialog* OModalHelperControler::dialog()const { 67QDialog* OModalHelperControler::dialog()const {
68 return m_dia; 68 return m_dia;
69} 69}
70 70
71/* 71/*
72 * If we're in the New mode we will map the QDialog 72 * If we're in the New mode we will map the QDialog
73 * to the TransactionID 73 * to the TransactionID
74 */ 74 */
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 );
84} 84}
85 85
86void OModalHelperControler::prev() { 86void OModalHelperControler::prev() {
87 m_base->prev( m_id ); 87 m_base->prev( m_id );
88} 88}
89 89
90/* The Queued Dialog inclusive QueuedBar */ 90/* The Queued Dialog inclusive QueuedBar */
91struct OModalQueueBar : public QHBox { 91struct OModalQueueBar : public QHBox {
92 QPushButton* next; 92 QPushButton* next;
93 QPushButton* prev; 93 QPushButton* prev;
94 QLabel * label; 94 QLabel * label;
95 95
96 OModalQueueBar( QWidget* parent ); 96 OModalQueueBar( QWidget* parent );
97 void setText( const QString& str ); 97 void setText( const QString& str );
98}; 98};
99 99
100OModalQueueBar::OModalQueueBar( QWidget* parent ) 100OModalQueueBar::OModalQueueBar( QWidget* parent )
101 : QWidget( parent, "OModal Queue Bar" ) { 101 : QWidget( parent, "OModal Queue Bar" ) {
102 prev = new QPushButton( this ); 102 prev = new QPushButton( this );
103 prev->setText( OModalQueuedDialog::tr("Prev") ); 103 prev->setText( OModalQueuedDialog::tr("Prev") );
@@ -134,27 +134,32 @@ OModalQueuedDialog::OModalQueuedDialog( QDialog* mainWidget )
134} 134}
135 135
136OModalQueuedDialog::~OModalQueuedDialog() { 136OModalQueuedDialog::~OModalQueuedDialog() {
137} 137}
138 138
139QDialog* OModalQueuedDialog::centerDialog()const { 139QDialog* OModalQueuedDialog::centerDialog()const {
140 return m_center; 140 return m_center;
141} 141}
142 142
143void OModalQueuedDialog::setQueueBarEnabled( bool b) { 143void OModalQueuedDialog::setQueueBarEnabled( bool b) {
144 /* in Qt3 use setEnabled( bool ) */ 144 /* in Qt3 use setEnabled( bool ) */
145 if (b) 145 if (b)
146 m_bar->show(); 146 m_bar->show();
147 else 147 else
148 m_bar->hide(); 148 m_bar->hide();
149} 149}
150 150
151void OModalQueuedDialog::setRecord( int record, int count ) { 151void OModalQueuedDialog::setRecord( int record, int count ) {
152 if (!record && !count ) { 152 if (!record && !count ) {
153 hide(); 153 hide();
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
@@ -12,131 +12,137 @@
12    .i_,=:_.      -<s. This library is distributed in the hope that 12    .i_,=:_.      -<s. This library is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY; 13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of 14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A 15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU 16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
17..}^=.=       =       ; Library General Public License for more 17..}^=.=       =       ; Library General Public License for more
18++=   -.     .`     .: details. 18++=   -.     .`     .: details.
19 :     =  ...= . :.=- 19 :     =  ...= . :.=-
20 -.   .:....=;==+<; You should have received a copy of the GNU 20 -.   .:....=;==+<; You should have received a copy of the GNU
21  -_. . .   )=.  = Library General Public License along with 21  -_. . .   )=.  = Library General Public License along with
22    --        :-=` this library; see the file COPYING.LIB. 22    --        :-=` this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation, 23 If not, write to the Free Software Foundation,
24 Inc., 59 Temple Place - Suite 330, 24 Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA. 25 Boston, MA 02111-1307, USA.
26 26
27*/ 27*/
28 28
29#ifndef HAZE_OMODAL_HELPER_H 29#ifndef HAZE_OMODAL_HELPER_H
30#define HAZE_OMODAL_HELPER_H 30#define HAZE_OMODAL_HELPER_H
31 31
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
49/** 50/**
50 * Modality sucks! ;) But it is easy to work with 51 * Modality sucks! ;) But it is easy to work with
51 * do exec() on a dialog and you know everything is funky. 52 * do exec() on a dialog and you know everything is funky.
52 * You only need to have one Dialog loaded and so on. 53 * You only need to have one Dialog loaded and so on.
53 * This class helps you to work like with modality and help 54 * This class helps you to work like with modality and help
54 * you to keep things in sync 55 * you to keep things in sync
55 * It's a template class but it sends signals once one Item is ready 56 * It's a template class but it sends signals once one Item is ready
56 * the signals contains the status and id of the item and then you 57 * the signals contains the status and id of the item and then you
57 * need fetch it. 58 * need fetch it.
58 * Handled Records will stay available until the first call to retrieve 59 * Handled Records will stay available until the first call to retrieve
59 * either the record via the TransactionID or via the QValueList<Record>. Note 60 * either the record via the TransactionID or via the QValueList<Record>. Note
60 * that most functions do not take handled records into account. 61 * that most functions do not take handled records into account.
61 * Also if you edit an record external you can tell this class and it'll 62 * Also if you edit an record external you can tell this class and it'll
62 * call the merge() function of your widget to maybe merge in these changes. 63 * call the merge() function of your widget to maybe merge in these changes.
63 * It also supports multiple modes. Either it can create new dialogs 64 * It also supports multiple modes. Either it can create new dialogs
64 * for each item or it can queue them depending on your usage. But it is 65 * for each item or it can queue them depending on your usage. But it is
65 * so smart that if only one item is shown that the queue bar is not shown 66 * so smart that if only one item is shown that the queue bar is not shown
66 * See the example for simple usage. 67 * See the example for simple usage.
67 * 68 *
68 * @short helps to life without modaility 69 * @short helps to life without modaility
69 * @author hOlgAr 70 * @author hOlgAr
70 * @version 0.01 71 * @version 0.01
71 */ 72 */
72template<class Dialog, class Record, typename Id = int> 73template<class Dialog, class Record, typename Id = int>
73class OModalHelper : private OModalHelperBase{ 74class OModalHelper : private OModalHelperBase{
74 friend class OModalHelperSignal; 75 friend class OModalHelperSignal;
75 friend class OModalHelperControler; 76 friend class OModalHelperControler;
76public: 77public:
77 typedef QValueList<Record> RecordList; 78 typedef QValueList<Record> RecordList;
78 typedef QMap<Id, Record> IdMap; 79 typedef QMap<Id, Record> IdMap;
79 typedef QMap<TransactionID, Id> TransactionMap; 80 typedef QMap<TransactionID, Id> TransactionMap;
80 typedef QMap<QDialog*, TransactionID> DialogMap 81 typedef QMap<QDialog*, TransactionID> DialogMap
81 enum Mode { Queue, New }; 82 enum Mode { Queue, New };
82 OModalHelper(enum Mode mode, QObject* parnet ); 83 OModalHelper(enum Mode mode, QObject* parnet );
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 );
91 void connectAccepted( QObject* rec, const char* slot ); 94 void connectAccepted( QObject* rec, const char* slot );
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;
111 OModalHelperSignal *m_signal; // our signal 116 OModalHelperSignal *m_signal; // our signal
112 OModalHelperControler *m_controler; 117 OModalHelperControler *m_controler;
113 IdMap m_ids; // maps ids (uids) to a record 118 IdMap m_ids; // maps ids (uids) to a record
114 IdMap m_doneIds; 119 IdMap m_doneIds;
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
123/* ### FIXME use namespace with Qt3 */ 129/* ### FIXME use namespace with Qt3 */
124 130
125/* 131/*
126 * A note on flow. The Signal is used for QT Signals when 132 * A note on flow. The Signal is used for QT Signals when
127 * a record is done. 133 * a record is done.
128 * There is either one controler and this controler slot will 134 * There is either one controler and this controler slot will
129 * be connected to a dialog signal. 135 * be connected to a dialog signal.
130 * In Queue we get the next and prev signals and call the Helper. 136 * In Queue we get the next and prev signals and call the Helper.
131 * this then changes the Record of the dialog and sets the transactionId 137 * this then changes the Record of the dialog and sets the transactionId
132 * of the controler. 138 * of the controler.
133 * For the new mode 139 * For the new mode
134 * 140 *
135 */ 141 */
136 142
137class OModalHelperSignal : public QObject { 143class OModalHelperSignal : public QObject {
138 Q_OBJECT 144 Q_OBJECT
139public: 145public:
140 OModalHelperSignal(OModalHelperBase* base, QObject* parent); 146 OModalHelperSignal(OModalHelperBase* base, QObject* parent);
141 ~OModalHelperSignal(); 147 ~OModalHelperSignal();
142 148
@@ -184,166 +190,168 @@ signals:
184 void next(); 190 void next();
185 void prev(); 191 void prev();
186 192
187private: 193private:
188 OModalQueueBar *m_bar; 194 OModalQueueBar *m_bar;
189 QDialog *m_center; 195 QDialog *m_center;
190}; 196};
191 197
192 198
193/* 199/*
194 * Tcpp Template Implementation 200 * Tcpp Template Implementation
195 */ 201 */
196 202
197/** 203/**
198 * This is the simple Template c'tor. It takes the mode 204 * This is the simple Template c'tor. It takes the mode
199 * this helper should operate in and the parent object. 205 * this helper should operate in and the parent object.
200 * This helper will be deleted when the parent gets deleted 206 * This helper will be deleted when the parent gets deleted
201 * or you delete it yourself. 207 * or you delete it yourself.
202 * 208 *
203 * @param mode The mode this dialog should be in 209 * @param mode The mode this dialog should be in
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/**
216 * This functions looks for your record and sees if it is 222 * This functions looks for your record and sees if it is
217 * handled with this helper. Note that done records 223 * handled with this helper. Note that done records
218 * will not be returned. 224 * will not be returned.
219 * 225 *
220 * @return true if the record is currenlty edited otherwise false 226 * @return true if the record is currenlty edited otherwise false
221 * 227 *
222 * @param Id The id which might be handled 228 * @param Id The id which might be handled
223 */ 229 */
224template<class Dialog, class Record, typename Id> 230template<class Dialog, class Record, typename Id>
225bool OModalHelper<Dialog, Record, Id>::handles( Id id )const { 231bool OModalHelper<Dialog, Record, Id>::handles( Id id )const {
226 if ( m_transactions.isEmpty() ) 232 if ( m_transactions.isEmpty() )
227 return false; 233 return false;
228 234
229 TransactionMap::ConstIterator it = m_transactions.begin(); 235 TransactionMap::ConstIterator it = m_transactions.begin();
230 for ( ; it != m_transactions.end(); ++it ) 236 for ( ; it != m_transactions.end(); ++it )
231 if ( it.data() == id ) 237 if ( it.data() == id )
232 return true; 238 return true;
233 239
234 return false; 240 return false;
235} 241}
236 242
237 243
238/** 244/**
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
256 * of done operations as well. 281 * of done operations as well.
257 * This also clears all done operations you did not popped 282 * This also clears all done operations you did not popped
258 */ 283 */
259template<class Dialog, class Record, typename Id> 284template<class Dialog, class Record, typename Id>
260void OModalHelper<Dialog, Record, Id>::cancel() { 285void OModalHelper<Dialog, Record, Id>::cancel() {
261 m_ids.clear(); 286 m_ids.clear();
262 m_doneIds.clear(); 287 m_doneIds.clear();
263 m_done.clear(); 288 m_done.clear();
264 m_transactions.clear(); 289 m_transactions.clear();
265 290
266 /* we also need to remove the QDialogs */ 291 /* we also need to remove the QDialogs */
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/**
280 * This cancels editing of the record behind the Transaction Number 306 * This cancels editing of the record behind the Transaction Number
281 * Note that if editing is already done it will also be removed from this list 307 * Note that if editing is already done it will also be removed from this list
282 */ 308 */
283template<class Dialog, class Record, typename Id> 309template<class Dialog, class Record, typename Id>
284void OModalHelper::cancel( TransactionID tid ) { 310void OModalHelper::cancel( TransactionID tid ) {
285 /* wrong tid */ 311 /* wrong tid */
286 if (!m_transactions.contains( tid ) && !m_done.contains( tid) ) 312 if (!m_transactions.contains( tid ) && !m_done.contains( tid) )
287 return; 313 return;
288 314
289 if (m_mode == New ) 315 if (m_mode == New )
290 /* reverse map eek */ 316 /* reverse map eek */
291 for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it ) 317 for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it )
292 if ( it.data() == tid ) { 318 if ( it.data() == tid ) {
293 it.key()->hide(); 319 it.key()->hide();
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 ) )
330 * This signal gets emitted whenever a Record was accepted or rejected 338 * This signal gets emitted whenever a Record was accepted or rejected
331 * 339 *
332 * @param rec The object where the slot belongs to 340 * @param rec The object where the slot belongs to
333 * @param slot The slot which should be called. See the needed parameter above 341 * @param slot The slot which should be called. See the needed parameter above
334 */ 342 */
335template<class Dialog, class Record, typename Id> 343template<class Dialog, class Record, typename Id>
336void OModalHelper<Dialog, Record, Id>::connectDone( QObject* rec, const char* slot ) { 344void OModalHelper<Dialog, Record, Id>::connectDone( QObject* rec, const char* slot ) {
337 QObject::connect(m_signal, SIGNAL(done(int, TransactionID) ), 345 QObject::connect(m_signal, SIGNAL(done(int, TransactionID) ),
338 rec, slot ); 346 rec, slot );
339} 347}
340 348
341/** 349/**
342 * Connect to the accepted Signal. SIGNAL( accepted(TransactionID ) ) 350 * Connect to the accepted Signal. SIGNAL( accepted(TransactionID ) )
343 * This signal gets emitted whenever a Record was accepted 351 * This signal gets emitted whenever a Record was accepted
344 * 352 *
345 * @param rec The object where the slot belongs to 353 * @param rec The object where the slot belongs to
346 * @param slot The slot which should be called. See the needed parameter above 354 * @param slot The slot which should be called. See the needed parameter above
347 */ 355 */
348template<class Dialog, class Record, typename Id> 356template<class Dialog, class Record, typename Id>
349void OModalHelper<Dialog, Record, Id>::connectAccepted( QObject* rec, const char* slot ) { 357void OModalHelper<Dialog, Record, Id>::connectAccepted( QObject* rec, const char* slot ) {
@@ -362,44 +370,339 @@ void OModalHelper<Dialog, Record, Id>::connectAccepted( QObject* rec, const char
362template<class Dialog, class Record, typename Id> 370template<class Dialog, class Record, typename Id>
363void OModalHelper<Dialog, Record, Id>::connectRejected( QObject* rec, const char* slot ) { 371void OModalHelper<Dialog, Record, Id>::connectRejected( QObject* rec, const char* slot ) {
364 QObject::connect(m_signal, SIGNAL(rejected(TransactionID) ), 372 QObject::connect(m_signal, SIGNAL(rejected(TransactionID) ),
365 rec, slot ); 373 rec, slot );
366} 374}
367 375
368/** 376/**
369 * Tell the helper to handle a record. If the record is currently handled 377 * Tell the helper to handle a record. If the record is currently handled
370 * it will be made active. 378 * it will be made active.
371 * Already handled record which are waiting getting popped are not taken into account 379 * Already handled record which are waiting getting popped are not taken into account
372 * Otherwise this helpers make the record editable. 380 * Otherwise this helpers make the record editable.
373 * The record supplied needs to have a valid copy operator and constructor. 381 * The record supplied needs to have a valid copy operator and constructor.
374 * In the case where the record is already present the parameter gets discarded. 382 * In the case where the record is already present the parameter gets discarded.
375 * If you want the new record to be taken you need to cancel the Transaction first 383 * If you want the new record to be taken you need to cancel the Transaction first
376 * 384 *
377 * @param id The Identification of the Record. For PIM it would uid() 385 * @param id The Identification of the Record. For PIM it would uid()
378 * @param rec The record we want to be edited 386 * @param rec The record we want to be edited
379 * 387 *
380 * @returns This functions returns the TransactionId assigned to the record 388 * @returns This functions returns the TransactionId assigned to the record
381 * 389 *
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