Qtopia library API Documentation

applnk.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 
00021 #define QTOPIA_INTERNAL_MIMEEXT
00022 #define QTOPIA_INTERNAL_PRELOADACCESS
00023 #define QTOPIA_INTERNAL_APPLNKASSIGN
00024 
00025 #include "applnk.h"
00026 
00027 #include <qpe/qpeapplication.h>
00028 #include <qpe/categories.h>
00029 #include <qpe/categoryselect.h>
00030 #include <qpe/qcopenvelope_qws.h>
00031 #include <qpe/global.h>
00032 #include <qpe/mimetype.h>
00033 #include <qpe/config.h>
00034 #include <qpe/storage.h>
00035 #include <qpe/resource.h>
00036 
00037 #include <qdict.h>
00038 #include <qdir.h>
00039 #include <qregexp.h>
00040 
00041 #include <qgfx_qws.h>
00042 
00043 #include <stdlib.h>
00044 
00045 int AppLnk::lastId = 5000;
00046 
00047 static int smallSize = 14;
00048 static int bigSize = 32;
00049 
00050 static QString safeFileName(const QString& n)
00051 {
00052  QString safename=n;
00053     safename.replace(QRegExp("[^0-9A-Za-z.]"),"_");
00054     safename.replace(QRegExp("^[^A-Za-z]*"),"");
00055     if ( safename.isEmpty() )
00056   safename = "_";
00057     return safename;
00058 }
00059 
00060 static bool prepareDirectories(const QString& lf)
00061 {
00062     if ( !QFile::exists(lf) ) {
00063   // May need to create directories
00064   QFileInfo fi(lf);
00065   if ( system(("mkdir -p "+fi.dirPath(TRUE))) )
00066       return FALSE;
00067     }
00068     return TRUE;
00069 }
00070 
00071 class AppLnkPrivate
00072 {
00073 public:
00074     /* the size of the Pixmap */
00075     enum Size {Normal = 0, Big };
00076     AppLnkPrivate() {
00077         /* we want one normal and one big item */
00078 
00079         QPixmap pix;
00080         mPixmaps.insert(0, pix );
00081         mPixmaps.insert(1,  pix);
00082     }
00083 
00084     QStringList mCatList; // always correct
00085     QArray<int> mCat; // cached value; correct if not empty
00086     QMap<int,  QPixmap> mPixmaps;
00087 
00088     void updateCatListFromArray()
00089     {
00090   Categories cat( 0 );
00091   cat.load( categoryFileName() );
00092   // we need to update the names for the mCat... to mCatList
00093         mCatList.clear();
00094         for (uint i = 0; i < mCat.count(); i++ )
00095             mCatList << cat.label("Document View", mCat[i] );
00096 
00097     }
00098 
00099     void setCatArrayDirty()
00100     {
00101   mCat.resize(0);
00102     }
00103 
00104     void ensureCatArray()
00105     {
00106   if ( mCat.count() > 0 || mCatList.count()==0 )
00107       return;
00108 
00109   Categories cat( 0 );
00110   cat.load( categoryFileName() );
00111   mCat.resize( mCatList.count() );
00112   int i;
00113   QStringList::ConstIterator it;
00114   for ( i = 0, it = mCatList.begin(); it != mCatList.end();
00115         ++it, i++ ) {
00116 
00117       bool number;
00118       int id = (*it).toInt( &number );
00119       if ( !number ) {
00120     id = cat.id( "Document View", *it );
00121     if ( id == 0 )
00122         id = cat.addCategory( "Document View", *it );
00123       }
00124       mCat[i] = id;
00125   }
00126     }
00127 };
00128 
00229 void AppLnk::setSmallIconSize(int small)
00230 {
00231     smallSize = small;
00232 }
00233 
00239 int AppLnk::smallIconSize()
00240 {
00241     return smallSize;
00242 }
00243 
00244 
00251 void AppLnk::setBigIconSize(int big)
00252 {
00253     bigSize = big;
00254 }
00255 
00261 int AppLnk::bigIconSize()
00262 {
00263     return bigSize;
00264 }
00265 
00266 
00314 const QArray<int>& AppLnk::categories() const
00315 {
00316     d->ensureCatArray();
00317     return d->mCat;
00318 }
00319 
00357 AppLnk::AppLnk()
00358 {
00359     mId = 0;
00360     d = new AppLnkPrivate();
00361 }
00362 
00368 AppLnk::AppLnk( const QString &file )
00369 {
00370     QStringList sl;
00371     d = new AppLnkPrivate();
00372     if ( !file.isNull() ) {
00373   Config config( file, Config::File );
00374 
00375   if ( config.isValid() ) {
00376       config.setGroup( "Desktop Entry" );
00377 
00378       mName = config.readEntry( "Name", file );
00379       mExec = config.readEntry( "Exec" );
00380       mType = config.readEntry( "Type", QString::null );
00381       mIconFile = config.readEntry( "Icon", QString::null );
00382       mRotation = config.readEntry( "Rotation", "" );
00383       mComment = config.readEntry( "Comment", QString::null );
00384       // MIME types are case-insensitive.
00385       mMimeTypes = config.readListEntry( "MimeType", ';' );
00386       for (QStringList::Iterator it=mMimeTypes.begin(); it!=mMimeTypes.end(); ++it)
00387     *it = (*it).lower();
00388       mMimeTypeIcons = config.readListEntry( "MimeTypeIcons", ';' );
00389       mLinkFile = file;
00390       mFile = config.readEntry("File", QString::null);
00391       if ( !mExec. isEmpty ( )) {
00392     mFile = QString::null;
00393       }
00394       else if ( mFile[0] != '/' ) {
00395     int slash = file.findRev('/');
00396     if ( slash >= 0 ) {
00397         mFile = file.left(slash) + '/' + mFile;
00398     }
00399       }
00400       d->mCatList = config.readListEntry("Categories", ';');
00401       if ( d->mCatList[0].toInt() < -1 ) {
00402     // numeric cats in file! convert to text
00403     Categories cat( 0 );
00404     cat.load( categoryFileName() );
00405     d->mCat.resize( d->mCatList.count() );
00406     int i;
00407     QStringList::ConstIterator it;
00408     for ( i = 0, it = d->mCatList.begin(); it != d->mCatList.end();
00409           ++it, i++ ) {
00410         bool number;
00411         int id = (*it).toInt( &number );
00412         if ( !number ) {
00413       // convert from text
00414       id = cat.id( "Document View", *it );
00415       if ( id == 0 )
00416           id = cat.addCategory( "Document View", *it );
00417         }
00418         d->mCat[i] = id;
00419     }
00420     d->updateCatListFromArray();
00421       }
00422   }
00423     }
00424     mId = 0;
00425 }
00426 
00427 AppLnk& AppLnk::operator=(const AppLnk &copy)
00428 {
00429     if ( this == &copy ) return *this;
00430     if ( mId )
00431   qWarning("Deleting AppLnk that is in an AppLnkSet");
00432     if ( d )
00433   delete d;
00434 
00435 
00436     mName = copy.mName;
00437 
00438     /* remove for Qtopia 3.0 -zecke */
00439     mPixmap = copy.mPixmap;
00440     mBigPixmap = copy.mBigPixmap;
00441 
00442     mExec = copy.mExec;
00443     mType = copy.mType;
00444     mRotation = copy.mRotation;
00445     mComment = copy.mComment;
00446     mFile = copy.mFile;
00447     mLinkFile = copy.mLinkFile;
00448     mIconFile = copy.mIconFile;
00449     mMimeTypes = copy.mMimeTypes;
00450     mMimeTypeIcons = copy.mMimeTypeIcons;
00451     mId = 0;
00452     d = new AppLnkPrivate();
00453     d->mCat = copy.d->mCat;
00454     d->mCatList = copy.d->mCatList;
00455     d->mPixmaps = copy.d->mPixmaps;
00456 
00457     return *this;
00458 }
00464 const QPixmap& AppLnk::pixmap( int pos, int size ) const {
00465     if ( d->mPixmaps[pos].isNull() ) {
00466   AppLnk* that = (AppLnk*)this;
00467   if ( mIconFile.isEmpty() ) {
00468       MimeType mt(type());
00469       that->d->mPixmaps[pos] = pos ? mt.bigPixmap() : mt.pixmap();
00470       if ( that->d->mPixmaps[pos].isNull() )
00471     that->d->mPixmaps[pos].convertFromImage(
00472         Resource::loadImage("UnknownDocument")
00473       .smoothScale( size, size ) );
00474       return that->d->mPixmaps[pos];
00475   }
00476   QImage unscaledIcon = Resource::loadImage( that->mIconFile );
00477   if ( unscaledIcon.isNull() ) {
00478     //  qDebug( "Cannot find icon: %s", that->mIconFile.latin1() );
00479       that->d->mPixmaps[pos].convertFromImage(
00480         Resource::loadImage("UnknownDocument")
00481       .smoothScale( size, size ) );
00482   } else {
00483       that->d->mPixmaps[0].convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) );
00484       that->d->mPixmaps[1].convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) );
00485   }
00486   return that->d->mPixmaps[pos];
00487     }
00488     return d->mPixmaps[pos];
00489 }
00490 
00496 const QPixmap& AppLnk::pixmap() const
00497 {
00498     if ( d->mPixmaps[0].isNull() ) {
00499         return pixmap(AppLnkPrivate::Normal, smallSize );
00500     }
00501     return d->mPixmaps[0];
00502 }
00503 
00509 const QPixmap& AppLnk::bigPixmap() const
00510 {
00511     if ( d->mPixmaps[1].isNull() ) {
00512         return pixmap( AppLnkPrivate::Big, bigSize );
00513     }
00514     return d->mPixmaps[1];
00515 }
00516 
00522 QString AppLnk::type() const
00523 {
00524     if ( mType.isNull() ) {
00525   AppLnk* that = (AppLnk*)this;
00526   QString f = file();
00527   if ( !f.isNull() ) {
00528       MimeType mt(f);
00529       that->mType = mt.id();
00530       return that->mType;
00531   }
00532     }
00533     return mType;
00534 }
00535 
00541 QString AppLnk::file() const
00542 {
00543     if ( mExec.isEmpty ( ) && mFile.isNull() ) {
00544   AppLnk* that = (AppLnk*)this;
00545   QString ext = MimeType(mType).extension();
00546   if ( !ext.isEmpty() )
00547       ext = "." + ext;
00548   if ( !mLinkFile.isEmpty() ) {
00549       that->mFile =
00550     mLinkFile.right(8)==".desktop" // 8 = strlen(".desktop")
00551         ? mLinkFile.left(mLinkFile.length()-8) : mLinkFile;
00552   qDebug("mFile now == %s", mFile.latin1());
00553   } else if ( mType.contains('/') ) {
00554       that->mFile =
00555     QString(getenv("HOME"))+"/Documents/"+mType+"/"+safeFileName(that->mName);
00556             /*
00557              * A file with the same name or a .desktop file already exists
00558              */
00559       if ( QFile::exists(that->mFile+ext) || QFile::exists(that->mFile+".desktop") ) {
00560     int n=1;
00561     QString nn;
00562     while (QFile::exists((nn=(that->mFile+"_"+QString::number(n)))+ext)
00563       || QFile::exists(nn+".desktop"))
00564         n++;
00565     that->mFile = nn;
00566       }
00567       that->mLinkFile = that->mFile+".desktop";
00568       that->mFile += ext;
00569   }
00570   prepareDirectories(that->mFile);
00571   if ( !that->mFile.isEmpty() ) {
00572       QFile f(that->mFile);
00573       if ( !f.open(IO_WriteOnly) )
00574     that->mFile = QString::null;
00575       return that->mFile;
00576   }
00577     }
00578     return mFile;
00579 }
00580 
00586 QString AppLnk::linkFile() const
00587 {
00588     if ( mLinkFile.isNull() ) {
00589   AppLnk* that = (AppLnk*)this;
00590   if ( type().contains('/') ) {
00591       StorageInfo storage;
00592       const FileSystem *fs = storage.fileSystemOf( that->mFile );
00593             /* tmpfs + and ramfs are available too but not removable
00594              * either we fix storage or add this
00595              */
00596       if ( fs && ( fs->isRemovable() || fs->disk() == "/dev/mtdblock6" || fs->disk() == "tmpfs") ) {
00597     that->mLinkFile = fs->path();
00598       } else
00599     that->mLinkFile = getenv( "HOME" );
00600       that->mLinkFile += "/Documents/"+type()+"/"+safeFileName(that->mName);
00601 
00602             /* the desktop file exists make sure we don't point to the same file */
00603       if ( QFile::exists(that->mLinkFile+".desktop") ) {
00604                 AppLnk lnk( that->mLinkFile + ".desktop" );
00605 
00606                 /* the linked is different */
00607                 if(that->file() != lnk.file() ) {
00608                     int n = 1;
00609                     QString nn;
00610                     while (QFile::exists((nn=that->mLinkFile+"_"+QString::number(n))+".desktop")) {
00611                         n++;
00612                         /* just to be sure */
00613                         AppLnk lnk(nn );
00614                         if (lnk.file() == that->file() )
00615                             break;
00616                     }
00617                     that->mLinkFile = nn;
00618                 }
00619       }
00620       that->mLinkFile += ".desktop";
00621       storeLink();
00622   }
00623   return that->mLinkFile;
00624     }
00625     return mLinkFile;
00626 }
00627 
00631 AppLnk::AppLnk( const AppLnk &copy )
00632 {
00633     mName = copy.mName;
00634     mPixmap = copy.mPixmap;
00635     mBigPixmap = copy.mBigPixmap;
00636     mExec = copy.mExec;
00637     mType = copy.mType;
00638     mRotation = copy.mRotation;
00639     mComment = copy.mComment;
00640     mFile = copy.mFile;
00641     mLinkFile = copy.mLinkFile;
00642     mIconFile = copy.mIconFile;
00643     mMimeTypes = copy.mMimeTypes;
00644     mMimeTypeIcons = copy.mMimeTypeIcons;
00645     mId = 0;
00646     d = new AppLnkPrivate();
00647     d->mCat = copy.d->mCat;
00648     d->mCatList = copy.d->mCatList;
00649     d->mPixmaps = copy.d->mPixmaps;
00650 }
00651 
00658 AppLnk::~AppLnk()
00659 {
00660     if ( mId )
00661   qWarning("Deleting AppLnk that is in an AppLnkSet");
00662     if ( d )
00663   delete d;
00664 }
00665 
00672 void AppLnk::execute() const
00673 {
00674     execute(QStringList());
00675 }
00676 
00683 void AppLnk::execute(const QStringList& args) const
00684 {
00685 #ifdef Q_WS_QWS
00686     if ( !mRotation.isEmpty() ) {
00687   // ######## this will only work in the server
00688   int rot = QPEApplication::defaultRotation();
00689   rot = (rot+mRotation.toInt())%360;
00690   QCString old = getenv("QWS_DISPLAY");
00691   setenv("QWS_DISPLAY", QString("Transformed:Rot%1:0").arg(rot), 1);
00692   invoke(args);
00693   setenv("QWS_DISPLAY", old.data(), 1);
00694     } else
00695 #endif
00696   invoke(args);
00697 }
00698 
00706 void AppLnk::invoke(const QStringList& args) const
00707 {
00708     Global::execute( exec(), args[0] );
00709 }
00710 
00716 void AppLnk::setExec( const QString& exec )
00717 {
00718     mExec = exec;
00719 }
00720 
00721 #if 0 // this was inlined for better BC
00722 
00727 void AppLnk::setRotation ( const QString &rot )
00728 {
00729   mRotation = rot;
00730 }
00731 #endif
00732 
00738 void AppLnk::setName( const QString& docname )
00739 {
00740     mName = docname;
00741 }
00742 
00748 void AppLnk::setFile( const QString& filename )
00749 {
00750     mFile = filename;
00751 }
00752 
00758 void AppLnk::setLinkFile( const QString& filename )
00759 {
00760     mLinkFile = filename;
00761 }
00762 
00771 void AppLnk::setComment( const QString& comment )
00772 {
00773     mComment = comment;
00774 }
00775 
00785 void AppLnk::setType( const QString& type )
00786 {
00787     mType = type;
00788 }
00789 
00804 void AppLnk::setIcon( const QString& iconname )
00805 {
00806     mIconFile = iconname;
00807     QImage unscaledIcon = Resource::loadImage( mIconFile );
00808     d->mPixmaps[0].convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) );
00809     d->mPixmaps[1].convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) );
00810 }
00811 
00819 void AppLnk::setCategories( const QArray<int>& c )
00820 {
00821     d->mCat = c;
00822     d->updateCatListFromArray();
00823 }
00824 
00838 bool AppLnk::ensureLinkExists() const
00839 {
00840     QString lf = linkFile();
00841     return prepareDirectories(lf);
00842 }
00843 
00851 bool AppLnk::writeLink() const
00852 {
00853     // Only re-writes settable parts
00854     QString lf = linkFile();
00855     if ( !ensureLinkExists() )
00856   return FALSE;
00857     storeLink();
00858     return TRUE;
00859 }
00860 
00864 void AppLnk::storeLink() const
00865 {
00866     Config config( mLinkFile, Config::File );
00867     config.setGroup("Desktop Entry");
00868     config.writeEntry("Name",mName);
00869     if ( !mIconFile.isNull() ) config.writeEntry("Icon",mIconFile);
00870     config.writeEntry("Type",type());
00871     if(!rotation().isEmpty())
00872   config.writeEntry("Rotation",rotation());
00873     else
00874   config.removeEntry("Rotation");
00875     if ( !mComment.isNull() ) config.writeEntry("Comment",mComment);
00876     QString f = file();
00877     int i = 0;
00878     while ( i < (int)f.length() && i < (int)mLinkFile.length() && f[i] == mLinkFile[i] )
00879   i++;
00880     while ( i && f[i] != '/' )
00881   i--;
00882     // simple case where in the same directory
00883     if ( mLinkFile.find( '/', i + 1 ) < 0 )
00884   f = f.mid(i+1);
00885     // ### could do relative ie ../../otherDocs/file.doc
00886     config.writeEntry("File",f);
00887     config.writeEntry( "Categories", d->mCatList, ';' );
00888 
00889 #ifndef QT_NO_COP
00890     QCopEnvelope e("QPE/System", "linkChanged(QString)");
00891     e << mLinkFile;
00892 #endif
00893 }
00894 
00900 void AppLnk::setProperty(const QString& key, const QString& value)
00901 {
00902     if ( ensureLinkExists() ) {
00903   Config cfg(linkFile(), Config::File);
00904   cfg.writeEntry(key,value);
00905     }
00906 }
00907 
00913 QString AppLnk::property(const QString& key) const
00914 {
00915     QString lf = linkFile();
00916     if ( !QFile::exists(lf) )
00917   return QString::null;
00918     Config cfg(lf, Config::File);
00919     return cfg.readEntry(key);
00920 }
00921 
00922 bool AppLnk::isPreloaded() const {
00923   // Preload information is stored in the Launcher config in v1.5.
00924   Config cfg("Launcher");
00925   cfg.setGroup("Preload");
00926   QStringList apps = cfg.readListEntry("Apps",',');
00927   if (apps.contains(exec()))
00928     return true;
00929   return false;
00930 }
00931 
00932 void AppLnk::setPreloaded(bool yesNo) {
00933   // Preload information is stored in the Launcher config in v1.5.
00934   Config cfg("Launcher");
00935   cfg.setGroup("Preload");
00936   QStringList apps = cfg.readListEntry("Apps", ',');
00937   if (apps.contains(exec()) && !yesNo)
00938     apps.remove(exec());
00939   else if (yesNo && !apps.contains(exec()))
00940     apps.append(exec());
00941   cfg.writeEntry("Apps", apps, ',');
00942 }
00943 
00944 
00950 void AppLnk::removeFiles()
00951 {
00952     bool valid = isValid();
00953     if ( !valid || !linkFileKnown() || QFile::remove(linkFile()) ) {
00954   if ( QFile::remove(file()) ) {
00955 #ifndef QT_NO_COP
00956       QCopEnvelope e("QPE/System", "linkChanged(QString)");
00957       if ( linkFileKnown() )
00958     e << linkFile();
00959       else
00960     e << file();
00961 #endif
00962   } else if ( valid ) {
00963       // restore link
00964       writeLink();
00965   }
00966     }
00967 }
00968 
00974 void AppLnk::removeLinkFile()
00975 {
00976     if ( isValid() && linkFileKnown() && QFile::remove(linkFile()) ) {
00977 #ifndef QT_NO_COP
00978   QCopEnvelope e("QPE/System", "linkChanged(QString)");
00979   e << linkFile();
00980 #endif
00981     }
00982 }
00983 
00984 class AppLnkSetPrivate {
00985 public:
00986     AppLnkSetPrivate()
00987     {
00988   typPix.setAutoDelete(TRUE);
00989   typPixBig.setAutoDelete(TRUE);
00990   typName.setAutoDelete(TRUE);
00991     }
00992 
00993     QDict<QPixmap> typPix;
00994     QDict<QPixmap> typPixBig;
00995     QDict<QString> typName;
00996 };
00997 
01023 AppLnkSet::AppLnkSet() :
01024     d(new AppLnkSetPrivate)
01025 {
01026 }
01027 
01039 AppLnkSet::AppLnkSet( const QString &directory ) :
01040     d(new AppLnkSetPrivate)
01041 {
01042     QDir dir( directory );
01043     mFile = directory;
01044     findChildren(directory,QString::null,QString::null);
01045 }
01046 
01051 void AppLnkSet::detachChildren()
01052 {
01053     QListIterator<AppLnk> it( mApps );
01054     for ( ; it.current(); ) {
01055   AppLnk* a = *it;
01056   ++it;
01057   a->mId = 0;
01058     }
01059     mApps.clear();
01060 }
01061 
01067 AppLnkSet::~AppLnkSet()
01068 {
01069     QListIterator<AppLnk> it( mApps );
01070     for ( ; it.current(); ) {
01071   AppLnk* a = *it;
01072   ++it;
01073   a->mId = 0;
01074   delete a;
01075     }
01076     delete d;
01077 }
01078 
01079 void AppLnkSet::findChildren(const QString &dr, const QString& typ, const QString& typName, int depth)
01080 {
01081     depth++;
01082     if ( depth > 10 )
01083   return;
01084 
01085     QDir dir( dr );
01086     QString typNameLocal = typName;
01087 
01088     if ( dir.exists( ".directory" ) ) {
01089   Config config( dr + "/.directory", Config::File );
01090   config.setGroup( "Desktop Entry" );
01091   typNameLocal = config.readEntry( "Name", typNameLocal );
01092   if ( !typ.isEmpty() ) {
01093       QString iconFile = config.readEntry( "Icon", "AppsIcon" );
01094       QImage unscaledIcon = Resource::loadImage( iconFile );
01095       QPixmap pm, bpm;
01096       pm.convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) );
01097       bpm.convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) );
01098       d->typPix.insert(typ, new QPixmap(pm));
01099       d->typPixBig.insert(typ, new QPixmap(bpm));
01100       d->typName.insert(typ, new QString(typNameLocal));
01101   }
01102     }
01103 
01104     const QFileInfoList *list = dir.entryInfoList();
01105     if ( list ) {
01106   QFileInfo* fi;
01107   bool cadded=FALSE;
01108   for ( QFileInfoListIterator it(*list); (fi=*it); ++it ) {
01109       QString bn = fi->fileName();
01110 //      qDebug("findChildren "+bn);
01111       if ( bn[0] != '.' && bn != "CVS" ) {
01112     if ( fi->isDir() ) {
01113         QString c = typ.isNull() ? bn : typ+"/"+bn;
01114         QString d = typNameLocal.isNull() ? bn : typNameLocal+"/"+bn;
01115         findChildren(fi->filePath(), c, d, depth );
01116     } else {
01117         if ( fi->extension(FALSE) == "desktop" ) {
01118       AppLnk* app = new AppLnk( fi->filePath() );
01119 #ifdef QT_NO_QWS_MULTIPROCESS
01120       if ( !Global::isBuiltinCommand( app->exec() ) )
01121           delete app;
01122       else
01123 #endif
01124       {
01125           if ( !typ.isEmpty() ) {
01126         if ( !cadded ) {
01127             typs.append(typ);
01128             cadded = TRUE;
01129         }
01130         app->setType(typ);
01131           }
01132           add(app);
01133       }
01134         }
01135     }
01136       }
01137   }
01138     }
01139 }
01140 
01147 void AppLnkSet::add( AppLnk *f )
01148 {
01149     if ( f->mId == 0 ) {
01150   AppLnk::lastId++;
01151   f->mId = AppLnk::lastId;
01152   mApps.append( f );
01153     } else {
01154   qWarning("Attempt to add an AppLnk twice");
01155     }
01156 }
01157 
01165 bool AppLnkSet::remove( AppLnk *f )
01166 {
01167     if ( mApps.remove( f ) ) {
01168   f->mId = 0;
01169   return TRUE;
01170     }
01171     return FALSE;
01172 }
01173 
01174 
01181 QString AppLnkSet::typeName( const QString& t ) const
01182 {
01183     QString *st = d->typName.find(t);
01184     return st ? *st : QString::null;
01185 }
01186 
01193 QPixmap AppLnkSet::typePixmap( const QString& t ) const
01194 {
01195     QPixmap *pm = d->typPix.find(t);
01196     return pm ? *pm : QPixmap();
01197 }
01198 
01205 QPixmap AppLnkSet::typeBigPixmap( const QString& t ) const
01206 {
01207     QPixmap *pm = d->typPixBig.find(t);
01208     return pm ? *pm : QPixmap();
01209 }
01210 
01214 const AppLnk *AppLnkSet::find( int id ) const
01215 {
01216     QListIterator<AppLnk> it( children() );
01217 
01218     for ( ; it.current(); ++it ) {
01219   const AppLnk *app = it.current();
01220   if ( app->id() == id )
01221       return app;
01222     }
01223 
01224     return 0;
01225 }
01226 
01230 const AppLnk *AppLnkSet::findExec( const QString& exec ) const
01231 {
01232     QListIterator<AppLnk> it( children() );
01233 
01234     for ( ; it.current(); ++it ) {
01235   const AppLnk *app = it.current();
01236   if ( app->exec() == exec )
01237       return app;
01238     }
01239 
01240     return 0;
01241 }
01242 
01259 DocLnkSet::DocLnkSet()
01260 {
01261 }
01262 
01275 DocLnkSet::DocLnkSet( const QString &directory, const QString& mimefilter ) :
01276     AppLnkSet()
01277 {
01278     QDir dir( directory );
01279     mFile = dir.dirName();
01280     QDict<void> reference;
01281 
01282     QStringList subFilter = QStringList::split(";", mimefilter);
01283     QValueList<QRegExp> mimeFilters;
01284     for( QStringList::Iterator it = subFilter.begin(); it != subFilter.end(); ++ it )
01285   mimeFilters.append( QRegExp(*it, FALSE, TRUE) );
01286 
01287     findChildren(directory, mimeFilters, reference);
01288 
01289     const QList<DocLnk> &list = children();
01290     for ( QListIterator<DocLnk> it( list ); it.current(); ++it ) {
01291   reference.remove( (*it)->file() );
01292     }
01293     for ( QDictIterator<void> dit(reference); dit.current(); ++dit ) {
01294   if ( dit.current() == (void*)2 ) {
01295       // Unreferenced, make an unwritten link
01296       DocLnk* dl = new DocLnk;
01297       QFileInfo fi( dit.currentKey() );
01298       dl->setFile(fi.filePath());
01299       dl->setName(fi.baseName());
01300       // #### default to current path?
01301       // dl->setCategories( ... );
01302       bool match = mimefilter.isNull();
01303       if ( !match )
01304     for( QValueList<QRegExp>::Iterator it = mimeFilters.begin(); it != mimeFilters.end() && !match; ++ it )
01305         if ( (*it).match(dl->type()) >= 0 )
01306       match = TRUE;
01307       if ( match /* && dl->type() != "application/octet-stream" */
01308         && !!dl->exec() )
01309     add(dl);
01310       else
01311     delete dl;
01312   }
01313     }
01314 }
01315 
01316 // other becomes empty
01321 void DocLnkSet::appendFrom( DocLnkSet& other )
01322 {
01323     if ( &other == this )
01324   return;
01325     QListIterator<AppLnk> it( other.mApps );
01326     for ( ; it.current(); ) {
01327   mApps.append(*it);
01328   ++it;
01329     }
01330     other.mApps.clear();
01331 }
01332 
01333 void DocLnkSet::findChildren(const QString &dr, const QValueList<QRegExp> &mimeFilters, QDict<void> &reference, int depth)
01334 {
01335     depth++;
01336     if ( depth > 10 )
01337   return;
01338 
01339     QDir dir( dr );
01340 
01341     /* Opie got a different approach
01342      * I guess it's geek vs. consumer
01343      * in this case to be discussed
01344      */
01345     if ( dir.exists( ".Qtopia-ignore" ) )
01346   return;
01347 
01348     const QFileInfoList *list = dir.entryInfoList();
01349     if ( list ) {
01350   QFileInfo* fi;
01351   for ( QFileInfoListIterator it(*list); (fi=*it); ++it ) {
01352       QString bn = fi->fileName();
01353       if ( bn[0] != '.' ) {
01354     if ( fi->isDir()  ) {
01355         if ( bn != "CVS" && bn != "Qtopia" && bn != "QtPalmtop" )
01356       findChildren(fi->filePath(), mimeFilters, reference, depth);
01357     } else {
01358         if ( fi->extension(FALSE) == "desktop" ) {
01359       DocLnk* dl = new DocLnk( fi->filePath() );
01360       QFileInfo fi2(dl->file());
01361       bool match = FALSE;
01362       if ( !fi2.exists() ) {
01363           dir.remove( dl->file() );
01364       }
01365       if ( mimeFilters.count() == 0 ) {
01366           add( dl );
01367           match = TRUE;
01368       } else {
01369           for( QValueList<QRegExp>::ConstIterator it = mimeFilters.begin(); it != mimeFilters.end(); ++ it ) {
01370         if ( (*it).match(dl->type()) >= 0 ) {
01371             add(dl);
01372             match = TRUE;
01373         }
01374           }
01375       }
01376       if ( !match )
01377           delete dl;
01378         } else {
01379       if ( !reference.find(fi->fileName()) )
01380           reference.insert(fi->filePath(), (void*)2);
01381         }
01382     }
01383       }
01384   }
01385     }
01386 }
01387 
01403 DocLnk::DocLnk( const QString &file ) :
01404     AppLnk(file)
01405 {
01406     init(file);
01407 }
01408 
01415 DocLnk::DocLnk( const QString &file, bool may_be_desktopfile ) :
01416     AppLnk(may_be_desktopfile ? file : QString::null)
01417 {
01418     init(file);
01419 }
01420 
01421 void DocLnk::init(const QString &file)
01422 {
01423     if ( isValid() ) {
01424 #ifndef FORCED_DIR_STRUCTURE_WAY
01425   if ( mType.isNull() )
01426       // try to infer it
01427 #endif
01428   {
01429       int s0 = file.findRev('/');
01430       if ( s0 > 0 ) {
01431     int s1 = file.findRev('/',s0-1);
01432     if ( s1 > 0 ) {
01433         int s2 = file.findRev('/',s1-1);
01434         if ( s2 > 0 ) {
01435       mType = file.mid(s2+1,s0-s2-1);
01436         }
01437     }
01438       }
01439   }
01440     } else if ( QFile::exists(file) ) {
01441   QString n = file;
01442   n.replace(QRegExp(".*/"),"");
01443   n.replace(QRegExp("\\..*"),"");
01444   setName( n );
01445   setFile( file );
01446     }
01447     MimeType mt(mType);
01448     if( mt.application() )
01449   mExec = mt.application()->exec();
01450 }
01451 
01455 DocLnk::DocLnk()
01456 {
01457 }
01458 
01463 DocLnk::~DocLnk()
01464 {
01465 }
01466 
01470 QString DocLnk::exec() const
01471 {
01472     MimeType mt(type());
01473     const AppLnk* app = mt.application();
01474     if ( app )
01475   return app->exec();
01476     else
01477   return QString::null;
01478 }
01479 
01483 void DocLnk::invoke(const QStringList& args) const
01484 {
01485     MimeType mt(type());
01486     const AppLnk* app = mt.application();
01487     if ( app ) {
01488   QStringList a = args;
01489   if ( linkFileKnown() && QFile::exists( linkFile() ) )
01490       a.append(linkFile());
01491   else
01492       a.append(file());
01493   app->execute(a);
01494     }
01495 }
01496 
01497 
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