Qtopia library API Documentation

categories.cpp

00001 /**********************************************************************
00002 ** Copyright (C) 2000-2002 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of the Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 #include <qtopia/private/categories.h>
00021 #include <qtopia/stringutil.h>
00022 #include <qfile.h>
00023 #include <qcstring.h>
00024 #include <qtextstream.h>
00025 
00026 using namespace Qtopia;
00027 
00028 /***********************************************************
00029  *
00030  * CategoryGroup
00031  *
00032  **********************************************************/
00033 
00034 #ifdef PALMTOPCENTER
00035 UidGen CategoryGroup::sUidGen( UidGen::PalmtopCenter );
00036 #else
00037 UidGen CategoryGroup::sUidGen( UidGen::Qtopia );
00038 #endif
00039 
00058 int CategoryGroup::add( const QString &label )
00059 {
00060     if ( label == QObject::tr("All") || label == QObject::tr("Unfiled") )
00061     return 0;
00062 
00063     QMap<QString,int>::Iterator findIt = mLabelIdMap.find( label );
00064     if ( findIt != mLabelIdMap.end() )
00065     return 0;
00066     int newUid = uidGen().generate();
00067     insert( newUid, label );
00068     return newUid;
00069 }
00070 
00071 void CategoryGroup::insert( int uid, const QString &label )
00072 {
00073     uidGen().store( uid );
00074     mIdLabelMap[uid] = label;
00075     mLabelIdMap[label] = uid;
00076 }
00077 
00080 bool CategoryGroup::add( int uid, const QString &label )
00081 {
00082     if ( label == QObject::tr("All") || label == QObject::tr("Unfiled") )
00083     return FALSE;
00084 
00085     QMap<QString,int>::ConstIterator labelIt = mLabelIdMap.find( label );
00086     if ( labelIt != mLabelIdMap.end() )
00087     return FALSE;
00088     QMap<int,QString>::ConstIterator idIt = mIdLabelMap.find( uid );
00089     if ( idIt != mIdLabelMap.end() )
00090     return FALSE;
00091     insert( uid, label );
00092     return TRUE;
00093 }
00094 
00098 bool CategoryGroup::remove( const QString &label )
00099 {
00100     QMap<QString,int>::Iterator findIt = mLabelIdMap.find( label );
00101     if ( findIt == mLabelIdMap.end() )
00102     return FALSE;
00103 
00104     mIdLabelMap.remove( *findIt );
00105     mLabelIdMap.remove( findIt );
00106 
00107     return TRUE;
00108 }
00109 
00113 bool CategoryGroup::remove( int uid )
00114 {
00115     QMap<int,QString>::Iterator idIt = mIdLabelMap.find( uid );
00116     if ( idIt == mIdLabelMap.end() )
00117     return FALSE;
00118 
00119     mLabelIdMap.remove( *idIt );
00120     mIdLabelMap.remove( idIt );
00121 
00122     return TRUE;
00123 }
00124 
00127 bool CategoryGroup::rename( int uid, const QString &newLabel )
00128 {
00129     if ( newLabel == QObject::tr("All") || newLabel == QObject::tr("Unfiled") )
00130     return FALSE;
00131 
00132     QMap<int, QString>::Iterator idIt = mIdLabelMap.find( uid );
00133     if ( idIt == mIdLabelMap.end() )
00134     return FALSE;
00135 
00136     mLabelIdMap.remove( *idIt );
00137     mLabelIdMap[newLabel] = uid;
00138     *idIt = newLabel;
00139 
00140     return TRUE;
00141 }
00142 
00145 bool CategoryGroup::rename( const QString &oldLabel, const QString &newLabel )
00146 {
00147     return rename( id(oldLabel), newLabel );
00148 }
00149 
00151 bool CategoryGroup::contains(int uid) const
00152 {
00153     return ( mIdLabelMap.find( uid ) != mIdLabelMap.end() );
00154 }
00155 
00157 bool CategoryGroup::contains(const QString &label) const
00158 {
00159     return ( mLabelIdMap.find( label ) != mLabelIdMap.end() );
00160 }
00161 
00165 const QString &CategoryGroup::label(int uid) const
00166 {
00167     QMap<int,QString>::ConstIterator idIt = mIdLabelMap.find( uid );
00168     if ( idIt == mIdLabelMap.end() )
00169     return QString::null;
00170     return *idIt;
00171 }
00172 
00174 int CategoryGroup::id(const QString &label) const
00175 {
00176     QMap<QString,int>::ConstIterator labelIt = mLabelIdMap.find( label );
00177     if ( labelIt == mLabelIdMap.end() )
00178     return 0;
00179     return *labelIt;
00180 }
00181 
00183 QStringList CategoryGroup::labels() const
00184 {
00185     QStringList labels;
00186     for ( QMap<int, QString>::ConstIterator it = mIdLabelMap.begin();
00187       it != mIdLabelMap.end(); ++it )
00188     labels += *it;
00189     // ### I don't think this is the place for this...
00190 //    labels.sort();
00191     return labels;
00192 }
00193 
00195 QStringList CategoryGroup::labels(const QArray<int> &catids ) const
00196 {
00197     QStringList labels;
00198     if ( catids.count() == 0 )
00199     return labels;
00200     for ( QMap<int, QString>::ConstIterator it = mIdLabelMap.begin();
00201       it != mIdLabelMap.end(); ++it )
00202     if ( catids.find( it.key() ) != -1 )
00203         labels += *it;
00204     return labels;
00205 }
00206 
00207 /***********************************************************
00208  *
00209  * Categories
00210  *
00211  **********************************************************/
00212 
00256 int Categories::addCategory( const QString &appname,
00257                  const QString &catname,
00258                  int uid )
00259 {
00260     if ( mGlobalCats.contains(catname) )
00261     return 0;
00262 
00263     QMap< QString, CategoryGroup >::Iterator
00264     appIt = mAppCats.find( appname );
00265 
00266     if ( appIt == mAppCats.end() ) {
00267     CategoryGroup newgroup;
00268     newgroup.add( uid, catname );
00269     mAppCats.insert( appname, newgroup );
00270     emit categoryAdded( *this, appname, uid );
00271     return uid;
00272     }
00273 
00274     CategoryGroup &cats = *appIt;
00275     cats.add( uid, catname );
00276     emit categoryAdded( *this, appname, uid );
00277     return uid;
00278 }
00279 
00285 int Categories::addCategory( const QString &appname,
00286                  const QString &catname )
00287 {
00288      if ( mGlobalCats.contains(catname) )
00289     return 0;
00290 
00291     QMap< QString, CategoryGroup >::Iterator
00292     appIt = mAppCats.find( appname );
00293 
00294     if ( appIt == mAppCats.end() ) {
00295     CategoryGroup newgroup;
00296     int uid = newgroup.add( catname );
00297     mAppCats.insert( appname, newgroup );
00298     emit categoryAdded( *this, appname, uid );
00299     return uid;
00300     }
00301 
00302     CategoryGroup &cats = *appIt;
00303     int uid = cats.add( catname );
00304     if ( !uid )
00305     return 0;
00306     emit categoryAdded( *this, appname, uid );
00307     return uid;
00308 }
00309 
00313 int Categories::addGlobalCategory( const QString &catname, int uid )
00314 {
00315     mGlobalCats.add( uid, catname );
00316     emit categoryAdded( *this, QString::null, uid );
00317     return uid;
00318 }
00319 
00326 int Categories::addGlobalCategory( const QString &catname )
00327 {
00328     int uid = mGlobalCats.add( catname );
00329     if ( !uid )
00330     return 0;
00331     emit categoryAdded( *this, QString::null, uid );
00332     return uid;
00333 }
00334 
00341 bool Categories::removeCategory( const QString &appname,
00342                  const QString &catname,
00343                  bool checkGlobal )
00344 {
00345     QMap< QString, CategoryGroup >::Iterator
00346     appIt = mAppCats.find( appname );
00347     if ( appIt != mAppCats.end() ) {
00348     CategoryGroup &cats = *appIt;
00349     int uid = cats.id( catname );
00350     if ( cats.remove( uid ) ) {
00351         emit categoryRemoved( *this, appname, uid );
00352         return TRUE;
00353     }
00354     }
00355     if ( !checkGlobal )
00356     return FALSE;
00357     return removeGlobalCategory( catname );
00358 }
00359 
00360 
00365 bool Categories::removeCategory( const QString &appname, int uid )
00366 {
00367     QMap< QString, CategoryGroup >::Iterator
00368     appIt = mAppCats.find( appname );
00369     if ( appIt != mAppCats.end() ) {
00370     CategoryGroup &cats = *appIt;
00371     if ( cats.remove( uid ) ) {
00372         emit categoryRemoved( *this, appname, uid );
00373         return TRUE;
00374     }
00375     }
00376     return FALSE;
00377 }
00378 
00383 bool Categories::removeGlobalCategory( const QString &catname )
00384 {
00385     int uid = mGlobalCats.id( catname );
00386     if ( mGlobalCats.remove( uid ) ) {
00387     emit categoryRemoved( *this, QString::null, uid );
00388     return TRUE;
00389     }
00390     return FALSE;
00391 }
00392 
00397 bool Categories::removeGlobalCategory( int uid )
00398 {
00399      if ( mGlobalCats.remove( uid ) ) {
00400     emit categoryRemoved( *this, QString::null, uid );
00401     return TRUE;
00402     }
00403     return FALSE;
00404 }
00405 
00411 QStringList Categories::labels( const QString &app,
00412                 bool includeGlobal,
00413                 ExtraLabels extra ) const
00414 {
00415     QMap< QString, CategoryGroup >::ConstIterator
00416     appIt = mAppCats.find( app );
00417     QStringList cats;
00418 
00419     if ( appIt != mAppCats.end() )
00420     cats += (*appIt).labels();
00421     //else qDebug("Categories::labels didn't find app %s", app.latin1() );
00422     if ( includeGlobal )
00423     cats += mGlobalCats.labels();
00424 
00425     cats.sort();
00426     switch ( extra ) {
00427     case NoExtra: break;
00428     case AllUnfiled:
00429     cats.append( tr("All") );
00430     cats.append( tr("Unfiled") );
00431     break;
00432     case AllLabel:
00433     cats.append( tr("All") );
00434     break;
00435     case UnfiledLabel:
00436     cats.append( tr("Unfiled") );
00437     break;
00438     }
00439 
00440     return cats;
00441 }
00442 
00446 QString Categories::label( const QString &app, int id ) const
00447 {
00448     if ( mGlobalCats.contains( id ) )
00449     return mGlobalCats.label( id );
00450     QMap< QString, CategoryGroup >::ConstIterator
00451     appIt = mAppCats.find( app );
00452     if ( appIt == mAppCats.end() )
00453     return QString::null;
00454     return (*appIt).label( id );
00455 }
00456 
00468 QString Categories::displaySingle( const QString &app,
00469                    const QArray<int> &catids,
00470                    DisplaySingle display ) const
00471 {
00472     QStringList strs = labels( app, catids );
00473     if ( !strs.count() )
00474     return tr("Unfiled");
00475     strs.sort();
00476     QString r;
00477     if ( strs.count() > 1 ) {
00478     switch ( display ) {
00479     case ShowFirst:
00480         r = strs.first();
00481         break;
00482     case ShowMulti:
00483         r = strs.first() + tr(" (multi.)");
00484         break;
00485     case ShowAll:
00486         r = strs.join(" ");
00487         break;
00488     }
00489     }
00490     else r = strs.first();
00491     return r;
00492 }
00493 
00499 QArray<int> Categories::ids( const QString &app, const QStringList &labels) const
00500 {
00501   QArray<int> results;
00502   QStringList::ConstIterator it;
00503   int i;
00504 
00505   for ( i=0, it=labels.begin(); it!=labels.end(); i++, ++it ) {
00506     int value = id( app, *it );
00507     if ( value != 0 ) {
00508       int tmp = results.size();
00509       results.resize( tmp + 1 );
00510       results[ tmp ] = value;
00511     }
00512   }
00513   return results;
00514 }
00515 
00521 int Categories::id( const QString &app, const QString &cat ) const
00522 {
00523     if ( cat == tr("Unfiled") || cat.contains( tr(" (multi.)") ) )
00524     return 0;
00525     int uid = mGlobalCats.id( cat );
00526     if ( uid != 0 )
00527     return uid;
00528     return mAppCats[app].id( cat );
00529 }
00530 
00531 
00540 bool Categories::renameCategory( const QString &appname,
00541                  const QString &oldName,
00542                  const QString &newName )
00543 {
00544     QMap< QString, CategoryGroup >::Iterator
00545     appIt = mAppCats.find( appname );
00546 
00547     if ( appIt != mAppCats.end() ) {
00548     CategoryGroup &cats = *appIt;
00549     int id = cats.id( oldName );
00550     if ( id != 0 && cats.rename( id, newName ) ) {
00551         emit categoryRenamed( *this, appname, id );
00552         return TRUE;
00553     }
00554     }
00555     return renameGlobalCategory( oldName, newName );
00556 }
00557 
00564 bool Categories::renameGlobalCategory( const QString &oldName,
00565                        const QString &newName )
00566 {
00567     int uid = mGlobalCats.id( oldName );
00568     if ( uid != 0 && mGlobalCats.rename( uid, newName ) ) {
00569     emit categoryRenamed( *this, QString::null, uid );
00570     return TRUE;
00571     }
00572     return FALSE;
00573 }
00574 
00579 void Categories::setGlobal( const QString &appname,
00580                 const QString &catname,
00581                 bool global )
00582 {
00583     // if in global and should be in app; then move it
00584     if ( mGlobalCats.contains( catname ) && !global ) {
00585     mGlobalCats.remove( catname );
00586     addCategory( appname, catname );
00587     return ;
00588     }
00589 
00590     // if in app and should be in global, then move it
00591     if ( !global )
00592     return;
00593     if ( removeCategory( appname, catname, FALSE ) )
00594     addGlobalCategory( catname );
00595 }
00596 
00600 bool Categories::isGlobal( const QString &catname ) const
00601 {
00602     return mGlobalCats.contains( catname );
00603 }
00604 
00605 
00610 bool Categories::exists( const QString &catname ) const
00611 {
00612     if ( isGlobal(catname) )
00613     return TRUE;
00614 
00615     for ( QMap<QString, CategoryGroup>::ConstIterator appsIt = mAppCats.begin(); appsIt != mAppCats.end(); ++appsIt )
00616     if ( exists( appsIt.key(), catname ) )
00617         return TRUE;
00618 
00619     return FALSE;
00620 }
00621 
00626 bool Categories::exists( const QString &appname,
00627              const QString &catname) const
00628 {
00629     QMap< QString, CategoryGroup >::ConstIterator
00630     appIt = mAppCats.find( appname );
00631 
00632     if ( appIt == mAppCats.end() )
00633     return FALSE;
00634 
00635     return (*appIt).contains( catname );
00636 }
00637 
00644 bool Categories::save( const QString &fname ) const
00645 {
00646     QString strNewFile = fname + ".new";
00647     QFile f( strNewFile );
00648     QString out;
00649     int total_written;
00650 
00651     if ( !f.open( IO_WriteOnly|IO_Raw ) ) {
00652     qWarning("Unable to write to %s", fname.latin1());
00653     return FALSE;
00654     }
00655 
00656     out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
00657     out += "<!DOCTYPE CategoryList>\n";
00658 
00659     out += "<Categories>\n";
00660 
00661     for ( QMap<int, QString>::ConstIterator git = mGlobalCats.idMap().begin();
00662       git != mGlobalCats.idMap().end(); ++git )
00663     out += "<Category id=\"" + QString::number(git.key()) + "\"" +
00664       " name=\"" + escapeString(*git) + "\" />\n";
00665 
00666     for ( QMap<QString, CategoryGroup>::ConstIterator appsIt=mAppCats.begin();
00667       appsIt != mAppCats.end(); ++appsIt ) {
00668     const QString &app = appsIt.key();
00669     const QMap<int, QString> &appcats = (*appsIt).idMap();
00670     for ( QMap<int, QString>::ConstIterator appcatit = appcats.begin();
00671           appcatit != appcats.end(); ++appcatit )
00672         out += "<Category id=\"" + QString::number(appcatit.key()) + "\"" +
00673           " app=\"" + escapeString(app) + "\"" +
00674           " name=\"" + escapeString(*appcatit) + "\" />\n";
00675     }
00676     out += "</Categories>\n";
00677 
00678     QCString cstr = out.utf8();
00679     total_written = f.writeBlock( cstr.data(), cstr.length() );
00680     if ( total_written != int(cstr.length()) ) {
00681     f.close();
00682     QFile::remove( strNewFile );
00683     return FALSE;
00684     }
00685     f.close();
00686 
00687 #ifdef Q_OS_WIN32
00688     QFile::remove( fname );
00689 #endif
00690     if ( ::rename( strNewFile.latin1(), fname.latin1() ) < 0 ) {
00691     qWarning( "problem renaming file %s to %s",
00692           strNewFile.latin1(), fname.latin1());
00693     // remove the tmp file...
00694     QFile::remove( strNewFile );
00695     }
00696 
00697     return TRUE;
00698 }
00699 
00706 bool Categories::load( const QString &fname )
00707 {
00708     QFile file( fname );
00709     if ( !file.open( IO_ReadOnly ) ) {
00710     qWarning("Unable to open %s", fname.latin1());
00711 
00712     addGlobalCategory(tr("Business"));
00713     addGlobalCategory(tr("Personal"));
00714     save(fname);
00715 
00716     return FALSE;
00717     }
00718 
00719     clear();
00720     QByteArray ba = file.readAll();
00721     QString data = QString::fromUtf8( ba.data(), ba.size() );
00722     QChar *uc = (QChar *)data.unicode();
00723     int len = data.length();
00724 
00725     //     QTime t;
00726     //     t.start();
00727     QString name;
00728     QString id;
00729     QString app;
00730     int i = 0;
00731     while ( (i = data.find( "<Category ",  i)) != -1 ) {
00732 
00733     i += 10;
00734     name = QString::null;
00735     app = QString::null;
00736     while ( 1 ) {
00737         // skip white space
00738         while ( i < len &&
00739             (uc[i] == ' ' || uc[i] == '\n' || uc[i] == '\r') )
00740         i++;
00741         // if at the end, then done
00742         if ( i >= len-2 || (uc[i] == '/' && uc[i+1] == '>') )
00743         break;
00744         // we have another attribute read it.
00745         int j = i;
00746         while ( j < len && uc[j] != '=' )
00747         j++;
00748         QString attr = QConstString( uc+i, j-i ).string();
00749         i = ++j; // skip =
00750         while ( i < len && uc[i] != '"' )
00751         i++;
00752         j = ++i;
00753         while ( j < len && uc[j] != '"' )
00754         j++;
00755         QString value = Qtopia::plainString( QConstString( uc+i, j-i ).string() );
00756         i = j + 1;
00757 
00758 //          qDebug("attr='%s' value='%s'", attr.latin1(), value.latin1() );
00759         if ( attr == "id" )
00760         id = value;
00761         else if ( attr == "app" )
00762         app = value;
00763 
00764         else if ( attr == "name" )
00765         name = value;
00766     }
00767 
00768     if ( name.isNull() || id.isNull() ) {
00769         qWarning("No name or id in the category");
00770         continue;
00771     }
00772     if ( app.isNull() )
00773         mGlobalCats.add( id.toInt(), name );
00774     else
00775         mAppCats[ app ].add( id.toInt(), name );
00776     }
00777 
00778     return TRUE;
00779 }
00780 
00785 void Categories::clear()
00786 {
00787     mGlobalCats.clear();
00788     mAppCats.clear();
00789 }
00790 
00794 void Categories::dump() const
00795 {
00796     qDebug("\tglobal categories = %s", mGlobalCats.labels().join(", ").latin1() );
00797     for ( QMap<QString, CategoryGroup>::ConstIterator appsIt = mAppCats.begin(); appsIt != mAppCats.end(); ++appsIt ) {
00798     const QString &app = appsIt.key();
00799     QStringList appcats = (*appsIt).labels();
00800     qDebug("\tapp = %s\tcategories = %s", app.latin1(),
00801            appcats.join(", ").latin1() );
00802 
00803     }
00804 }
00805 
00806 QStringList CheckedListView::checked() const
00807 {
00808     QStringList strs;
00809     for ( QCheckListItem *i = (QCheckListItem *) firstChild();
00810       i; i = (QCheckListItem *)i->nextSibling() )
00811     if ( i->isOn() )
00812         strs += i->text( 0 );
00813     return strs;
00814 }
00815 
00816 void CheckedListView::addCheckableList( const QStringList &options )
00817 {
00818     for ( QStringList::ConstIterator it = options.begin();
00819       it != options.end(); ++it ) {
00820     (void) new QCheckListItem( this, *it,
00821                    QCheckListItem::CheckBox );
00822     }
00823 }
00824 
00825 void CheckedListView::setChecked( const QStringList &checked )
00826 {
00827     // iterate over all items
00828     bool showingChecked = FALSE;
00829     for ( QCheckListItem *i = (QCheckListItem *) firstChild();
00830       i; i = (QCheckListItem *)i->nextSibling() )
00831     // see if the item should be checked by searching the
00832     // checked list
00833     if ( checked.find( i->text( 0 ) ) != checked.end() ) {
00834        i->setOn( TRUE );
00835        // make sure it is showing at least one checked item
00836        if ( !showingChecked ) {
00837            ensureItemVisible( i );
00838            showingChecked = TRUE;
00839        }
00840     }
00841        else
00842        i->setOn( FALSE );
00843 }
00844 
00933 /* ### FIXME properly merge */
00934 QStringList Categories::labels( const QString & app, const QArray<int> &catids ) const
00935 {
00936     QStringList strs = mGlobalCats.labels( catids );
00937     strs += mAppCats[app].labels( catids );
00938     return strs;
00939 }
KDE Logo
This file is part of the documentation for OPIE Version 1.5.5.
Documentation copyright © 1997-2003 the KDE developers. 2003 OPIE developers
Generated on Tue Feb 10 20:24:03 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001