summaryrefslogtreecommitdiff
authormickeyl <mickeyl>2004-03-08 16:37:42 (UTC)
committer mickeyl <mickeyl>2004-03-08 16:37:42 (UTC)
commit2599910741451f86323af10585c858d217a122d5 (patch) (side-by-side diff)
treee00a51cc13f2cfd85eb79e9af7a79d69f777ad77
parent82fb70f4e5d8582185da89264e1a1e3b2517f459 (diff)
downloadopie-2599910741451f86323af10585c858d217a122d5.zip
opie-2599910741451f86323af10585c858d217a122d5.tar.gz
opie-2599910741451f86323af10585c858d217a122d5.tar.bz2
support launching applications with user defined arguments
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--library/applnk.cpp5
1 files changed, 4 insertions, 1 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 &copy)
{
if ( this == &copy ) 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 &copy )
{
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
{
+ 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() ) {