author | mickeyl <mickeyl> | 2004-03-08 16:37:42 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2004-03-08 16:37:42 (UTC) |
commit | 2599910741451f86323af10585c858d217a122d5 (patch) (side-by-side diff) | |
tree | e00a51cc13f2cfd85eb79e9af7a79d69f777ad77 | |
parent | 82fb70f4e5d8582185da89264e1a1e3b2517f459 (diff) | |
download | opie-2599910741451f86323af10585c858d217a122d5.zip opie-2599910741451f86323af10585c858d217a122d5.tar.gz opie-2599910741451f86323af10585c858d217a122d5.tar.bz2 |
support launching applications with user defined arguments
-rw-r--r-- | library/applnk.cpp | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/library/applnk.cpp b/library/applnk.cpp index 9c60f1a..5f7da8e 100644 --- a/library/applnk.cpp +++ b/library/applnk.cpp @@ -286,803 +286,806 @@ int AppLnk::bigIconSize() */ /*! \fn QString AppLnk::comment() const Returns the Comment property. \sa setComment() */ /*! \fn QStringList AppLnk::mimeTypes() const Returns the MimeTypes property. This is the list of MIME types that the application can view or edit. */ /*! \fn const QArray<int>& AppLnk::categories() const Returns the Categories property. See the CategoryWidget for more details. \sa setCategories() */ const QArray<int>& AppLnk::categories() const { d->ensureCatArray(); return d->mCat; } /*! \fn int AppLnk::id() const Returns the id of the AppLnk. If the AppLnk is not in an AppLnkSet, this value is 0, otherwise it is a value that is unique for the duration of the current process. \sa AppLnkSet::find() */ /*! \fn bool AppLnk::isValid() const Returns TRUE if this AppLnk is valid; otherwise returns FALSE. */ /*! \fn bool AppLnk::fileKnown() const If the with the AppLnk associated file is not equal to QString::null */ /*! \fn bool AppLnk::linkFileKnown()const The filename of the AppLnk */ /*! \fn void AppLnk::setRotation( const QString& ) The default rotation of the associated application. This function is included inline for binary compatible issues */ /*! Creates an invalid AppLnk. \sa isValid() */ AppLnk::AppLnk() { mId = 0; d = new AppLnkPrivate(); } /*! Loads \a file (e.g. \e app.desktop) as an AppLnk. \sa writeLink() */ AppLnk::AppLnk( const QString &file ) { QStringList sl; d = new AppLnkPrivate(); if ( !file.isNull() ) { Config config( file, Config::File ); if ( config.isValid() ) { config.setGroup( "Desktop Entry" ); mName = config.readEntry( "Name", file ); mExec = config.readEntry( "Exec" ); mType = config.readEntry( "Type", QString::null ); mIconFile = config.readEntry( "Icon", QString::null ); mRotation = config.readEntry( "Rotation", "" ); mComment = config.readEntry( "Comment", QString::null ); // MIME types are case-insensitive. mMimeTypes = config.readListEntry( "MimeType", ';' ); for (QStringList::Iterator it=mMimeTypes.begin(); it!=mMimeTypes.end(); ++it) *it = (*it).lower(); mMimeTypeIcons = config.readListEntry( "MimeTypeIcons", ';' ); mLinkFile = file; mFile = config.readEntry("File", QString::null); if ( !mExec. isEmpty ( )) { mFile = QString::null; } else if ( mFile[0] != '/' ) { int slash = file.findRev('/'); if ( slash >= 0 ) { mFile = file.left(slash) + '/' + mFile; } } d->mCatList = config.readListEntry("Categories", ';'); if ( d->mCatList[0].toInt() < -1 ) { // numeric cats in file! convert to text Categories cat( 0 ); cat.load( categoryFileName() ); d->mCat.resize( d->mCatList.count() ); int i; QStringList::ConstIterator it; for ( i = 0, it = d->mCatList.begin(); it != d->mCatList.end(); ++it, i++ ) { bool number; int id = (*it).toInt( &number ); if ( !number ) { // convert from text id = cat.id( "Document View", *it ); if ( id == 0 ) id = cat.addCategory( "Document View", *it ); } d->mCat[i] = id; } d->updateCatListFromArray(); } } } mId = 0; } AppLnk& AppLnk::operator=(const AppLnk ©) { if ( this == © ) return *this; if ( mId ) qWarning("Deleting AppLnk that is in an AppLnkSet"); if ( d ) delete d; mName = copy.mName; /* remove for Qtopia 3.0 -zecke */ mPixmap = copy.mPixmap; mBigPixmap = copy.mBigPixmap; mExec = copy.mExec; mType = copy.mType; mRotation = copy.mRotation; mComment = copy.mComment; mFile = copy.mFile; mLinkFile = copy.mLinkFile; mIconFile = copy.mIconFile; mMimeTypes = copy.mMimeTypes; mMimeTypeIcons = copy.mMimeTypeIcons; mId = 0; d = new AppLnkPrivate(); d->mCat = copy.d->mCat; d->mCatList = copy.d->mCatList; d->mPixmaps = copy.d->mPixmaps; return *this; } /*! protected internally to share code should I document that at all? I don't know the TT style for that */ const QPixmap& AppLnk::pixmap( int pos, int size ) const { if ( d->mPixmaps[pos].isNull() ) { AppLnk* that = (AppLnk*)this; if ( mIconFile.isEmpty() ) { MimeType mt(type()); that->d->mPixmaps[pos] = pos ? mt.bigPixmap() : mt.pixmap(); if ( that->d->mPixmaps[pos].isNull() ) that->d->mPixmaps[pos].convertFromImage( Resource::loadImage("UnknownDocument") .smoothScale( size, size ) ); return that->d->mPixmaps[pos]; } QImage unscaledIcon = Resource::loadImage( that->mIconFile ); if ( unscaledIcon.isNull() ) { // qDebug( "Cannot find icon: %s", that->mIconFile.latin1() ); that->d->mPixmaps[pos].convertFromImage( Resource::loadImage("UnknownDocument") .smoothScale( size, size ) ); } else { that->d->mPixmaps[0].convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) ); that->d->mPixmaps[1].convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) ); } return that->d->mPixmaps[pos]; } return d->mPixmaps[pos]; } /*! Returns a small pixmap associated with the application. \sa bigPixmap() setIcon() */ const QPixmap& AppLnk::pixmap() const { if ( d->mPixmaps[0].isNull() ) { return pixmap(AppLnkPrivate::Normal, smallSize ); } return d->mPixmaps[0]; } /*! Returns a large pixmap associated with the application. \sa pixmap() setIcon() */ const QPixmap& AppLnk::bigPixmap() const { if ( d->mPixmaps[1].isNull() ) { return pixmap( AppLnkPrivate::Big, bigSize ); } return d->mPixmaps[1]; } /*! Returns the type of the AppLnk. For applications, games and settings the type is \c Application; for documents the type is the document's MIME type. */ QString AppLnk::type() const { if ( mType.isNull() ) { AppLnk* that = (AppLnk*)this; QString f = file(); if ( !f.isNull() ) { MimeType mt(f); that->mType = mt.id(); return that->mType; } } return mType; } /*! Returns the file associated with the AppLnk. \sa exec() name() */ QString AppLnk::file() const { if ( mExec.isEmpty ( ) && mFile.isNull() ) { AppLnk* that = (AppLnk*)this; QString ext = MimeType(mType).extension(); if ( !ext.isEmpty() ) ext = "." + ext; if ( !mLinkFile.isEmpty() ) { that->mFile = mLinkFile.right(8)==".desktop" // 8 = strlen(".desktop") ? mLinkFile.left(mLinkFile.length()-8) : mLinkFile; qDebug("mFile now == %s", mFile.latin1()); } else if ( mType.contains('/') ) { that->mFile = QString(getenv("HOME"))+"/Documents/"+mType+"/"+safeFileName(that->mName); /* * A file with the same name or a .desktop file already exists */ if ( QFile::exists(that->mFile+ext) || QFile::exists(that->mFile+".desktop") ) { int n=1; QString nn; while (QFile::exists((nn=(that->mFile+"_"+QString::number(n)))+ext) || QFile::exists(nn+".desktop")) n++; that->mFile = nn; } that->mLinkFile = that->mFile+".desktop"; that->mFile += ext; } prepareDirectories(that->mFile); if ( !that->mFile.isEmpty() ) { QFile f(that->mFile); if ( !f.open(IO_WriteOnly) ) that->mFile = QString::null; return that->mFile; } } return mFile; } /*! Returns the desktop file corresponding to this AppLnk. \sa file() exec() name() */ QString AppLnk::linkFile() const { if ( mLinkFile.isNull() ) { AppLnk* that = (AppLnk*)this; if ( type().contains('/') ) { StorageInfo storage; const FileSystem *fs = storage.fileSystemOf( that->mFile ); /* tmpfs + and ramfs are available too but not removable * either we fix storage or add this */ if ( fs && ( fs->isRemovable() || fs->disk() == "/dev/mtdblock6" || fs->disk() == "tmpfs") ) { that->mLinkFile = fs->path(); } else that->mLinkFile = getenv( "HOME" ); that->mLinkFile += "/Documents/"+type()+"/"+safeFileName(that->mName); /* the desktop file exists make sure we don't point to the same file */ if ( QFile::exists(that->mLinkFile+".desktop") ) { AppLnk lnk( that->mLinkFile + ".desktop" ); /* the linked is different */ if(that->file() != lnk.file() ) { int n = 1; QString nn; while (QFile::exists((nn=that->mLinkFile+"_"+QString::number(n))+".desktop")) { n++; /* just to be sure */ AppLnk lnk(nn ); if (lnk.file() == that->file() ) break; } that->mLinkFile = nn; } } that->mLinkFile += ".desktop"; storeLink(); } return that->mLinkFile; } return mLinkFile; } /*! Copies \a copy. */ AppLnk::AppLnk( const AppLnk © ) { mName = copy.mName; mPixmap = copy.mPixmap; mBigPixmap = copy.mBigPixmap; mExec = copy.mExec; mType = copy.mType; mRotation = copy.mRotation; mComment = copy.mComment; mFile = copy.mFile; mLinkFile = copy.mLinkFile; mIconFile = copy.mIconFile; mMimeTypes = copy.mMimeTypes; mMimeTypeIcons = copy.mMimeTypeIcons; mId = 0; d = new AppLnkPrivate(); d->mCat = copy.d->mCat; d->mCatList = copy.d->mCatList; d->mPixmaps = copy.d->mPixmaps; } /*! Destroys the AppLnk. Note that if the AppLnk is currently a member of an AppLnkSet, this will produce a run-time warning. \sa AppLnkSet::add() AppLnkSet::remove() */ AppLnk::~AppLnk() { if ( mId ) qWarning("Deleting AppLnk that is in an AppLnkSet"); if ( d ) delete d; } /*! \overload Executes the application associated with this AppLnk. \sa exec() */ void AppLnk::execute() const { - execute(QStringList()); + execute( QStringList::split( ' ', property( "Arguments" ) ) ); } /*! Executes the application associated with this AppLnk, with \a args as arguments. \sa exec() */ void AppLnk::execute(const QStringList& args) const { #ifdef Q_WS_QWS if ( !mRotation.isEmpty() ) { // ######## this will only work in the server int rot = QPEApplication::defaultRotation(); rot = (rot+mRotation.toInt())%360; QCString old = getenv("QWS_DISPLAY"); setenv("QWS_DISPLAY", QString("Transformed:Rot%1:0").arg(rot), 1); invoke(args); setenv("QWS_DISPLAY", old.data(), 1); } else #endif invoke(args); } /*! Invokes the application associated with this AppLnk, with \a args as arguments. Rotation is not taken into account by this function, so you should not call it directly. \sa execute() */ void AppLnk::invoke(const QStringList& args) const { - Global::execute( exec(), args[0] ); + if ( property( "Arguments" ).isEmpty() ) + Global::execute( exec(), args[0] ); + else + Global::execute( exec(), args.join( " " ) ); } /*! Sets the Exec property to \a exec. \sa exec() name() */ void AppLnk::setExec( const QString& exec ) { mExec = exec; } #if 0 // this was inlined for better BC /*! Sets the Rotation property to \a rot. \sa rotation() */ void AppLnk::setRotation ( const QString &rot ) { mRotation = rot; } #endif /*! Sets the Name property to \a docname. \sa name() */ void AppLnk::setName( const QString& docname ) { mName = docname; } /*! Sets the File property to \a filename. \sa file() name() */ void AppLnk::setFile( const QString& filename ) { mFile = filename; } /*! Sets the LinkFile property to \a filename. \sa linkFile() */ void AppLnk::setLinkFile( const QString& filename ) { mLinkFile = filename; } /*! Sets the Comment property to \a comment. This text is displayed in the 'Details Dialog', for example if the user uses the 'press-and-hold' gesture. \sa comment() */ void AppLnk::setComment( const QString& comment ) { mComment = comment; } /*! Sets the Type property to \a type. For applications, games and settings the type should be \c Application; for documents the type should be the document's MIME type. \sa type() */ void AppLnk::setType( const QString& type ) { mType = type; } /*! \fn QString AppLnk::icon() const Returns the Icon property. \sa setIcon() */ /*! Sets the Icon property to \a iconname. This is the filename from which the pixmap() and bigPixmap() are obtained. \sa icon() setSmallIconSize() setBigIconSize() */ void AppLnk::setIcon( const QString& iconname ) { mIconFile = iconname; QImage unscaledIcon = Resource::loadImage( mIconFile ); d->mPixmaps[0].convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) ); d->mPixmaps[1].convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) ); } /*! Sets the Categories property to \a c. See the CategoryWidget for more details. \sa categories() */ void AppLnk::setCategories( const QArray<int>& c ) { d->mCat = c; d->updateCatListFromArray(); } /*! \fn QStringList AppLnk::mimeTypeIcons() const Returns the MimeTypeIcons property of the AppLnk. */ /*! Attempts to ensure that the link file for this AppLnk exists, including creating any required directories. Returns TRUE if successful; otherwise returns FALSE. You should not need to use this function. */ bool AppLnk::ensureLinkExists() const { QString lf = linkFile(); return prepareDirectories(lf); } /*! Commits the AppLnk to disk. Returns TRUE if the operation succeeded; otherwise returns FALSE. In addition, the "linkChanged(QString)" message is sent to the "QPE/System" \link qcop.html QCop\endlink channel. */ bool AppLnk::writeLink() const { // Only re-writes settable parts QString lf = linkFile(); if ( !ensureLinkExists() ) return FALSE; storeLink(); return TRUE; } /*! \internal */ void AppLnk::storeLink() const { Config config( mLinkFile, Config::File ); config.setGroup("Desktop Entry"); config.writeEntry("Name",mName); if ( !mIconFile.isNull() ) config.writeEntry("Icon",mIconFile); config.writeEntry("Type",type()); if(!rotation().isEmpty()) config.writeEntry("Rotation",rotation()); else config.removeEntry("Rotation"); if ( !mComment.isNull() ) config.writeEntry("Comment",mComment); QString f = file(); int i = 0; while ( i < (int)f.length() && i < (int)mLinkFile.length() && f[i] == mLinkFile[i] ) i++; while ( i && f[i] != '/' ) i--; // simple case where in the same directory if ( mLinkFile.find( '/', i + 1 ) < 0 ) f = f.mid(i+1); // ### could do relative ie ../../otherDocs/file.doc config.writeEntry("File",f); config.writeEntry( "Categories", d->mCatList, ';' ); #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "linkChanged(QString)"); e << mLinkFile; #endif } /*! Sets the property named \a key to \a value. \sa property() */ void AppLnk::setProperty(const QString& key, const QString& value) { if ( ensureLinkExists() ) { Config cfg(linkFile(), Config::File); cfg.writeEntry(key,value); } } /*! Returns the property named \a key. \sa setProperty() */ QString AppLnk::property(const QString& key) const { QString lf = linkFile(); if ( !QFile::exists(lf) ) return QString::null; Config cfg(lf, Config::File); return cfg.readEntry(key); } bool AppLnk::isPreloaded() const { // Preload information is stored in the Launcher config in v1.5. Config cfg("Launcher"); cfg.setGroup("Preload"); QStringList apps = cfg.readListEntry("Apps",','); if (apps.contains(exec())) return true; return false; } void AppLnk::setPreloaded(bool yesNo) { // Preload information is stored in the Launcher config in v1.5. Config cfg("Launcher"); cfg.setGroup("Preload"); QStringList apps = cfg.readListEntry("Apps", ','); if (apps.contains(exec()) && !yesNo) apps.remove(exec()); else if (yesNo && !apps.contains(exec())) apps.append(exec()); cfg.writeEntry("Apps", apps, ','); } /*! Deletes both the linkFile() and the file() associated with this AppLnk. \sa removeLinkFile() */ void AppLnk::removeFiles() { bool valid = isValid(); if ( !valid || !linkFileKnown() || QFile::remove(linkFile()) ) { if ( QFile::remove(file()) ) { #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "linkChanged(QString)"); if ( linkFileKnown() ) e << linkFile(); else e << file(); #endif } else if ( valid ) { // restore link writeLink(); } } } /*! Deletes the linkFile(), leaving any file() untouched. \sa removeFiles() */ void AppLnk::removeLinkFile() { if ( isValid() && linkFileKnown() && QFile::remove(linkFile()) ) { #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "linkChanged(QString)"); e << linkFile(); #endif } } class AppLnkSetPrivate { public: AppLnkSetPrivate() { typPix.setAutoDelete(TRUE); typPixBig.setAutoDelete(TRUE); typName.setAutoDelete(TRUE); } QDict<QPixmap> typPix; QDict<QPixmap> typPixBig; QDict<QString> typName; }; /*! \class AppLnkSet applnk.h \brief The AppLnkSet class is a set of AppLnk objects. */ /*! \fn QStringList AppLnkSet::types() const Returns the list of \link applnk.html#Types types\endlink in the set. For applications, games and settings the type is \c Application; for documents the type is the document's MIME type. \sa AppLnk::type(), typeName(), typePixmap(), typeBigPixmap() */ /*! \fn const QList<AppLnk>& AppLnkSet::children() const Returns the members of the set. */ /*! Constructs an empty AppLnkSet. */ AppLnkSet::AppLnkSet() : d(new AppLnkSetPrivate) { } /*! Constructs an AppLnkSet that contains AppLnk objects representing all the files in the given \a directory (and any subdirectories recursively). \omit The directories may contain ".directory" files which override any AppLnk::type() values for AppLnk objects found in the directory. This allows simple localization of application types. \endomit */ AppLnkSet::AppLnkSet( const QString &directory ) : d(new AppLnkSetPrivate) { QDir dir( directory ); mFile = directory; findChildren(directory,QString::null,QString::null); } /*! Detaches all AppLnk objects from the set. The set become empty and the caller becomes responsible for deleting the AppLnk objects. */ void AppLnkSet::detachChildren() { QListIterator<AppLnk> it( mApps ); for ( ; it.current(); ) { AppLnk* a = *it; ++it; a->mId = 0; } mApps.clear(); } /*! Destroys the set, deleting all the AppLnk objects it contains. \sa detachChildren() */ AppLnkSet::~AppLnkSet() { QListIterator<AppLnk> it( mApps ); for ( ; it.current(); ) { AppLnk* a = *it; ++it; a->mId = 0; delete a; } delete d; } void AppLnkSet::findChildren(const QString &dr, const QString& typ, const QString& typName, int depth) { depth++; if ( depth > 10 ) return; QDir dir( dr ); QString typNameLocal = typName; if ( dir.exists( ".directory" ) ) { Config config( dr + "/.directory", Config::File ); config.setGroup( "Desktop Entry" ); typNameLocal = config.readEntry( "Name", typNameLocal ); if ( !typ.isEmpty() ) { |