-rw-r--r-- | libopie/big-screen/omodalhelper.cpp | 7 | ||||
-rw-r--r-- | libopie/big-screen/omodalhelper.h | 377 |
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 | ||
58 | TransactionID OModalHelperControler::transactionID()const { | 58 | TransactionID OModalHelperControler::transactionID()const { |
59 | return m_id; | 59 | return m_id; |
60 | } | 60 | } |
61 | 61 | ||
62 | void OModalHelperControler::setTransactionID( TransactionID id ) { | 62 | void OModalHelperControler::setTransactionID( TransactionID id ) { |
63 | m_dia = 0; | 63 | m_dia = 0; |
64 | m_id = id; | 64 | m_id = id; |
65 | } | 65 | } |
66 | 66 | ||
67 | QDialog* OModalHelperControler::dialog()const { | 67 | QDialog* 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 | */ |
75 | void OModalHelperControler::done( int result ) { | 75 | void 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 | ||
82 | void OModalHelperControler::next() { | 82 | void OModalHelperControler::next() { |
83 | m_base->next( m_id ); | 83 | m_base->next( m_id ); |
84 | } | 84 | } |
85 | 85 | ||
86 | void OModalHelperControler::prev() { | 86 | void 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 */ |
91 | struct OModalQueueBar : public QHBox { | 91 | struct 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 | ||
100 | OModalQueueBar::OModalQueueBar( QWidget* parent ) | 100 | OModalQueueBar::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 | ||
136 | OModalQueuedDialog::~OModalQueuedDialog() { | 136 | OModalQueuedDialog::~OModalQueuedDialog() { |
137 | } | 137 | } |
138 | 138 | ||
139 | QDialog* OModalQueuedDialog::centerDialog()const { | 139 | QDialog* OModalQueuedDialog::centerDialog()const { |
140 | return m_center; | 140 | return m_center; |
141 | } | 141 | } |
142 | 142 | ||
143 | void OModalQueuedDialog::setQueueBarEnabled( bool b) { | 143 | void 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 | ||
151 | void OModalQueuedDialog::setRecord( int record, int count ) { | 151 | void 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 | ||
37 | typedef int TransactionID; | 38 | typedef int TransactionID; |
38 | 39 | ||
39 | class OModalHelperControler; | 40 | class OModalHelperControler; |
40 | class OModalHelperSignal; | 41 | class OModalHelperSignal; |
41 | class QDialog; | 42 | class QDialog; |
42 | 43 | ||
43 | struct OModalHelperBase { | 44 | struct 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 | */ |
72 | template<class Dialog, class Record, typename Id = int> | 73 | template<class Dialog, class Record, typename Id = int> |
73 | class OModalHelper : private OModalHelperBase{ | 74 | class OModalHelper : private OModalHelperBase{ |
74 | friend class OModalHelperSignal; | 75 | friend class OModalHelperSignal; |
75 | friend class OModalHelperControler; | 76 | friend class OModalHelperControler; |
76 | public: | 77 | public: |
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; |
100 | private: | 103 | private: |
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 | ||
108 | private: | 113 | private: |
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 | ||
137 | class OModalHelperSignal : public QObject { | 143 | class OModalHelperSignal : public QObject { |
138 | Q_OBJECT | 144 | Q_OBJECT |
139 | public: | 145 | public: |
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 | ||
187 | private: | 193 | private: |
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 | */ |
206 | template<class Dialog, class Record, typename Id> | 212 | template<class Dialog, class Record, typename Id> |
207 | OModalHelper<Dialog, Record, Id>::OModalHelper( enum Mode mode, QObject* parent ) { | 213 | OModalHelper<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 | */ |
224 | template<class Dialog, class Record, typename Id> | 230 | template<class Dialog, class Record, typename Id> |
225 | bool OModalHelper<Dialog, Record, Id>::handles( Id id )const { | 231 | bool 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 | */ |
241 | template<class Dialog, class Record, typename Id> | 247 | template<class Dialog, class Record, typename Id> |
242 | TransactionID OModalHelper<Dialog, Record, Id>::transactionID( Id id)const { | 248 | TransactionID 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 | */ | ||
269 | template<class Dialog, class Record, typename Id> | ||
270 | void 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 | */ |
259 | template<class Dialog, class Record, typename Id> | 284 | template<class Dialog, class Record, typename Id> |
260 | void OModalHelper<Dialog, Record, Id>::cancel() { | 285 | void 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 | */ |
283 | template<class Dialog, class Record, typename Id> | 309 | template<class Dialog, class Record, typename Id> |
284 | void OModalHelper::cancel( TransactionID tid ) { | 310 | void 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 | */ |
335 | template<class Dialog, class Record, typename Id> | 343 | template<class Dialog, class Record, typename Id> |
336 | void OModalHelper<Dialog, Record, Id>::connectDone( QObject* rec, const char* slot ) { | 344 | void 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 | */ |
348 | template<class Dialog, class Record, typename Id> | 356 | template<class Dialog, class Record, typename Id> |
349 | void OModalHelper<Dialog, Record, Id>::connectAccepted( QObject* rec, const char* slot ) { | 357 | void OModalHelper<Dialog, Record, Id>::connectAccepted( QObject* rec, const char* slot ) { |
@@ -362,44 +370,339 @@ void OModalHelper<Dialog, Record, Id>::connectAccepted( QObject* rec, const char | |||
362 | template<class Dialog, class Record, typename Id> | 370 | template<class Dialog, class Record, typename Id> |
363 | void OModalHelper<Dialog, Record, Id>::connectRejected( QObject* rec, const char* slot ) { | 371 | void 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 | */ |
383 | template<class Dialog, class Record, typename Id> | 391 | template<class Dialog, class Record, typename Id> |
384 | TransactionID OModalHelper<Dialog, Record, Id>::handle( Id id, const Record& rec ) { | 392 | TransactionID 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 | */ | ||
440 | template<class Dialog, class Record, typename Id> | ||
441 | void 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 | */ | ||
467 | template<class Dialog, class Record, typename Id> | ||
468 | Record 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 | */ | ||
484 | template<class Dialog, class Record, typename Id> | ||
485 | OModalHelper<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 | */ | ||
502 | template<class Dialog, class Record, typename Id> | ||
503 | void 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 | */ | ||
540 | template<class Dialog, class Record, typename Id> | ||
541 | void 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 | */ | ||
573 | template<class Dialog, class Record, typename Id> | ||
574 | void 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 | */ | ||
602 | template<class Dialog, class Record, typename Id> | ||
603 | Record 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 | */ | ||
633 | template<class Dialog, class Record, typename Id> | ||
634 | Record 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 | */ | ||
665 | template<class Dialog, class Record, typename Id> | ||
666 | int 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 | */ | ||
679 | template<class Dialog, class Record, typename Id> | ||
680 | Dialog* 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 | |||
692 | template<class Record, class Dialog, typename Id> | ||
693 | OModalHelperDialog* 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 |