summaryrefslogtreecommitdiff
authorwimpie <wimpie>2005-01-09 02:59:13 (UTC)
committer wimpie <wimpie>2005-01-09 02:59:13 (UTC)
commit987bc9a2c5b39ddd4dc2a665cea65688bfd2179e (patch) (side-by-side diff)
tree815fc6d12162f1a5eccc4b1ae0da61dea3811bdf
parente54346d28b19d3ac671802a25e8c03f346693291 (diff)
downloadopie-987bc9a2c5b39ddd4dc2a665cea65688bfd2179e.zip
opie-987bc9a2c5b39ddd4dc2a665cea65688bfd2179e.tar.gz
opie-987bc9a2c5b39ddd4dc2a665cea65688bfd2179e.tar.bz2
applnk : lazy loading of mime type icons (load only when needed)
resource.cpp : print warning when requested image cannot be found and print the name of that image too
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--library/applnk.cpp60
-rw-r--r--library/resource.cpp11
2 files changed, 54 insertions, 17 deletions
diff --git a/library/applnk.cpp b/library/applnk.cpp
index 1c1a227..80f2c62 100644
--- a/library/applnk.cpp
+++ b/library/applnk.cpp
@@ -856,481 +856,513 @@ bool AppLnk::writeLink() const
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 AppLnkImagePrivate {
+public :
+ AppLnkImagePrivate( const QString & ImageName ) {
+ IconName = ImageName;
+ Small = 0;
+ Big = 0;
+ }
+ ~AppLnkImagePrivate( ) {
+ if ( Small ) delete Small;
+ if ( Big ) delete Big;
+ }
+
+ inline QPixmap * small( void ) {
+ if( ! Small ) {
+ QImage unscaledIcon = Resource::loadImage( IconName );
+ // works as long as smallSize remains static
+ Small = new QPixmap();
+ Small->convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) );
+ }
+ return Small;
+ }
+
+ inline QPixmap * big( void ) {
+ if( ! Big ) {
+ QImage unscaledIcon = Resource::loadImage( IconName );
+ // works as long as bigSize remains static
+ Big = new QPixmap();
+ Big->convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) );
+ }
+ return Big;
+ }
+
+ QString IconName;
+ QPixmap * Small;
+ QPixmap * Big;
+};
+
class AppLnkSetPrivate {
public:
AppLnkSetPrivate()
{
typPix.setAutoDelete(TRUE);
- typPixBig.setAutoDelete(TRUE);
typName.setAutoDelete(TRUE);
}
- QDict<QPixmap> typPix;
- QDict<QPixmap> typPixBig;
+ QDict<AppLnkImagePrivate> typPix;
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() ) {
- QString iconFile = config.readEntry( "Icon", "AppsIcon" );
- QImage unscaledIcon = Resource::loadImage( iconFile );
- QPixmap pm, bpm;
- pm.convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) );
- bpm.convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) );
- d->typPix.insert(typ, new QPixmap(pm));
- d->typPixBig.insert(typ, new QPixmap(bpm));
+ d->typPix.insert( typ,
+ new AppLnkImagePrivate( config.readEntry( "Icon", "AppsIcon" ) )
+ );
d->typName.insert(typ, new QString(typNameLocal));
+
}
}
const QFileInfoList *list = dir.entryInfoList();
if ( list ) {
QFileInfo* fi;
bool cadded=FALSE;
for ( QFileInfoListIterator it(*list); (fi=*it); ++it ) {
QString bn = fi->fileName();
// qDebug("findChildren "+bn);
if ( bn[0] != '.' && bn != "CVS" ) {
if ( fi->isDir() ) {
QString c = typ.isNull() ? bn : typ+"/"+bn;
QString d = typNameLocal.isNull() ? bn : typNameLocal+"/"+bn;
findChildren(fi->filePath(), c, d, depth );
} else {
if ( fi->extension(FALSE) == "desktop" ) {
AppLnk* app = new AppLnk( fi->filePath() );
#ifdef QT_NO_QWS_MULTIPROCESS
if ( !Global::isBuiltinCommand( app->exec() ) )
delete app;
else
#endif
{
if ( !typ.isEmpty() ) {
if ( !cadded ) {
typs.append(typ);
cadded = TRUE;
}
app->setType(typ);
}
add(app);
}
}
}
}
}
}
}
/*!
Adds AppLnk \a f to the set. The set takes responsibility for
deleting \a f.
\sa remove()
*/
void AppLnkSet::add( AppLnk *f )
{
if ( f->mId == 0 ) {
AppLnk::lastId++;
f->mId = AppLnk::lastId;
mApps.append( f );
} else {
qWarning("Attempt to add an AppLnk twice");
}
}
/*!
Removes AppLnk \a f to the set. The caller becomes responsible for
deleting \a f. Returns TRUE if \a f was in the set; otherwise
returns FALSE.
\sa add()
*/
bool AppLnkSet::remove( AppLnk *f )
{
if ( mApps.remove( f ) ) {
f->mId = 0;
return TRUE;
}
return FALSE;
}
/*!
Returns the localized name for type \a t.
For applications, games and settings the type is \c Application;
for documents the type is the document's MIME type.
*/
QString AppLnkSet::typeName( const QString& t ) const
{
QString *st = d->typName.find(t);
return st ? *st : QString::null;
}
/*!
Returns the small pixmap associated with type \a t.
For applications, games and settings the type is \c Application;
for documents the type is the document's MIME type.
*/
QPixmap AppLnkSet::typePixmap( const QString& t ) const
{
- QPixmap *pm = d->typPix.find(t);
- return pm ? *pm : QPixmap();
+ AppLnkImagePrivate *alip = d->typPix.find(t);
+ return alip ? *(alip->small()) : QPixmap();
}
/*!
Returns the large pixmap associated with type \a t.
For applications, games and settings the type is \c Application;
for documents the type is the document's MIME type.
*/
QPixmap AppLnkSet::typeBigPixmap( const QString& t ) const
{
- QPixmap *pm = d->typPixBig.find(t);
- return pm ? *pm : QPixmap();
+ AppLnkImagePrivate *alip = d->typPix.find(t);
+ return alip ? *(alip->big()) : QPixmap();
}
/*!
Returns the AppLnk with the given \a id.
*/
const AppLnk *AppLnkSet::find( int id ) const
{
QListIterator<AppLnk> it( children() );
for ( ; it.current(); ++it ) {
const AppLnk *app = it.current();
if ( app->id() == id )
return app;
}
return 0;
}
/*!
Returns the AppLnk with the given \a exec attribute.
*/
const AppLnk *AppLnkSet::findExec( const QString& exec ) const
{
QListIterator<AppLnk> it( children() );
for ( ; it.current(); ++it ) {
const AppLnk *app = it.current();
if ( app->exec() == exec )
return app;
}
return 0;
}
/*!
\class DocLnkSet applnk.h
\brief The DocLnkSet class is a set of DocLnk objects.
*/
/*!
\fn const QList<DocLnk>& DocLnkSet::children() const
Returns the members of the set.
*/
/*!
Constructs an empty DocLnkSet.
\sa appendFrom()
*/
DocLnkSet::DocLnkSet()
{
}
/*!
Constructs a DocLnkSet that contains DocLnk objects representing all
the files in the \a directory (and any subdirectories, recursively).
If \a mimefilter is not null,
only documents with a MIME type matching \a mimefilter are selected.
The value may contain multiple wild-card patterns separated by ";",
such as \c{*o/mpeg;audio/x-wav}.
See also \link applnk.html#files-and-links Files and Links\endlink.
*/
DocLnkSet::DocLnkSet( const QString &directory, const QString& mimefilter ) :
AppLnkSet()
{
QDir dir( directory );
mFile = dir.dirName();
QDict<void> reference(1021);
QStringList subFilter = QStringList::split(";", mimefilter);
QValueList<QRegExp> mimeFilters;
for( QStringList::Iterator it = subFilter.begin(); it != subFilter.end(); ++ it )
mimeFilters.append( QRegExp(*it, FALSE, TRUE) );
findChildren(directory, mimeFilters, reference);
const QList<DocLnk> &list = children();
for ( QListIterator<DocLnk> it( list ); it.current(); ++it ) {
reference.remove( (*it)->file() );
}
for ( QDictIterator<void> dit(reference); dit.current(); ++dit ) {
if ( dit.current() == (void*)2 ) {
// Unreferenced, make an unwritten link
DocLnk* dl = new DocLnk;
QFileInfo fi( dit.currentKey() );
dl->setFile(fi.filePath());
dl->setName(fi.baseName());
// #### default to current path?
// dl->setCategories( ... );
bool match = mimefilter.isNull();
if ( !match )
for( QValueList<QRegExp>::Iterator it = mimeFilters.begin(); it != mimeFilters.end() && !match; ++ it )
if ( (*it).match(dl->type()) >= 0 )
match = TRUE;
if ( match /* && dl->type() != "application/octet-stream" */
&& !!dl->exec() )
add(dl);
else
delete dl;
}
}
}
// other becomes empty
/*!
Transfers all DocLnk objects from \a other to this set. \a other becomes
empty.
*/
void DocLnkSet::appendFrom( DocLnkSet& other )
{
if ( &other == this )
return;
QListIterator<AppLnk> it( other.mApps );
for ( ; it.current(); ) {
mApps.append(*it);
++it;
}
other.mApps.clear();
}
void DocLnkSet::findChildren(const QString &dr, const QValueList<QRegExp> &mimeFilters, QDict<void> &reference, int depth)
{
depth++;
if ( depth > 10 )
diff --git a/library/resource.cpp b/library/resource.cpp
index cfa0d26..b31876f 100644
--- a/library/resource.cpp
+++ b/library/resource.cpp
@@ -1,230 +1,235 @@
/**********************************************************************
** 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
#include <qpe/qpeapplication.h>
#include "resource.h"
#include "mimetype.h"
#include <qdir.h>
#include <qpixmapcache.h>
// this namespace is just a workaround for a gcc bug
// gcc exports inline functions in the generated file
// inlinepics_p.h
namespace {
#include "inlinepics_p.h"
}
static bool g_notUseSet = ::getenv("OVERWRITE_ICON_SET");
/*!
\class Resource resource.h
\brief The Resource class provides access to named resources.
The resources may be provided from files or other sources.
The allSounds() function returns a list of all the sounds available.
A particular sound can be searched for using findSound().
Images can be loaded with loadImage(), loadPixmap(), loadBitmap()
and loadIconSet().
\ingroup qtopiaemb
*/
/*!
\fn Resource::Resource()
\internal
*/
/*!
Returns the QPixmap called \a pix. You should avoid including
any filename type extension (e.g. .png, .xpm).
*/
+#include <stdio.h>
QPixmap Resource::loadPixmap( const QString &pix )
{
- QPixmap pm;
+ QPixmap pm; // null pixmap
QString key="QPE_"+pix;
if ( !QPixmapCache::find(key,pm) ) {
- pm.convertFromImage(loadImage(pix));
+ QImage I = loadImage(pix);
+ if( I.isNull() ) {
+ qWarning( "Could not load %s", pix.latin1() );
+ } else {
+ pm.convertFromImage(I);
QPixmapCache::insert(key,pm);
}
+ }
return pm;
}
/*!
Returns the QBitmap called \a pix. You should avoid including
any filename type extension (e.g. .png, .xpm).
*/
QBitmap Resource::loadBitmap( const QString &pix )
{
QBitmap bm;
bm = loadPixmap(pix);
return bm;
}
/*!
Returns the filename of a pixmap called \a pix. You should avoid including
any filename type extension (e.g. .png, .xpm).
Normally you will use loadPixmap() rather than this function.
*/
QString Resource::findPixmap( const QString &pix )
{
QString picsPath = QPEApplication::qpeDir() + "pics/";
QString f;
// Common case optimizations...
f = picsPath + pix + ".png";
if ( QFile( f ).exists() )
return f;
f = picsPath + pix + ".xpm";
if ( QFile( f ).exists() )
return f;
-
// All formats...
QStrList fileFormats = QImageIO::inputFormats();
QString ff = fileFormats.first();
while ( fileFormats.current() ) {
QStringList exts = MimeType("image/"+ff.lower()).extensions();
for ( QStringList::ConstIterator it = exts.begin(); it!=exts.end(); ++it ) {
QString f = picsPath + pix + "." + *it;
if ( QFile(f).exists() )
return f;
}
ff = fileFormats.next();
}
// Finally, no (or existing) extension...
if ( QFile( picsPath + pix ).exists() )
return picsPath + pix;
//qDebug("Cannot find pixmap: %s", pix.latin1());
return QString();
}
/*!
Returns a sound file for a sound called \a name.
You should avoid including any filename type extension (e.g. .wav),
as the system will search for only those fileformats which are supported
by the library.
Currently, only WAV files are supported.
*/
QString Resource::findSound( const QString &name )
{
QString picsPath = QPEApplication::qpeDir() + "sounds/";
QString result;
if ( QFile( (result = picsPath + name + ".wav") ).exists() )
return result;
return QString();
}
/*!
Returns a list of all sound names.
*/
QStringList Resource::allSounds()
{
QDir resourcedir( QPEApplication::qpeDir() + "sounds/", "*.wav" );
QStringList entries = resourcedir.entryList();
QStringList result;
for (QStringList::Iterator i=entries.begin(); i != entries.end(); ++i)
result.append((*i).replace(QRegExp("\\.wav"),""));
return result;
}
static QImage load_image(const QString &name)
{
if (g_notUseSet ) {
// try file
QImage img;
QString f = Resource::findPixmap(name);
if ( !f.isEmpty() )
img.load(f);
if (img.isNull() )
img = qembed_findImage(name.latin1() );
return img;
}
else{
QImage img = qembed_findImage(name.latin1());
if ( img.isNull() ) {
// No inlined image, try file
QString f = Resource::findPixmap(name);
if ( !f.isEmpty() )
img.load(f);
}
return img;
}
}
/*!
Returns the QImage called \a name. You should avoid including
any filename type extension (e.g. .png, .xpm).
*/
QImage Resource::loadImage( const QString &name)
{
#ifndef QT_NO_DEPTH_32 // have alpha-blended pixmaps
static QImage last_enabled;
static QString last_enabled_name;
if ( name == last_enabled_name )
return last_enabled;
#endif
QImage img = load_image(name);
#ifndef QT_NO_DEPTH_32 // have alpha-blended pixmaps
if ( img.isNull() ) {
// No file, try generating
if ( name[name.length()-1]=='d' && name.right(9)=="_disabled" ) {
last_enabled_name = name.left(name.length()-9);
last_enabled = load_image(last_enabled_name);
if ( last_enabled.isNull() ) {
last_enabled_name = QString::null;
} else {
img.detach();
img.create( last_enabled.width(), last_enabled.height(), 32 );
for ( int y = 0; y < img.height(); y++ ) {
for ( int x = 0; x < img.width(); x++ ) {
QRgb p = last_enabled.pixel( x, y );
int a = qAlpha(p)/3;
int g = qGray(qRed(p),qGreen(p),qBlue(p));
img.setPixel( x, y, qRgba(g,g,g,a) );
}
}
img.setAlphaBuffer( TRUE );
}
}
}
#endif
return img;
}
/*!
\fn QIconSet Resource::loadIconSet( const QString &name )
Returns a QIconSet for the pixmap named \a name. A disabled icon is
generated that conforms to the Qtopia look & feel. You should avoid
including any filename type extension (eg. .png, .xpm).
*/