summaryrefslogtreecommitdiff
path: root/library/applnk.cpp
Side-by-side diff
Diffstat (limited to 'library/applnk.cpp') (more/less context) (show whitespace changes)
-rw-r--r--library/applnk.cpp4
1 files changed, 0 insertions, 4 deletions
diff --git a/library/applnk.cpp b/library/applnk.cpp
index a56da5d..5763c62 100644
--- a/library/applnk.cpp
+++ b/library/applnk.cpp
@@ -1,557 +1,553 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of the 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
#define QTOPIA_INTERNAL_PRELOADACCESS
#define QTOPIA_INTERNAL_APPLNKASSIGN
#include "applnk.h"
#include <qpe/qpeapplication.h>
#include <qpe/categories.h>
#include <qpe/categoryselect.h>
-#ifdef QWS
#include <qpe/qcopenvelope_qws.h>
-#endif
#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("^[^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:
/* the size of the Pixmap */
enum Size {Normal = 0, Big };
AppLnkPrivate() {
/* we want one normal and one big item */
QPixmap pix;
mPixmaps.insert(0, pix );
mPixmaps.insert(1, pix);
}
QStringList mCatList; // always correct
QArray<int> mCat; // cached value; correct if not empty
QMap<int, QPixmap> mPixmaps;
void updateCatListFromArray()
{
Categories cat( 0 );
cat.load( categoryFileName() );
mCatList = cat.labels("Document View",mCat);
}
void setCatArrayDirty()
{
mCat.resize(0);
}
void ensureCatArray()
{
if ( mCat.count() > 0 || mCatList.count()==0 )
return;
Categories cat( 0 );
cat.load( categoryFileName() );
mCat.resize( mCatList.count() );
int i;
QStringList::ConstIterator it;
for ( i = 0, it = mCatList.begin(); it != mCatList.end();
++it, i++ ) {
bool number;
int id = (*it).toInt( &number );
if ( !number ) {
id = cat.id( "Document View", *it );
if ( id == 0 )
id = cat.addCategory( "Document View", *it );
}
mCat[i] = id;
}
}
};
/*!
\class AppLnk applnk.h
\brief The AppLnk class represents an application available on the system.
Every Qtopia application \e app has a corresponding \e app.desktop
file. When one of these files is read its data is stored as an
AppLnk object.
The AppLnk class introduces some Qtopia-specific concepts, and
provides a variety of functions, as described in the following
sections.
\tableofcontents
\target Types
\section1 Types
Every AppLnk object has a \e type. For applications, games and
settings the type is \c Application; for documents the
type is the document's MIME type.
\target files-and-links
\section1 Files and Links
When you create an AppLnk (or more likely, a \link doclnk.html
DocLnk\endlink), you don't deal directly with filenames in the
filesystem. Instead you do this:
\code
DocLnk d;
d.setType("text/plain");
d.setName("My Nicely Named Document / Whatever"); // Yes, "/" is legal.
\endcode
At this point, the file() and linkFile() are unknown. Normally
this is uninteresting, and the names become automatically known,
and more importantly, becomes reserved, when you ask what they are:
\code
QString fn = d.file();
\endcode
This invents a filename, and creates the file on disk (an empty
reservation file) to prevent the name being used by another
application.
In some circumstances, you don't want to create the file if it
doesn't already exist (e.g. in the Document tab, some of the \link
doclnk.html DocLnk\endlink objects represented by icons are
DocLnk's created just for that view - they don't have
corresponding \c .desktop files. To avoid littering empty
reservation files around, we check in a few places to see whether
the file really needs to exist).
\section1 Functionality
AppLnk objects are created by calling the constructor with the
name of a \e .desktop file. The object can be checked for validity
using isValid().
The following functions are used to set or retrieve information
about the application:
\table
\header \i Get Function \i Set Function \i Short Description
\row \i \l name() \i \l setName() \i application's name
\row \i \l pixmap() \i \e none \i application's icon
\row \i \l bigPixmap() \i \e none \i application's large icon
\row \i \e none \i setIcon() \i sets the icon's filename
\row \i \l type() \i \l setType() \i see \link #Types Types\endlink above
\row \i \l rotation() \i \e none \i 0, 90, 180 or 270 degrees
\row \i \l comment() \i \l setComment() \i text for the Details dialog
\row \i \l exec() \i \l setExec() \i executable's filename
\row \i \l file() \i \e none \i document's filename
\row \i \l linkFile() \i \l setLinkFile() \i \e .desktop filename
\row \i \l mimeTypes() \i \e none \i the mime types the application can view or edit
\row \i \l categories() \i \l setCategories() \i \e{see the function descriptions}
\row \i \l fileKnown() \i \e none \i see \link
#files-and-links Files and Links\endlink above
\row \i \l linkFileKnown() \i \e none \i see \link
#files-and-links Files and Links\endlink above
\row \i \l property() \i \l setProperty() \i any AppLnk property
can be retrieved or set (if writeable) using these
\endtable
To save an AppLnk to disk use writeLink(). To execute the
application that the AppLnk object refers to, use execute().
AppLnk's can be deleted from disk using removeLinkFile(). To
remove both the link and the application's executable use
removeFiles().
Icon sizes can be globally changed (but only for AppLnk objects
created after the calls) with setSmallIconSize() and
setBigIconSize().
\ingroup qtopiaemb
*/
/*!
Sets the size used for small icons to \a small pixels.
Only affects AppLnk objects created after the call.
\sa smallIconSize() setIcon()
*/
void AppLnk::setSmallIconSize(int small)
{
smallSize = small;
}
/*!
Returns the size used for small icons.
\sa setSmallIconSize() setIcon()
*/
int AppLnk::smallIconSize()
{
return smallSize;
}
/*!
Sets the size used for large icons to \a big pixels.
Only affects AppLnk objects created after the call.
\sa bigIconSize() setIcon()
*/
void AppLnk::setBigIconSize(int big)
{
bigSize = big;
}
/*!
Returns the size used for large icons.
\sa setBigIconSize() setIcon()
*/
int AppLnk::bigIconSize()
{
return bigSize;
}
/*!
\fn QString AppLnk::name() const
Returns the Name property. This is the user-visible name for the
document or application, not the filename.
See \link #files-and-links Files and Links\endlink.
\sa setName()
*/
/*!
\fn QString AppLnk::exec() const
Returns the Exec property. This is the name of the executable
program associated with the AppLnk.
\sa setExec()
*/
/*!
\fn QString AppLnk::rotation() const
Returns the Rotation property. The value is 0, 90, 180 or 270
degrees.
*/
/*!
\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.
*/
/*!
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 ( 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] = 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;