-rw-r--r-- | library/applnk.cpp | 83 |
1 files changed, 56 insertions, 27 deletions
diff --git a/library/applnk.cpp b/library/applnk.cpp index 2af6cf4..5185b5f 100644 --- a/library/applnk.cpp +++ b/library/applnk.cpp @@ -1,105 +1,117 @@ /********************************************************************** ** Copyright (C) 2000 Trolltech AS. All rights reserved. ** ** This file is part of Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ +#define QTOPIA_INTERNAL_MIMEEXT + #include "applnk.h" #include <qpe/qpeapplication.h> #include <qpe/categories.h> #include <qpe/categoryselect.h> #include <qpe/qcopenvelope_qws.h> #include <qpe/global.h> #include <qpe/mimetype.h> #include <qpe/config.h> #include <qpe/storage.h> #include <qpe/resource.h> #include <qdict.h> #include <qdir.h> #include <qregexp.h> #ifdef Q_WS_QWS #include <qgfx_qws.h> #endif #include <stdlib.h> int AppLnk::lastId = 5000; static int smallSize = 14; static int bigSize = 32; static QString safeFileName(const QString& n) { QString safename=n; - safename.replace(QRegExp("[^0-9A-Za-z.]"),"_"); + safename.replace(QRegExp("[^0-9A-Za-z.]"),"_"); // Njaard says this is broken safename.replace(QRegExp("^[^A-Za-z]*"),""); if ( safename.isEmpty() ) safename = "_"; return safename; } +static bool prepareDirectories(const QString& lf) +{ + if ( !QFile::exists(lf) ) { + // May need to create directories + QFileInfo fi(lf); + if ( system(("mkdir -p "+fi.dirPath(TRUE))) ) + return FALSE; + } + return TRUE; +} class AppLnkPrivate { public: QArray<int> mCat; }; /*! \class AppLnk applnk.h \brief The AppLnk class represents an application available on the system. Information about applications are stored in Qtopia as ".desktop" files. When read, these files are stored as AppLnk objects. */ /*! Sets the size used for small icons to \a small pixels. Only affects AppLnk objects created after the call. */ void AppLnk::setSmallIconSize(int small) { smallSize = small; } /*! Returns the size used for small icons. */ int AppLnk::smallIconSize() { return smallSize; } /*! Sets the size used for large icons to \a big pixels. Only affects AppLnk objects created after the call. */ void AppLnk::setBigIconSize(int big) { bigSize = big; } /*! Returns the size used for large icons. */ int AppLnk::bigIconSize() { return bigSize; @@ -238,149 +250,165 @@ const QPixmap& AppLnk::pixmap() const } return mPixmap; } /*! Returns a large pixmap associated with the application. */ const QPixmap& AppLnk::bigPixmap() const { if ( mBigPixmap.isNull() ) { AppLnk* that = (AppLnk*)this; if ( mIconFile.isEmpty() ) { MimeType mt(type()); that->mBigPixmap = mt.bigPixmap(); if ( that->mBigPixmap.isNull() ) that->mBigPixmap = Resource::loadPixmap("UnknownDocument"); return that->mBigPixmap; } QImage unscaledIcon = Resource::loadImage( that->mIconFile ); that->mPixmap.convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) ); that->mBigPixmap.convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) ); return that->mBigPixmap; } return mBigPixmap; } /*! Returns the type of the application. */ QString AppLnk::type() const { if ( mType.isNull() ) { AppLnk* that = (AppLnk*)this; MimeType mt(file()); that->mType = mt.id(); return that->mType; } return mType; } /*! Returns the file associated with the AppLnk. \sa exec() */ QString AppLnk::file() const { if ( mFile.isNull() ) { - AppLnk* that = (AppLnk*)this; + AppLnk* that = (AppLnk*)this; // copy? + 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; } else if ( mType.contains('/') ) { that->mFile = QString(getenv("HOME"))+"/Documents/"+mType+"/"+safeFileName(that->mName); - if ( QFile::exists(that->mFile) || QFile::exists(that->mFile+".desktop") ) { + if ( QFile::exists(that->mFile+ext) || QFile::exists(that->mFile+".desktop") ) { // a .desktop with the same name exists int n=1; + qWarning("AppLnk::file() n=1 %s", that->mFile.latin1() ); QString nn; - while (QFile::exists((nn=(that->mFile+"_"+QString::number(n)))) + while (QFile::exists((nn=(that->mFile+"_"+QString::number(n)))+ext) || QFile::exists(nn+".desktop")) n++; that->mFile = nn; + qWarning("AppLnl::file() now mFile is %s", that->mFile.latin1() ); } that->mLinkFile = that->mFile+".desktop"; + that->mFile += ext; } + prepareDirectories(that->mFile); + QFile f(that->mFile); + if ( !f.open(IO_WriteOnly) ) + that->mFile = QString::null; return that->mFile; } return mFile; } /*! Returns the desktop file coresponding to this AppLnk. \sa file(), exec() */ QString AppLnk::linkFile() const { if ( mLinkFile.isNull() ) { AppLnk* that = (AppLnk*)this; if ( type().contains('/') ) { StorageInfo storage; const FileSystem *fs = storage.fileSystemOf( that->mFile ); -// qDebug("creating lnkFile for %s", mFile.latin1() ); -// if ( fs ) -// qDebug("fs is %s", fs->path().latin1() ); if ( fs && fs->isRemovable() ) { -// qDebug("isRemovable"); that->mLinkFile = fs->path(); } else that->mLinkFile = getenv( "HOME" ); that->mLinkFile += "/Documents/"+type()+"/"+safeFileName(that->mName); - if ( QFile::exists(that->mLinkFile+".desktop") ) { + if ( QFile::exists(that->mLinkFile+".desktop") ) { // ok the file exists lets check if we point to the same file int n=1; QString nn; - while (QFile::exists((nn=that->mLinkFile+"_"+QString::number(n))+".desktop")) + AppLnk lnk( that->mLinkFile+".desktop" ); + if(that->file() != lnk.file() ){ + qWarning("AppLnk::linkFile exists %s", that->mLinkFile.latin1() ); + while (QFile::exists((nn=that->mLinkFile+"_"+QString::number(n))+".desktop")){ n++; - that->mLinkFile = nn; + AppLnk lnk(nn ); // just to be sure + if(lnk.file() ==that->file() ){ + break; + } + } + that->mLinkFile = nn; + } } that->mLinkFile += ".desktop"; -// qDebug("file is %s", mLinkFile.latin1() ); + qWarning("AppLnk::linkFile is %s", that->mLinkFile.latin1() ); + 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; } /*! Destroys the AppLnk. Note that if the AppLnk is current 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; } /*! Executes the application associated with this AppLnk. */ void AppLnk::execute() const { execute(QStringList()); @@ -469,185 +497,186 @@ void AppLnk::setComment( const QString& comment ) } /*! Sets the Type property to \a type. \sa type() */ void AppLnk::setType( const QString& type ) { mType = type; } /*! Sets the Icon property to \a iconname. \sa pixmap(), bigPixmap() */ void AppLnk::setIcon( const QString& iconname ) { mIconFile = iconname; QImage unscaledIcon = Resource::loadImage( mIconFile ); mPixmap.convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) ); mBigPixmap.convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) ); } /*! Sets the Categories property to \a c. \sa categories() */ void AppLnk::setCategories( const QArray<int>& c ) { d->mCat = c; } /*! \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. */ bool AppLnk::ensureLinkExists() const { QString lf = linkFile(); - if ( !QFile::exists(lf) ) { - // May need to create directories - QFileInfo fi(lf); - if ( system(("mkdir -p "+fi.dirPath(TRUE))) ) - return FALSE; - } - return TRUE; + return prepareDirectories(lf); } /*! Commits the AppLnk to disk. Returns whether the operation succeeded. The "linkChanged(QString)" message is sent to the "QPE/System" QCop channel as a result. */ bool AppLnk::writeLink() const { // Only re-writes settable parts QString lf = linkFile(); if ( !ensureLinkExists() ) return FALSE; - Config config( lf, Config::File ); + storeLink(); + return TRUE; +} + +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 ( !mComment.isNull() ) config.writeEntry("Comment",mComment); config.writeEntry("File",file()); // write out the id... int i; QStringList sl; for ( i = 0; i < int(d->mCat.count()); i++ ) { sl.append( QString::number( d->mCat[i] ) ); } config.writeEntry( "Categories", sl, ';' ); QCopEnvelope e("QPE/System", "linkChanged(QString)"); - e << lf; - - return TRUE; + e << mLinkFile; } /*! Sets the property named \a key to \a value. */ 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. */ 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); } /*! Deletes both the linkFile() and file() associated with this AppLnk. */ void AppLnk::removeFiles() { bool valid = isValid(); - if ( !valid || QFile::remove(linkFile()) ) { + if ( !valid || !linkFileKnown() || QFile::remove(linkFile()) ) { if ( QFile::remove(file()) ) { QCopEnvelope e("QPE/System", "linkChanged(QString)"); - e << linkFile(); + if ( linkFileKnown() ) + e << linkFile(); + else + e << file(); } else if ( valid ) { // restore link writeLink(); } } } /*! Delete the linkFile(), leaving any file() untouched. */ void AppLnk::removeLinkFile() { - if ( isValid() && QFile::remove(linkFile()) ) { + if ( isValid() && linkFileKnown() && QFile::remove(linkFile()) ) { QCopEnvelope e("QPE/System", "linkChanged(QString)"); e << linkFile(); } } 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 types in the set. \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 @@ -1038,56 +1067,56 @@ void DocLnk::init(const QString &file) QString n = file; n.replace(QRegExp("\\..*"),""); n.replace(QRegExp(".*/"),""); setName( n ); setFile( file ); } MimeType mt(mType); if( mt.application() ) mExec = mt.application()->exec(); } /*! Constructs an invalid DocLnk. */ DocLnk::DocLnk() { } /*! Destroys the DocLnk. As with AppLnk objects, a run-time error occurs if the DocLnk is a member of a DocLnkSet (or AppLnkSet). */ DocLnk::~DocLnk() { } /*! \reimp */ QString DocLnk::exec() const { MimeType mt(type()); const AppLnk* app = mt.application(); if ( app ) return app->exec(); else return QString::null; } /*! \reimp */ void DocLnk::invoke(const QStringList& args) const { MimeType mt(type()); const AppLnk* app = mt.application(); if ( app ) { QStringList a = args; - if ( QFile::exists( linkFile() ) ) + if ( linkFileKnown() && QFile::exists( linkFile() ) ) a.append(linkFile()); else a.append(file()); app->execute(a); } } |