Diffstat (limited to 'library/backend/categories.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | library/backend/categories.cpp | 701 |
1 files changed, 701 insertions, 0 deletions
diff --git a/library/backend/categories.cpp b/library/backend/categories.cpp new file mode 100644 index 0000000..91331db --- a/dev/null +++ b/library/backend/categories.cpp | |||
@@ -0,0 +1,701 @@ | |||
1 | /********************************************************************** | ||
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | ||
3 | ** | ||
4 | ** This file is part of Qtopia Environment. | ||
5 | ** | ||
6 | ** This file may be distributed and/or modified under the terms of the | ||
7 | ** GNU General Public License version 2 as published by the Free | ||
8 | ** Software Foundation and appearing in the file LICENSE.GPL included | ||
9 | ** in the packaging of this file. | ||
10 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING | ||
12 | ** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A | ||
13 | ** PARTICULAR PURPOSE. | ||
14 | ** | ||
15 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
16 | ** | ||
17 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
18 | ** not clear to you. | ||
19 | ** | ||
20 | **********************************************************************/ | ||
21 | #include "categories.h" | ||
22 | #include <qfile.h> | ||
23 | #include <qcstring.h> | ||
24 | #include <qtextstream.h> | ||
25 | #include "stringutil.h" | ||
26 | |||
27 | using namespace Qtopia; | ||
28 | |||
29 | /*********************************************************** | ||
30 | * | ||
31 | * CategoryGroup | ||
32 | * | ||
33 | **********************************************************/ | ||
34 | |||
35 | #ifdef PALMTOPCENTER | ||
36 | UidGen CategoryGroup::sUidGen( UidGen::PalmtopCenter ); | ||
37 | #else | ||
38 | UidGen CategoryGroup::sUidGen( UidGen::Qtopia ); | ||
39 | #endif | ||
40 | |||
41 | int CategoryGroup::add( const QString &label ) | ||
42 | { | ||
43 | if ( label == QObject::tr("All") || label == QObject::tr("Unfiled") ) | ||
44 | return 0; | ||
45 | |||
46 | QMap<QString,int>::Iterator findIt = mLabelIdMap.find( label ); | ||
47 | if ( findIt != mLabelIdMap.end() ) | ||
48 | return 0; | ||
49 | int newUid = uidGen().generate(); | ||
50 | insert( newUid, label ); | ||
51 | return newUid; | ||
52 | } | ||
53 | |||
54 | void CategoryGroup::insert( int uid, const QString &label ) | ||
55 | { | ||
56 | uidGen().store( uid ); | ||
57 | mIdLabelMap[uid] = label; | ||
58 | mLabelIdMap[label] = uid; | ||
59 | } | ||
60 | |||
61 | bool CategoryGroup::add( int uid, const QString &label ) | ||
62 | { | ||
63 | if ( label == QObject::tr("All") || label == QObject::tr("Unfiled") ) | ||
64 | return FALSE; | ||
65 | |||
66 | QMap<QString,int>::ConstIterator labelIt = mLabelIdMap.find( label ); | ||
67 | if ( labelIt != mLabelIdMap.end() ) | ||
68 | return FALSE; | ||
69 | QMap<int,QString>::ConstIterator idIt = mIdLabelMap.find( uid ); | ||
70 | if ( idIt != mIdLabelMap.end() ) | ||
71 | return FALSE; | ||
72 | insert( uid, label ); | ||
73 | return TRUE; | ||
74 | } | ||
75 | |||
76 | bool CategoryGroup::remove( const QString &label ) | ||
77 | { | ||
78 | QMap<QString,int>::Iterator findIt = mLabelIdMap.find( label ); | ||
79 | if ( findIt == mLabelIdMap.end() ) | ||
80 | return FALSE; | ||
81 | |||
82 | mIdLabelMap.remove( *findIt ); | ||
83 | mLabelIdMap.remove( findIt ); | ||
84 | |||
85 | return TRUE; | ||
86 | } | ||
87 | |||
88 | bool CategoryGroup::remove( int uid ) | ||
89 | { | ||
90 | QMap<int,QString>::Iterator idIt = mIdLabelMap.find( uid ); | ||
91 | if ( idIt == mIdLabelMap.end() ) | ||
92 | return FALSE; | ||
93 | |||
94 | mLabelIdMap.remove( *idIt ); | ||
95 | mIdLabelMap.remove( idIt ); | ||
96 | |||
97 | return TRUE; | ||
98 | } | ||
99 | |||
100 | bool CategoryGroup::rename( int uid, const QString &newLabel ) | ||
101 | { | ||
102 | if ( newLabel == QObject::tr("All") || newLabel == QObject::tr("Unfiled") ) | ||
103 | return FALSE; | ||
104 | |||
105 | QMap<int, QString>::Iterator idIt = mIdLabelMap.find( uid ); | ||
106 | if ( idIt == mIdLabelMap.end() ) | ||
107 | return FALSE; | ||
108 | |||
109 | mLabelIdMap.remove( *idIt ); | ||
110 | mLabelIdMap[newLabel] = uid; | ||
111 | *idIt = newLabel; | ||
112 | |||
113 | return TRUE; | ||
114 | } | ||
115 | |||
116 | bool CategoryGroup::rename( const QString &oldLabel, const QString &newLabel ) | ||
117 | { | ||
118 | return rename( id(oldLabel), newLabel ); | ||
119 | } | ||
120 | |||
121 | bool CategoryGroup::contains(int uid) const | ||
122 | { | ||
123 | return ( mIdLabelMap.find( uid ) != mIdLabelMap.end() ); | ||
124 | } | ||
125 | |||
126 | bool CategoryGroup::contains(const QString &label) const | ||
127 | { | ||
128 | return ( mLabelIdMap.find( label ) != mLabelIdMap.end() ); | ||
129 | } | ||
130 | |||
131 | /** Returns label associated with the uid or QString::null if | ||
132 | * not found | ||
133 | */ | ||
134 | const QString &CategoryGroup::label(int uid) const | ||
135 | { | ||
136 | QMap<int,QString>::ConstIterator idIt = mIdLabelMap.find( uid ); | ||
137 | if ( idIt == mIdLabelMap.end() ) | ||
138 | return QString::null; | ||
139 | return *idIt; | ||
140 | } | ||
141 | |||
142 | /** Returns the uid associated with label or 0 if not found */ | ||
143 | int CategoryGroup::id(const QString &label) const | ||
144 | { | ||
145 | QMap<QString,int>::ConstIterator labelIt = mLabelIdMap.find( label ); | ||
146 | if ( labelIt == mLabelIdMap.end() ) | ||
147 | return 0; | ||
148 | return *labelIt; | ||
149 | } | ||
150 | |||
151 | QStringList CategoryGroup::labels() const | ||
152 | { | ||
153 | QStringList labels; | ||
154 | for ( QMap<int, QString>::ConstIterator it = mIdLabelMap.begin(); | ||
155 | it != mIdLabelMap.end(); ++it ) | ||
156 | labels += *it; | ||
157 | // ### I don't think this is the place for this... | ||
158 | // labels.sort(); | ||
159 | return labels; | ||
160 | } | ||
161 | |||
162 | QStringList CategoryGroup::labels(const QArray<int> &catids ) const | ||
163 | { | ||
164 | QStringList labels; | ||
165 | if ( catids.count() == 0 ) | ||
166 | return labels; | ||
167 | for ( QMap<int, QString>::ConstIterator it = mIdLabelMap.begin(); | ||
168 | it != mIdLabelMap.end(); ++it ) | ||
169 | if ( catids.find( it.key() ) != -1 ) | ||
170 | labels += *it; | ||
171 | return labels; | ||
172 | } | ||
173 | |||
174 | QArray<int> CategoryGroup::ids( const QStringList &cats ) const | ||
175 | { | ||
176 | QArray<int> results; | ||
177 | |||
178 | for ( QStringList::ConstIterator catIt = cats.begin(); | ||
179 | catIt != cats.end(); ++catIt ) { | ||
180 | if ( *catIt == QObject::tr("All") || *catIt == QObject::tr("Unfiled") ) | ||
181 | continue; | ||
182 | int value = id( *catIt ); | ||
183 | if ( value != 0 ) { | ||
184 | int tmp = results.size(); | ||
185 | results.resize( tmp + 1 ); | ||
186 | results[ tmp ] = value; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | return results; | ||
191 | } | ||
192 | |||
193 | QArray<int> CategoryGroup::ids() const | ||
194 | { | ||
195 | QArray<int> results( mIdLabelMap.count() ); | ||
196 | int i = 0; | ||
197 | for ( QMap<int, QString>::ConstIterator it = mIdLabelMap.begin(); | ||
198 | it != mIdLabelMap.end(); ++it ) | ||
199 | results[i++] = it.key(); | ||
200 | |||
201 | return results; | ||
202 | } | ||
203 | |||
204 | /*********************************************************** | ||
205 | * | ||
206 | * Categories | ||
207 | * | ||
208 | **********************************************************/ | ||
209 | |||
210 | /** Add the category name as long as it doesn't already exist locally | ||
211 | * or globally. Return TRUE if added, FALSE if conflicts. | ||
212 | */ | ||
213 | int Categories::addCategory( const QString &appname, | ||
214 | const QString &catname, | ||
215 | int uid ) | ||
216 | { | ||
217 | if ( mGlobalCats.contains(catname) ) | ||
218 | return 0; | ||
219 | |||
220 | QMap< QString, CategoryGroup >::Iterator | ||
221 | appIt = mAppCats.find( appname ); | ||
222 | |||
223 | if ( appIt == mAppCats.end() ) { | ||
224 | CategoryGroup newgroup; | ||
225 | newgroup.add( uid, catname ); | ||
226 | mAppCats.insert( appname, newgroup ); | ||
227 | emit categoryAdded( *this, appname, uid ); | ||
228 | return uid; | ||
229 | } | ||
230 | |||
231 | CategoryGroup &cats = *appIt; | ||
232 | cats.add( uid, catname ); | ||
233 | emit categoryAdded( *this, appname, uid ); | ||
234 | return uid; | ||
235 | } | ||
236 | |||
237 | int Categories::addCategory( const QString &appname, | ||
238 | const QString &catname ) | ||
239 | { | ||
240 | if ( mGlobalCats.contains(catname) ) | ||
241 | return 0; | ||
242 | |||
243 | QMap< QString, CategoryGroup >::Iterator | ||
244 | appIt = mAppCats.find( appname ); | ||
245 | |||
246 | if ( appIt == mAppCats.end() ) { | ||
247 | CategoryGroup newgroup; | ||
248 | int uid = newgroup.add( catname ); | ||
249 | mAppCats.insert( appname, newgroup ); | ||
250 | emit categoryAdded( *this, appname, uid ); | ||
251 | return uid; | ||
252 | } | ||
253 | |||
254 | CategoryGroup &cats = *appIt; | ||
255 | int uid = cats.add( catname ); | ||
256 | if ( !uid ) | ||
257 | return 0; | ||
258 | emit categoryAdded( *this, appname, uid ); | ||
259 | return uid; | ||
260 | } | ||
261 | |||
262 | int Categories::addGlobalCategory( const QString &catname, int uid ) | ||
263 | { | ||
264 | mGlobalCats.add( uid, catname ); | ||
265 | emit categoryAdded( *this, QString::null, uid ); | ||
266 | return uid; | ||
267 | } | ||
268 | |||
269 | int Categories::addGlobalCategory( const QString &catname ) | ||
270 | { | ||
271 | int uid = mGlobalCats.add( catname ); | ||
272 | if ( !uid ) | ||
273 | return 0; | ||
274 | emit categoryAdded( *this, QString::null, uid ); | ||
275 | return uid; | ||
276 | } | ||
277 | |||
278 | /** Removes the category from the application; if it is not found | ||
279 | * in the application, then it attempts to remove it from | ||
280 | * the global list | ||
281 | */ | ||
282 | bool Categories::removeCategory( const QString &appname, | ||
283 | const QString &catname, | ||
284 | bool checkGlobal ) | ||
285 | { | ||
286 | QMap< QString, CategoryGroup >::Iterator | ||
287 | appIt = mAppCats.find( appname ); | ||
288 | if ( appIt != mAppCats.end() ) { | ||
289 | CategoryGroup &cats = *appIt; | ||
290 | int uid = cats.id( catname ); | ||
291 | if ( cats.remove( uid ) ) { | ||
292 | emit categoryRemoved( *this, appname, uid ); | ||
293 | return TRUE; | ||
294 | } | ||
295 | } | ||
296 | if ( !checkGlobal ) | ||
297 | return FALSE; | ||
298 | return removeGlobalCategory( catname ); | ||
299 | } | ||
300 | |||
301 | bool Categories::removeCategory( const QString &appname, int uid ) | ||
302 | { | ||
303 | QMap< QString, CategoryGroup >::Iterator | ||
304 | appIt = mAppCats.find( appname ); | ||
305 | if ( appIt != mAppCats.end() ) { | ||
306 | CategoryGroup &cats = *appIt; | ||
307 | if ( cats.remove( uid ) ) { | ||
308 | emit categoryRemoved( *this, appname, uid ); | ||
309 | return TRUE; | ||
310 | } | ||
311 | } | ||
312 | return FALSE; | ||
313 | } | ||
314 | |||
315 | bool Categories::removeGlobalCategory( const QString &catname ) | ||
316 | { | ||
317 | int uid = mGlobalCats.id( catname ); | ||
318 | if ( mGlobalCats.remove( uid ) ) { | ||
319 | emit categoryRemoved( *this, QString::null, uid ); | ||
320 | return TRUE; | ||
321 | } | ||
322 | return FALSE; | ||
323 | } | ||
324 | |||
325 | |||
326 | bool Categories::removeGlobalCategory( int uid ) | ||
327 | { | ||
328 | if ( mGlobalCats.remove( uid ) ) { | ||
329 | emit categoryRemoved( *this, QString::null, uid ); | ||
330 | return TRUE; | ||
331 | } | ||
332 | return FALSE; | ||
333 | } | ||
334 | |||
335 | /** Returns the sorted list of all categories that are associated with | ||
336 | * the app. If includeGlobal parameter is TRUE then the returned | ||
337 | * categories will include the global category items. | ||
338 | */ | ||
339 | QStringList Categories::labels( const QString &app, | ||
340 | bool includeGlobal, | ||
341 | ExtraLabels extra ) const | ||
342 | { | ||
343 | QMap< QString, CategoryGroup >::ConstIterator | ||
344 | appIt = mAppCats.find( app ); | ||
345 | QStringList cats; | ||
346 | switch ( extra ) { | ||
347 | case NoExtra: break; | ||
348 | case AllUnfiled: | ||
349 | cats.append( tr("All") ); | ||
350 | cats.append( tr("Unfiled") ); | ||
351 | break; | ||
352 | case AllLabel: | ||
353 | cats.append( tr("All") ); | ||
354 | break; | ||
355 | case UnfiledLabel: | ||
356 | cats.append( tr("Unfiled") ); | ||
357 | break; | ||
358 | } | ||
359 | if ( appIt != mAppCats.end() ) | ||
360 | cats += (*appIt).labels(); | ||
361 | else qDebug("Categories::labels didn't find app %s", app.latin1() ); | ||
362 | if ( includeGlobal ) | ||
363 | cats += mGlobalCats.labels(); | ||
364 | // I don't think a sorted list is useful, the user might find prefer | ||
365 | // it in the original order. | ||
366 | // cats.sort(); | ||
367 | return cats; | ||
368 | } | ||
369 | |||
370 | QString Categories::label( const QString &app, int id ) const | ||
371 | { | ||
372 | if ( mGlobalCats.contains( id ) ) | ||
373 | return mGlobalCats.label( id ); | ||
374 | QMap< QString, CategoryGroup >::ConstIterator | ||
375 | appIt = mAppCats.find( app ); | ||
376 | if ( appIt == mAppCats.end() ) | ||
377 | return QString::null; | ||
378 | return (*appIt).label( id ); | ||
379 | } | ||
380 | |||
381 | QStringList Categories::labels( const QString & app, | ||
382 | const QArray<int> &catids ) const | ||
383 | { | ||
384 | QStringList strs = mGlobalCats.labels( catids ); | ||
385 | strs += mAppCats[app].labels( catids ); | ||
386 | return strs; | ||
387 | } | ||
388 | |||
389 | /** Returns a single string associated with the cat ids for display in | ||
390 | * a combobox or any area that requires one string. If catids are empty | ||
391 | * then "Unfiled" will be returned. If multiple categories are assigned | ||
392 | * the first cat id is shown with " (multi)" appended to the string. | ||
393 | */ | ||
394 | QString Categories::displaySingle( const QString &app, | ||
395 | const QArray<int> &catids, | ||
396 | DisplaySingle display ) const | ||
397 | { | ||
398 | QStringList strs = labels( app, catids ); | ||
399 | if ( !strs.count() ) | ||
400 | return tr("Unfiled"); | ||
401 | strs.sort(); | ||
402 | QString r; | ||
403 | if ( strs.count() > 1 ) { | ||
404 | switch ( display ) { | ||
405 | case ShowFirst: | ||
406 | r = strs.first(); | ||
407 | break; | ||
408 | case ShowMulti: | ||
409 | r = strs.first() + tr(" (multi.)"); | ||
410 | break; | ||
411 | case ShowAll: | ||
412 | r = strs.join(" "); | ||
413 | break; | ||
414 | } | ||
415 | } | ||
416 | else r = strs.first(); | ||
417 | return r; | ||
418 | } | ||
419 | |||
420 | QArray<int> Categories::ids( const QString &app ) const | ||
421 | { | ||
422 | QArray<int> allIds = mGlobalCats.ids(); | ||
423 | QArray<int> appIds = mAppCats[app].ids(); | ||
424 | |||
425 | // we should make the guarentee that the ids are in the | ||
426 | // same order as the labels, (i.e. app cats then global) | ||
427 | // otherwise there is no point in having these two separate functions. | ||
428 | uint appSize = appIds.size(); | ||
429 | appIds.resize( appSize + allIds.size() ); | ||
430 | for ( uint i = appSize; i < appIds.size(); ++i ) | ||
431 | appIds[int(i)] = allIds[int(i - appSize)]; | ||
432 | |||
433 | return appIds; | ||
434 | } | ||
435 | |||
436 | QArray<int> Categories::ids( const QString &app, const QStringList &cats ) const | ||
437 | { | ||
438 | QArray<int> allIds = mGlobalCats.ids( cats ); | ||
439 | QArray<int> appIds = mAppCats[app].ids( cats ); | ||
440 | |||
441 | uint appSize = appIds.size(); | ||
442 | appIds.resize( appSize + allIds.size() ); | ||
443 | for ( uint i = appSize; i < appIds.size(); ++i ) | ||
444 | appIds[int(i)] = allIds[int(i - appSize)]; | ||
445 | |||
446 | return appIds; | ||
447 | } | ||
448 | |||
449 | int Categories::id( const QString &app, const QString &cat ) const | ||
450 | { | ||
451 | if ( cat == tr("Unfiled") || cat.contains( tr(" (multi.)") ) ) | ||
452 | return 0; | ||
453 | int uid = mGlobalCats.id( cat ); | ||
454 | if ( uid != 0 ) | ||
455 | return uid; | ||
456 | return mAppCats[app].id( cat ); | ||
457 | } | ||
458 | |||
459 | |||
460 | /** Return TRUE if renaming succeeded; FALSE if app name not found, | ||
461 | * or if there was a name conflict | ||
462 | */ | ||
463 | bool Categories::renameCategory( const QString &appname, | ||
464 | const QString &oldName, | ||
465 | const QString &newName ) | ||
466 | { | ||
467 | QMap< QString, CategoryGroup >::Iterator | ||
468 | appIt = mAppCats.find( appname ); | ||
469 | |||
470 | if ( appIt != mAppCats.end() ) { | ||
471 | CategoryGroup &cats = *appIt; | ||
472 | int id = cats.id( oldName ); | ||
473 | if ( id != 0 && cats.rename( id, newName ) ) { | ||
474 | emit categoryRenamed( *this, appname, id ); | ||
475 | return TRUE; | ||
476 | } | ||
477 | } | ||
478 | return renameGlobalCategory( oldName, newName ); | ||
479 | } | ||
480 | |||
481 | bool Categories::renameGlobalCategory( const QString &oldName, | ||
482 | const QString &newName ) | ||
483 | { | ||
484 | int uid = mGlobalCats.id( oldName ); | ||
485 | if ( uid != 0 && mGlobalCats.rename( uid, newName ) ) { | ||
486 | emit categoryRenamed( *this, QString::null, uid ); | ||
487 | return TRUE; | ||
488 | } | ||
489 | return FALSE; | ||
490 | } | ||
491 | |||
492 | void Categories::setGlobal( const QString &appname, | ||
493 | const QString &catname, | ||
494 | bool global ) | ||
495 | { | ||
496 | // if in global and should be in app; then move it | ||
497 | if ( mGlobalCats.contains( catname ) && !global ) { | ||
498 | mGlobalCats.remove( catname ); | ||
499 | addCategory( appname, catname ); | ||
500 | return ; | ||
501 | } | ||
502 | |||
503 | // if in app and should be in global, then move it | ||
504 | if ( !global ) | ||
505 | return; | ||
506 | if ( removeCategory( appname, catname, FALSE ) ) | ||
507 | addGlobalCategory( catname ); | ||
508 | } | ||
509 | |||
510 | bool Categories::isGlobal( const QString &catname ) const | ||
511 | { | ||
512 | return mGlobalCats.contains( catname ); | ||
513 | } | ||
514 | |||
515 | |||
516 | /** Returns true if the catname is associated with any application | ||
517 | */ | ||
518 | bool Categories::exists( const QString &catname ) const | ||
519 | { | ||
520 | if ( isGlobal(catname) ) | ||
521 | return TRUE; | ||
522 | |||
523 | for ( QMap<QString, CategoryGroup>::ConstIterator appsIt = mAppCats.begin(); appsIt != mAppCats.end(); ++appsIt ) | ||
524 | if ( exists( appsIt.key(), catname ) ) | ||
525 | return TRUE; | ||
526 | |||
527 | return FALSE; | ||
528 | } | ||
529 | |||
530 | bool Categories::exists( const QString &appname, | ||
531 | const QString &catname) const | ||
532 | { | ||
533 | QMap< QString, CategoryGroup >::ConstIterator | ||
534 | appIt = mAppCats.find( appname ); | ||
535 | |||
536 | if ( appIt == mAppCats.end() ) | ||
537 | return FALSE; | ||
538 | |||
539 | return (*appIt).contains( catname ); | ||
540 | } | ||
541 | |||
542 | bool Categories::save( const QString &fname ) const | ||
543 | { | ||
544 | QFile file( fname ); | ||
545 | if ( !file.open( IO_WriteOnly ) ) { | ||
546 | qWarning("Unable to write to %s", fname.latin1()); | ||
547 | return FALSE; | ||
548 | } | ||
549 | |||
550 | QTextStream ts( &file ); | ||
551 | ts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; | ||
552 | ts << "<!DOCTYPE CategoryList>" << endl; | ||
553 | |||
554 | ts << "<Categories>" << endl; | ||
555 | for ( QMap<int, QString>::ConstIterator git = mGlobalCats.idMap().begin(); | ||
556 | git != mGlobalCats.idMap().end(); ++git ) | ||
557 | ts << "<Category id=\"" << git.key() << "\"" | ||
558 | << " name=\"" << escapeString(*git) << "\" />" << endl; | ||
559 | |||
560 | for ( QMap<QString, CategoryGroup>::ConstIterator appsIt=mAppCats.begin(); | ||
561 | appsIt != mAppCats.end(); ++appsIt ) { | ||
562 | const QString &app = appsIt.key(); | ||
563 | const QMap<int, QString> &appcats = (*appsIt).idMap(); | ||
564 | for ( QMap<int, QString>::ConstIterator appcatit = appcats.begin(); | ||
565 | appcatit != appcats.end(); ++appcatit ) | ||
566 | ts << "<Category id=\"" << appcatit.key() << "\"" | ||
567 | << " app=\"" << escapeString(app) << "\"" | ||
568 | << " name=\"" << escapeString(*appcatit) << "\" />" << endl; | ||
569 | } | ||
570 | ts << "</Categories>" << endl; | ||
571 | |||
572 | file.close(); | ||
573 | return TRUE; | ||
574 | } | ||
575 | |||
576 | bool Categories::load( const QString &fname ) | ||
577 | { | ||
578 | QFile file( fname ); | ||
579 | if ( !file.open( IO_ReadOnly ) ) { | ||
580 | qWarning("Unable to open %s", fname.latin1()); | ||
581 | return FALSE; | ||
582 | } | ||
583 | |||
584 | clear(); | ||
585 | QByteArray ba = file.readAll(); | ||
586 | QString data = QString::fromUtf8( ba.data(), ba.size() ); | ||
587 | QChar *uc = (QChar *)data.unicode(); | ||
588 | int len = data.length(); | ||
589 | |||
590 | // QTime t; | ||
591 | // t.start(); | ||
592 | QString name; | ||
593 | QString id; | ||
594 | QString app; | ||
595 | int i = 0; | ||
596 | while ( (i = data.find( "<Category ", i)) != -1 ) { | ||
597 | |||
598 | i += 10; | ||
599 | name = QString::null; | ||
600 | app = QString::null; | ||
601 | while ( 1 ) { | ||
602 | // skip white space | ||
603 | while ( i < len && | ||
604 | (uc[i] == ' ' || uc[i] == '\n' || uc[i] == '\r') ) | ||
605 | i++; | ||
606 | // if at the end, then done | ||
607 | if ( i >= len-2 || (uc[i] == '/' && uc[i+1] == '>') ) | ||
608 | break; | ||
609 | // we have another attribute read it. | ||
610 | int j = i; | ||
611 | while ( j < len && uc[j] != '=' ) | ||
612 | j++; | ||
613 | QString attr = QConstString( uc+i, j-i ).string(); | ||
614 | i = ++j; // skip = | ||
615 | while ( i < len && uc[i] != '"' ) | ||
616 | i++; | ||
617 | j = ++i; | ||
618 | while ( j < len && uc[j] != '"' ) | ||
619 | j++; | ||
620 | QString value = Qtopia::plainString( QConstString( uc+i, j-i ).string() ); | ||
621 | i = j + 1; | ||
622 | |||
623 | // qDebug("attr='%s' value='%s'", attr.latin1(), value.latin1() ); | ||
624 | if ( attr == "id" ) | ||
625 | id = value; | ||
626 | else if ( attr == "app" ) | ||
627 | app = value; | ||
628 | |||
629 | else if ( attr == "name" ) | ||
630 | name = value; | ||
631 | } | ||
632 | |||
633 | if ( name.isNull() || id.isNull() ) { | ||
634 | qWarning("No name or id in the category"); | ||
635 | continue; | ||
636 | } | ||
637 | if ( app.isNull() ) | ||
638 | mGlobalCats.add( id.toInt(), name ); | ||
639 | else | ||
640 | mAppCats[ app ].add( id.toInt(), name ); | ||
641 | } | ||
642 | |||
643 | return TRUE; | ||
644 | } | ||
645 | |||
646 | void Categories::clear() | ||
647 | { | ||
648 | mGlobalCats.clear(); | ||
649 | mAppCats.clear(); | ||
650 | } | ||
651 | |||
652 | void Categories::dump() const | ||
653 | { | ||
654 | qDebug("\tglobal categories = %s", mGlobalCats.labels().join(", ").latin1() ); | ||
655 | for ( QMap<QString, CategoryGroup>::ConstIterator appsIt = mAppCats.begin(); appsIt != mAppCats.end(); ++appsIt ) { | ||
656 | const QString &app = appsIt.key(); | ||
657 | QStringList appcats = (*appsIt).labels(); | ||
658 | qDebug("\tapp = %s\tcategories = %s", app.latin1(), | ||
659 | appcats.join(", ").latin1() ); | ||
660 | |||
661 | } | ||
662 | } | ||
663 | |||
664 | QStringList CheckedListView::checked() const | ||
665 | { | ||
666 | QStringList strs; | ||
667 | for ( QCheckListItem *i = (QCheckListItem *) firstChild(); | ||
668 | i; i = (QCheckListItem *)i->nextSibling() ) | ||
669 | if ( i->isOn() ) | ||
670 | strs += i->text( 0 ); | ||
671 | return strs; | ||
672 | } | ||
673 | |||
674 | void CheckedListView::addCheckableList( const QStringList &options ) | ||
675 | { | ||
676 | for ( QStringList::ConstIterator it = options.begin(); | ||
677 | it != options.end(); ++it ) { | ||
678 | (void) new QCheckListItem( this, *it, | ||
679 | QCheckListItem::CheckBox ); | ||
680 | } | ||
681 | } | ||
682 | |||
683 | void CheckedListView::setChecked( const QStringList &checked ) | ||
684 | { | ||
685 | // iterate over all items | ||
686 | bool showingChecked = FALSE; | ||
687 | for ( QCheckListItem *i = (QCheckListItem *) firstChild(); | ||
688 | i; i = (QCheckListItem *)i->nextSibling() ) | ||
689 | // see if the item should be checked by searching the | ||
690 | // checked list | ||
691 | if ( checked.find( i->text( 0 ) ) != checked.end() ) { | ||
692 | i->setOn( TRUE ); | ||
693 | // make sure it is showing at least one checked item | ||
694 | if ( !showingChecked ) { | ||
695 | ensureItemVisible( i ); | ||
696 | showingChecked = TRUE; | ||
697 | } | ||
698 | } | ||
699 | else | ||
700 | i->setOn( FALSE ); | ||
701 | } | ||