summaryrefslogtreecommitdiff
authorleseb <leseb>2002-08-30 18:10:11 (UTC)
committer leseb <leseb>2002-08-30 18:10:11 (UTC)
commitb5ec106e5f612042987397a5a5b6683fdabaf793 (patch) (side-by-side diff)
tree58da0aac60a7a39cca162fe222107c9e3d676dac
parentf6125710c0ca99fc62ffce69973a168b6604f29d (diff)
downloadopie-b5ec106e5f612042987397a5a5b6683fdabaf793.zip
opie-b5ec106e5f612042987397a5a5b6683fdabaf793.tar.gz
opie-b5ec106e5f612042987397a5a5b6683fdabaf793.tar.bz2
Try to handle RAM storage for documents
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--library/applnk.cpp2
-rw-r--r--library/global.cpp4
-rw-r--r--library/lnkproperties.cpp7
-rw-r--r--library/storage.cpp14
4 files changed, 16 insertions, 11 deletions
diff --git a/library/applnk.cpp b/library/applnk.cpp
index 5185b5f..778ccab 100644
--- a/library/applnk.cpp
+++ b/library/applnk.cpp
@@ -1,1122 +1,1122 @@
/**********************************************************************
** 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.]"),"_"); // 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;
}
/*!
\fn QString AppLnk::name() const
Returns the Name property.
*/
/*!
\fn QString AppLnk::exec() const
Returns the Exec property. This is the executable program associated
with the AppLnk.
*/
/*!
\fn QString AppLnk::rotation() const
Returns the Rotation property.
*/
/*!
\fn QString AppLnk::comment() const
Returns the Comment property.
*/
/*!
\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.
*/
const QArray<int>& AppLnk::categories() const
{
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.
*/
/*!
\fn bool AppLnk::isValid() const
Returns whether this AppLnk is valid.
*/
/*!
Creates an invalid AppLnk.
\sa isValid()
*/
AppLnk::AppLnk()
{
mId = 0;
d = new AppLnkPrivate();
}
/*!
Loads \a file as an AppLnk.
*/
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 );
mMimeTypes = config.readListEntry( "MimeType", ';' );
mMimeTypeIcons = config.readListEntry( "MimeTypeIcons", ';' );
mLinkFile = file;
mFile = config.readEntry("File", QString::null);
sl = config.readListEntry("Categories", ';');
}
}
// let's try our darndest to create categories...
Categories cat( 0 );
cat.load( categoryFileName() );
d->mCat.resize( sl.count() );
int i;
QStringList::Iterator it;
for ( i = 0, it = sl.begin(); it != sl.end();
++it, i++ ) {
bool number;
int id = (*it).toInt( &number );
if ( !number ) {
// convert from old school...
id = cat.id( "Document Viewer", *it );
if ( id == 0 )
id = cat.addCategory( "Document Viewer", *it );
}
d->mCat[i] = id;
}
mId = 0;
}
/*!
Returns a small pixmap associated with the application.
*/
const QPixmap& AppLnk::pixmap() const
{
if ( mPixmap.isNull() ) {
AppLnk* that = (AppLnk*)this;
if ( mIconFile.isEmpty() ) {
MimeType mt(type());
that->mPixmap = mt.pixmap();
if ( that->mPixmap.isNull() )
that->mPixmap = Resource::loadPixmap("UnknownDocument-14");
return that->mPixmap;
}
QImage unscaledIcon = Resource::loadImage( that->mIconFile );
that->mPixmap.convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) );
that->mBigPixmap.convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) );
return that->mPixmap;
}
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; // 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+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)))+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 );
- if ( fs && fs->isRemovable() ) {
+ 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);
if ( QFile::exists(that->mLinkFile+".desktop") ) { // ok the file exists lets check if we point to the same file
int n=1;
QString nn;
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++;
AppLnk lnk(nn ); // just to be sure
if(lnk.file() ==that->file() ){
break;
}
}
that->mLinkFile = nn;
}
}
that->mLinkFile += ".desktop";
qWarning("AppLnk::linkFile is %s", that->mLinkFile.latin1() );
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;
}
/*!
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());
}
/*!
Executes the application associated with this AppLnk, with
\a args as arguments.
*/
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, you should not call it directly.
\sa execute()
*/
void AppLnk::invoke(const QStringList& args) const
{
Global::execute( exec(), args[0] );
}
/*!
Sets the Exec property to \a exec.
\sa exec()
*/
void AppLnk::setExec( const QString& exec )
{
mExec = exec;
}
/*!
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()
*/
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.
\sa comment()
*/
void AppLnk::setComment( const QString& comment )
{
mComment = 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();
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;
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 << 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 || !linkFileKnown() || QFile::remove(linkFile()) ) {
if ( QFile::remove(file()) ) {
QCopEnvelope e("QPE/System", "linkChanged(QString)");
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() && 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
all the files in a \a directory (recursively).
The directories may contain ".directory" files which overrides
any AppLnk::type() value of AppLnk objects found in the directory.
This allows simple localization of application types.
*/
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 call 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 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->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();
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 \a f to the set. The set takes over 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 \a f to the set, returning whether \a f was in the set.
The caller becomes responsible for deleting \a f.
\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.
*/
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.
*/
QPixmap AppLnkSet::typePixmap( const QString& t ) const
{
QPixmap *pm = d->typPix.find(t);
return pm ? *pm : QPixmap();
}
/*!
Returns the large pixmap associated with type \a t.
*/
QPixmap AppLnkSet::typeBigPixmap( const QString& t ) const
{
QPixmap *pm = d->typPixBig.find(t);
return pm ? *pm : 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 an DocLnkSet that contains DocLnk objects representing
all the files in a \a directory (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 "*o/mpeg;audio/x-wav".
*/
DocLnkSet::DocLnkSet( const QString &directory, const QString& mimefilter ) :
AppLnkSet()
{
QDir dir( directory );
mFile = dir.dirName();
QDict<void> reference;
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 )
return;
QDir dir( dr );
const QFileInfoList *list = dir.entryInfoList();
if ( list ) {
QFileInfo* fi;
for ( QFileInfoListIterator it(*list); (fi=*it); ++it ) {
QString bn = fi->fileName();
if ( bn[0] != '.' && bn != "CVS" ) {
if ( fi->isDir() ) {
findChildren(fi->filePath(), mimeFilters, reference, depth);
} else {
if ( fi->extension(FALSE) == "desktop" ) {
DocLnk* dl = new DocLnk( fi->filePath() );
QFileInfo fi2(dl->file());
bool match = FALSE;
if ( !fi2.exists() ) {
dir.remove( dl->file() );
}
if ( mimeFilters.count() == 0 ) {
add( dl );
match = TRUE;
} else {
for( QValueList<QRegExp>::ConstIterator it = mimeFilters.begin(); it != mimeFilters.end(); ++ it ) {
if ( (*it).match(dl->type()) >= 0 ) {
add(dl);
match = TRUE;
}
}
}
if ( !match )
delete dl;
} else {
if ( !reference.find(fi->fileName()) )
reference.insert(fi->filePath(), (void*)2);
}
}
}
}
}
}
/*!
\class DocLnk applnk.h
\brief The DocLnk class represents loaded document references.
*/
/*!
\fn DocLnk::DocLnk( const DocLnk &o )
Copies \a o.
*/
/*!
Constructs a DocLnk from a valid .desktop \a file or a new .desktop
\a file for other files.
*/
DocLnk::DocLnk( const QString &file ) :
AppLnk(file)
{
init(file);
}
/*!
Constructs a DocLnk from a valid .desktop \a file or a new .desktop
\a file for other files. If \a may_be_desktopfile is TRUE, then \a file
is first attempted to be read as a .desktop file.
*/
DocLnk::DocLnk( const QString &file, bool may_be_desktopfile ) :
AppLnk(may_be_desktopfile ? file : QString::null)
{
init(file);
}
void DocLnk::init(const QString &file)
{
if ( isValid() ) {
#ifndef FORCED_DIR_STRUCTURE_WAY
if ( mType.isNull() )
// try to infer it
#endif
{
int s0 = file.findRev('/');
if ( s0 > 0 ) {
int s1 = file.findRev('/',s0-1);
if ( s1 > 0 ) {
int s2 = file.findRev('/',s1-1);
if ( s2 > 0 ) {
mType = file.mid(s2+1,s0-s2-1);
}
}
}
}
} else if ( QFile::exists(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 ( linkFileKnown() && QFile::exists( linkFile() ) )
a.append(linkFile());
else
a.append(file());
app->execute(a);
}
}
diff --git a/library/global.cpp b/library/global.cpp
index edb7b85..ab27b3f 100644
--- a/library/global.cpp
+++ b/library/global.cpp
@@ -1,726 +1,730 @@
/**********************************************************************
** 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_LANGLIST
#include <qpe/qpedebug.h>
#include <qpe/global.h>
#include <qpe/qdawg.h>
#include <qpe/qpeapplication.h>
#include <qpe/resource.h>
#include <qpe/storage.h>
#include <qpe/applnk.h>
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
#include "qpe/qcopenvelope_qws.h"
#endif
#include <qfile.h>
#include <qlabel.h>
#include <qtimer.h>
#include <qmap.h>
#include <qdict.h>
#include <qdir.h>
#include <qmessagebox.h>
#include <qregexp.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <qwindowsystem_qws.h> // for qwsServer
#include <qdatetime.h>
#include <qfile.h>
namespace {
// checks if the storage should be searched
bool checkStorage(const QString &path ){ // this is a small Config replacement cause config is too limited -zecke
QFile file(path );
if(!file.open(IO_ReadOnly ) )
return true;
QByteArray array = file.readAll();
QStringList list = QStringList::split('\n', QString( array ) );
for(QStringList::Iterator it = list.begin(); it != list.end(); ++it ){
if( (*it).startsWith("autocheck = 0" ) ){
return false;
}else if( (*it).startsWith("autocheck = 1" ) ){
return true;
}
}
return true;
}
}
//#include "quickexec_p.h"
class Emitter : public QObject {
Q_OBJECT
public:
Emitter( QWidget* receiver, const QString& document )
{
connect(this, SIGNAL(setDocument(const QString&)),
receiver, SLOT(setDocument(const QString&)));
emit setDocument(document);
disconnect(this, SIGNAL(setDocument(const QString&)),
receiver, SLOT(setDocument(const QString&)));
}
signals:
void setDocument(const QString&);
};
class StartingAppList : public QObject {
Q_OBJECT
public:
static void add( const QString& name );
static bool isStarting( const QString name );
private slots:
void handleNewChannel( const QString &);
private:
StartingAppList( QObject *parent=0, const char* name=0 ) ;
QDict<QTime> dict;
static StartingAppList *appl;
};
StartingAppList* StartingAppList::appl = 0;
StartingAppList::StartingAppList( QObject *parent, const char* name )
:QObject( parent, name )
{
#if QT_VERSION >= 232 && !defined(QT_NO_COP)
connect( qwsServer, SIGNAL( newChannel(const QString&)),
this, SLOT( handleNewChannel(const QString&)) );
dict.setAutoDelete( TRUE );
#endif
}
void StartingAppList::add( const QString& name )
{
#if QT_VERSION >= 232 && !defined(QT_NO_COP)
if ( !appl )
appl = new StartingAppList;
QTime *t = new QTime;
t->start();
appl->dict.insert( "QPE/Application/" + name, t );
#endif
}
bool StartingAppList::isStarting( const QString name )
{
#if QT_VERSION >= 232 && !defined(QT_NO_COP)
if ( appl ) {
QTime *t = appl->dict.find( "QPE/Application/" + name );
if ( !t )
return FALSE;
if ( t->elapsed() > 10000 ) {
// timeout in case of crash or something
appl->dict.remove( "QPE/Application/" + name );
return FALSE;
}
return TRUE;
}
#endif
return FALSE;
}
void StartingAppList::handleNewChannel( const QString & name )
{
#if QT_VERSION >= 232 && !defined(QT_NO_COP)
dict.remove( name );
#endif
}
static bool docDirCreated = FALSE;
static QDawg* fixed_dawg = 0;
static QDict<QDawg> *named_dawg = 0;
static QString qpeDir()
{
QString dir = getenv("OPIEDIR");
if ( dir.isEmpty() ) dir = "..";
return dir;
}
static QString dictDir()
{
return qpeDir() + "/etc/dict";
}
/*!
\class Global global.h
\brief The Global class collects application-wide global functions.
*/
/*!
\internal
*/
Global::Global()
{
}
/*!
Returns the unchangeable QDawg that contains general
words for the current locale.
\sa addedDawg()
*/
const QDawg& Global::fixedDawg()
{
if ( !fixed_dawg ) {
if ( !docDirCreated )
createDocDir();
fixed_dawg = new QDawg;
QString dawgfilename = dictDir() + "/dawg";
QString words_lang;
QStringList langs = Global::languageList();
for (QStringList::ConstIterator it = langs.begin(); it!=langs.end(); ++it) {
QString lang = *it;
words_lang = dictDir() + "/words." + lang;
QString dawgfilename_lang = dawgfilename + "." + lang;
if ( QFile::exists(dawgfilename_lang) ||
QFile::exists(words_lang) ) {
dawgfilename = dawgfilename_lang;
break;
}
}
QFile dawgfile(dawgfilename);
if ( !dawgfile.exists() ) {
QString fn = dictDir() + "/words";
if ( QFile::exists(words_lang) )
fn = words_lang;
QFile in(fn);
if ( in.open(IO_ReadOnly) ) {
fixed_dawg->createFromWords(&in);
dawgfile.open(IO_WriteOnly);
fixed_dawg->write(&dawgfile);
dawgfile.close();
}
} else {
fixed_dawg->readFile(dawgfilename);
}
}
return *fixed_dawg;
}
/*!
Returns the changeable QDawg that contains general
words for the current locale.
\sa fixedDawg()
*/
const QDawg& Global::addedDawg()
{
return dawg("local");
}
/*!
Returns the QDawg with the given \a name.
This is an application-specific word list.
\a name should not contain "/".
*/
const QDawg& Global::dawg(const QString& name)
{
createDocDir();
if ( !named_dawg )
named_dawg = new QDict<QDawg>;
QDawg* r = named_dawg->find(name);
if ( !r ) {
r = new QDawg;
named_dawg->insert(name,r);
QString dawgfilename = dictDir() + "/" + name + ".dawg";
QFile dawgfile(dawgfilename);
if ( dawgfile.open(IO_ReadOnly) )
r->readFile(dawgfilename);
}
return *r;
}
/*!
Adds \a wordlist to the addedDawg().
*/
void Global::addWords(const QStringList& wordlist)
{
addWords("local",wordlist);
}
/*!
Adds \a wordlist to the dawg() named \a dictname.
*/
void Global::addWords(const QString& dictname, const QStringList& wordlist)
{
QDawg& d = (QDawg&)dawg(dictname);
QStringList all = d.allWords() + wordlist;
d.createFromWords(all);
QString dawgfilename = dictDir() + "/" + dictname + ".dawg";
QFile dawgfile(dawgfilename);
if ( dawgfile.open(IO_WriteOnly) ) {
d.write(&dawgfile);
dawgfile.close();
}
// #### Re-read the dawg here if we use mmap().
// #### Signal other processes to re-read.
}
/*!
Returns a full path for the application named \a appname, with the
given \a filename or QString::null if there was a problem creating
the directory tree for \a appname.
If \a filename contains "/", it is the caller's responsibility to
ensure those directories exist.
*/
QString Global::applicationFileName(const QString& appname, const QString& filename)
{
QDir d;
QString r = getenv("HOME");
r += "/Applications/";
if ( !QFile::exists( r ) )
if ( d.mkdir(r) == false )
return QString::null;
r += appname;
if ( !QFile::exists( r ) )
if ( d.mkdir(r) == false )
return QString::null;
r += "/"; r += filename;
return r;
}
/*!
\internal
*/
void Global::createDocDir()
{
if ( !docDirCreated ) {
docDirCreated = TRUE;
mkdir( QPEApplication::documentDir().latin1(), 0755 );
}
}
/*!
Displays a status \a message to the user. This generally appears
in the taskbar for some amount of time, then disappears.
*/
void Global::statusMessage(const QString& message)
{
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
QCopEnvelope e( "QPE/TaskBar", "message(QString)" );
e << message;
#endif
}
/*!
\internal
*/
void Global::applyStyle()
{
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
QCopChannel::send( "QPE/System", "applyStyle()" );
#else
((QPEApplication *)qApp)->applyStyle(); // apply without needing QCop for floppy version
#endif
}
/*!
\internal
*/
QWidget *Global::shutdown( bool )
{
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
QCopChannel::send( "QPE/System", "shutdown()" );
#endif
return 0;
}
/*!
\internal
*/
QWidget *Global::restart( bool )
{
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
QCopChannel::send( "QPE/System", "restart()" );
#endif
return 0;
}
/*!
Explicitly show the current input method.
*/
void Global::showInputMethod()
{
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
QCopChannel::send( "QPE/TaskBar", "showInputMethod()" );
#endif
}
/*!
Explicitly hide the current input method.
*/
void Global::hideInputMethod()
{
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
QCopChannel::send( "QPE/TaskBar", "hideInputMethod()" );
#endif
}
/*!
\internal
*/
bool Global::isBuiltinCommand( const QString &name )
{
if(!builtin)
return FALSE; // yes, it can happen
for (int i = 0; builtin[i].file; i++) {
if ( builtin[i].file == name ) {
return TRUE;
}
}
return FALSE;
}
Global::Command* Global::builtin=0;
QGuardedPtr<QWidget> *Global::running=0;
/*!
\class Global::Command
\brief The Global::Command class is internal.
\internal
*/
/*!
\internal
*/
void Global::setBuiltinCommands( Command* list )
{
if ( running )
delete [] running;
builtin = list;
int count = 0;
if (!builtin)
return;
while ( builtin[count].file )
count++;
running = new QGuardedPtr<QWidget> [ count ];
}
/*!
\internal
*/
void Global::setDocument( QWidget* receiver, const QString& document )
{
Emitter emitter(receiver,document);
}
/*!
\internal
*/
bool Global::terminateBuiltin( const QString& n )
{
if (!builtin)
return FALSE;
for (int i = 0; builtin[i].file; i++) {
if ( builtin[i].file == n ) {
delete running[i];
return TRUE;
}
}
return FALSE;
}
/*!
\internal
*/
void Global::terminate( const AppLnk* app )
{
//if ( terminateBuiltin(app->exec()) ) return; // maybe? haven't tried this
QCString channel = "QPE/Application/" + app->exec().utf8();
if ( QCopChannel::isRegistered(channel) ) {
QCopEnvelope e(channel, "quit()");
}
}
/*!
Low-level function to run command \a c. Not recommended.
*/
void Global::invoke(const QString &c)
{
// Convert the command line in to a list of arguments
QStringList list = QStringList::split(QRegExp(" *"),c);
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
QString ap=list[0];
// see if the application is already running
// XXX should lock file /tmp/qcop-msg-ap
if ( QCopChannel::isRegistered( ("QPE/Application/" + ap).latin1() ) ) {
QCopEnvelope e("QPE/System", "notBusy(QString)" );
e << ap;
return;
}
// XXX should unlock file /tmp/qcop-msg-ap
//see if it is being started
if ( StartingAppList::isStarting( ap ) ) {
QCopEnvelope e("QPE/System", "notBusy(QString)" );
e << ap;
return;
}
#endif
#ifdef QT_NO_QWS_MULTIPROCESS
QMessageBox::warning( 0, "Error", "Could not find the application " + c, "Ok", 0, 0, 0, 1 );
#else
QStrList slist;
unsigned int j;
for ( j = 0; j < list.count(); j++ )
slist.append( list[j].utf8() );
const char **args = new (const char *)[slist.count() + 1];
for ( j = 0; j < slist.count(); j++ )
args[j] = slist.at(j);
args[j] = NULL;
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
// an attempt to show a wait...
// more logic should be used, but this will be fine for the moment...
QCopEnvelope ( "QPE/System", "busy()" );
#endif
#ifdef HAVE_QUICKEXEC
QString libexe = qpeDir()+"/binlib/lib"+args[0] + ".so";
qDebug("libfile = %s", libexe.latin1() );
if ( QFile::exists( libexe ) ) {
qDebug("calling quickexec %s", libexe.latin1() );
quickexecv( libexe.utf8().data(), (const char **)args );
} else
#endif
{
if ( !::vfork() ) {
for ( int fd = 3; fd < 100; fd++ )
::close( fd );
::setpgid( ::getpid(), ::getppid() );
// Try bindir first, so that foo/bar works too
::execv( qpeDir()+"/bin/"+args[0], (char * const *)args );
::execvp( args[0], (char * const *)args );
_exit( -1 );
}
}
StartingAppList::add( list[0] );
#endif //QT_NO_QWS_MULTIPROCESS
}
/*!
Executes application identfied by \a c, passing \a document.
Note that you might be better off sending a QCop message to
the application's QPE/Application/<i>appname</i> channel.
*/
void Global::execute( const QString &c, const QString& document )
{
if ( qApp->type() != QApplication::GuiServer ) {
// ask the server to do the work
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
if ( document.isNull() ) {
QCopEnvelope e( "QPE/System", "execute(QString)" );
e << c;
} else {
QCopEnvelope e( "QPE/System", "execute(QString,QString)" );
e << c << document;
}
#endif
return;
}
// Attempt to execute the app using a builtin class for the app first
// else try and find it in the bin directory
if (builtin) {
for (int i = 0; builtin[i].file; i++) {
if ( builtin[i].file == c ) {
if ( running[i] ) {
if ( !document.isNull() && builtin[i].documentary )
setDocument(running[i], document);
running[i]->raise();
running[i]->show();
running[i]->setActiveWindow();
} else {
running[i] = builtin[i].func( builtin[i].maximized );
}
QCopEnvelope e("QPE/System", "notBusy(QString)" );
e << c; // that was quick ;-)
return;
}
}
}
//Global::invoke(c, document);
// Convert the command line in to a list of arguments
QStringList list = QStringList::split(QRegExp(" *"),c);
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
QString ap=list[0];
qDebug("executing %s", ap.latin1() );
if ( ap == "suspend" ) {
QWSServer::sendKeyEvent( 0xffff, Qt::Key_F34, FALSE, TRUE, FALSE );
return;
}
/* if need be, sending a qcop message will result in an invoke, see
preceeding function */
{ QCopEnvelope env( ("QPE/Application/" + ap).latin1(), "raise()" ); }
if ( !document.isEmpty() ) {
QCopEnvelope env( ("QPE/Application/" + ap).latin1(), "setDocument(QString)" );
env << document;
}
#endif
}
/*!
Returns the string \a s with the characters backslash, ", and $
quoted by a preceeding backslash.
*/
QString Global::shellQuote(const QString& s)
{
QString r="\"";
for (int i=0; i<(int)s.length(); i++) {
char c = s[i].latin1();
switch (c) {
case '\\': case '"': case '$':
r+="\\";
}
r += s[i];
}
r += "\"";
return r;
}
/*!
Returns the string \a s with the characters backslash and "
quoted by a preceeding backslash.
*/
QString Global::stringQuote(const QString& s)
{
QString r="\"";
for (int i=0; i<(int)s.length(); i++) {
char c = s[i].latin1();
switch (c) {
case '\\': case '"':
r+="\\";
}
r += s[i];
}
r += "\"";
return r;
}
/*!
Finds all documents on the system's document directories which
match the filter \a mimefilter, and appends the resulting DocLnk
objects to \a folder.
*/
void Global::findDocuments(DocLnkSet* folder, const QString &mimefilter)
{
QString homedocs = QString(getenv("HOME")) + "/Documents";
DocLnkSet d(homedocs,mimefilter);
folder->appendFrom(d);
/** let's do intellegint way of searching these files
* a) the user don't want to check mediums global
* b) the user wants to check but use the global options for it
* c) the user wants to check it but not this medium
* d) the user wants to check and this medium as well
*
* In all cases we need to apply a different mimefilter to
* the medium.
* a) mimefilter.isEmpty() we need to apply the responding filter
* either the global or the one on the medium
*
* b) mimefilter is set to an application we need to find out if the
* mimetypes are included in the mime mask of the medium
*/
StorageInfo storage;
const QList<FileSystem> &fs = storage.fileSystems();
QListIterator<FileSystem> it ( fs );
for ( ; it.current(); ++it ) {
if ( (*it)->isRemovable() ) { // let's find out if we should search on it
// this is a candidate look at the cf and see if we should search on it
QString path = (*it)->path();
if( !checkStorage((*it)->path() + "/.opiestorage.cf" ) )
continue;
DocLnkSet ide( path, mimefilter );
folder->appendFrom(ide);
+ } else if ( (*it)->disk() == "/dev/mtdblock6" || (*it)->disk() == "tmpfs" ) {
+ QString path = (*it)->path() + "/Documents";
+ DocLnkSet ide( path, mimefilter );
+ folder->appendFrom(ide);
}
}
}
QStringList Global::languageList()
{
QString lang = getenv("LANG");
QStringList langs;
langs.append(lang);
int i = lang.find(".");
if ( i > 0 )
lang = lang.left( i );
i = lang.find( "_" );
if ( i > 0 )
langs.append(lang.left(i));
return langs;
}
QStringList Global::helpPath()
{
QStringList path;
QStringList langs = Global::languageList();
for (QStringList::ConstIterator it = langs.fromLast(); it!=langs.end(); --it) {
QString lang = *it;
if ( !lang.isEmpty() )
path += QPEApplication::qpeDir() + "/help/" + lang + "/html";
}
path += QPEApplication::qpeDir() + "/pics";
path += QPEApplication::qpeDir() + "/help/en/html";
path += QPEApplication::qpeDir() + "/docs";
QString dir = QDir::current().canonicalPath();
if ( dir == "/" )
dir += "/docs";
else {
path += dir + "/../pics";
dir += "/../docs";
path += dir;
}
return path;
}
#include "global.moc"
diff --git a/library/lnkproperties.cpp b/library/lnkproperties.cpp
index e8baca6..c020328 100644
--- a/library/lnkproperties.cpp
+++ b/library/lnkproperties.cpp
@@ -1,314 +1,315 @@
/**********************************************************************
** 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.
**
**********************************************************************/
// WARNING: Do *NOT* define this yourself. The SL5xxx from SHARP does NOT
// have this class.
#define QTOPIA_INTERNAL_FSLP
#include "lnkproperties.h"
#include "lnkproperties.h"
#include "lnkpropertiesbase_p.h"
#include "ir.h"
#include <qpe/applnk.h>
#include <qpe/global.h>
#include <qpe/categorywidget.h>
#include <qpe/qcopenvelope_qws.h>
#include <qpe/filemanager.h>
#include <qpe/config.h>
#include <qpe/storage.h>
#include <qpe/qpemessagebox.h>
#include <qlineedit.h>
#include <qtoolbutton.h>
#include <qpushbutton.h>
#include <qgroupbox.h>
#include <qcheckbox.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qmessagebox.h>
#include <qsize.h>
#include <qcombobox.h>
#include <qregexp.h>
#include <stdlib.h>
LnkProperties::LnkProperties( AppLnk* l, QWidget* parent )
: QDialog( parent, 0, TRUE ), lnk(l), fileSize( 0 )
{
QVBoxLayout *vbox = new QVBoxLayout( this );
d = new LnkPropertiesBase( this );
vbox->add( d );
d->docname->setText(l->name());
QString inf;
if ( l->type().isEmpty() ) {
d->type->hide();
d->typeLabel->hide();
} else {
d->type->setText( l->type() );
}
if ( l->comment().isEmpty() ) {
d->comment->hide();
d->commentLabel->hide();
} else {
d->comment->setText( l->comment() );
}
connect(d->beam,SIGNAL(clicked()),this,SLOT(beamLnk()));
if ( lnk->type().contains('/') ) { // A document? (#### better predicate needed)
connect(d->unlink,SIGNAL(clicked()),this,SLOT(unlinkLnk()));
connect(d->duplicate,SIGNAL(clicked()),this,SLOT(duplicateLnk()));
connect(d->delicon,SIGNAL(clicked()),this,SLOT(unlinkIcon()));
d->docname->setReadOnly( FALSE );
d->preload->hide();
d->spacer->hide();
// ### THIS MUST GO, FIX WIERD BUG in QLAYOUT
d->categoryEdit->kludge();
d->categoryEdit->setCategories( lnk->categories(),
"Document View",
tr("Document View") );
setupLocations();
} else {
d->unlink->hide();
d->duplicate->hide();
d->beam->hide();
d->hline->hide();
d->locationLabel->hide();
d->locationCombo->hide();
// Can't edit categories, since the app .desktop files are global,
// possibly read-only.
d->categoryEdit->hide();
d->docname->setReadOnly( TRUE );
if ( l->property("CanFastload") == "0" )
d->preload->hide();
Config cfg("Launcher");
cfg.setGroup("Preload");
QStringList apps = cfg.readListEntry("Apps",',');
d->preload->setChecked( apps.contains(l->exec()) );
if ( Global::isBuiltinCommand(lnk->exec()) )
d->preload->hide(); // builtins are always fast
currentLocation = 0; // apps not movable (yet)
}
setCaption( l->file());
}
LnkProperties::~LnkProperties()
{
}
void LnkProperties::unlinkLnk()
{
if ( QPEMessageBox::confirmDelete( this, tr("Delete"), lnk->name() ) ) {
if ( QFile::exists(lnk->file()) )
lnk->removeFiles();
else
QMessageBox::warning( this, tr("Delete"), tr("File does not exist.") );
if ( QFile::exists(lnk->file()) ) {
QMessageBox::warning( this, tr("Delete"), tr("File deletion failed.") );
} else {
reject();
}
}
}
/*
* remove only the link from documents, not also the file
*/
void LnkProperties::unlinkIcon()
{
if ( QPEMessageBox::confirmDelete( this, tr("Delete Icon and leave file"), lnk->name() ) ) {
lnk->removeLinkFile();
if ( QFile::exists(lnk->linkFile()) ) {
QMessageBox::warning( this, tr("Delete"), tr("Icon deletion failed.") );
} else {
reject();
}
}
}
void LnkProperties::setupLocations()
{
QFileInfo fi( lnk->file() );
fileSize = fi.size();
StorageInfo storage;
const QList<FileSystem> &fs = storage.fileSystems();
QListIterator<FileSystem> it ( fs );
QString s;
QString homeDir = getenv("HOME");
QString hardDiskHome;
QString hardDiskPath;
int index = 0;
currentLocation = -1;
for ( ; it.current(); ++it ) {
// we add 10k to the file size so we are sure we can also save the desktop file
if ( (*it)->availBlocks() * (*it)->blockSize() > fileSize + 10000 ) {
if ( (*it)->isRemovable() ||
(*it)->disk() == "/dev/mtdblock1" ||
- (*it)->disk() == "/dev/mtdblock/1" || (*it)->disk().left(13) == "/dev/mtdblock" ) {
+ (*it)->disk() == "/dev/mtdblock/1" || (*it)->disk().left(13) == "/dev/mtdblock" ||
+ (*it)->disk() == "/dev/mtdblock6" || (*it)->disk() == "tmpfs" ) {
d->locationCombo->insertItem( (*it)->name(), index );
- locations.append( ((*it)->isRemovable() ? (*it)->path() : homeDir) );
+ locations.append( ((*it)->isRemovable() || (*it)->disk() == "/dev/mtdblock6" || (*it)->disk() == "tmpfs" ? (*it)->path() : homeDir) );
if ( lnk->file().contains( (*it)->path() ) ) {
d->locationCombo->setCurrentItem( index );
currentLocation = index;
}
index++;
- } else if ( (*it)->name().contains( "Hard Disk") &&
+ } else if ( (*it)->name().contains( tr("Hard Disk") ) &&
homeDir.contains( (*it)->path() ) &&
(*it)->path().length() > hardDiskHome.length() ) {
hardDiskHome = (*it)->name();
hardDiskPath = (*it)->path();
}
}
}
if ( !hardDiskHome.isEmpty() ) {
d->locationCombo->insertItem( hardDiskHome );
locations.append( hardDiskPath );
if ( currentLocation == -1 ) { // assume it's the hard disk
d->locationCombo->setCurrentItem( index );
currentLocation = index;
}
}
}
void LnkProperties::duplicateLnk()
{
// The duplicate takes the new properties.
DocLnk newdoc( *((DocLnk *)lnk) );
if ( d->docname->text() == lnk->name() )
newdoc.setName(tr("Copy of ")+d->docname->text());
else
newdoc.setName(d->docname->text());
if ( !copyFile( newdoc ) ) {
QMessageBox::warning( this, tr("Duplicate"), tr("File copy failed.") );
return;
}
reject();
}
bool LnkProperties::moveLnk()
{
DocLnk newdoc( *((DocLnk *)lnk) );
newdoc.setName(d->docname->text());
if ( !copyFile( newdoc ) ) {
QMessageBox::warning( this, tr("Details"), tr("Moving Document failed.") );
return FALSE;
}
// remove old lnk
lnk->removeFiles();
return TRUE;
}
void LnkProperties::beamLnk()
{
Ir ir;
DocLnk doc( *((DocLnk *)lnk) );
ir.send( doc, doc.comment() );
}
bool LnkProperties::copyFile( DocLnk &newdoc )
{
const char *linkExtn = ".desktop";
QString fileExtn;
int extnPos = lnk->file().findRev( '.' );
if ( extnPos > 0 )
fileExtn = lnk->file().mid( extnPos );
QString safename = newdoc.name();
safename.replace(QRegExp("/"),"_");
QString fn = locations[ d->locationCombo->currentItem() ]
+ "/Documents/" + newdoc.type() + "/" + safename;
if ( QFile::exists(fn + fileExtn) || QFile::exists(fn + linkExtn) ) {
int n=1;
QString nn = fn + "_" + QString::number(n);
while ( QFile::exists(nn+fileExtn) || QFile::exists(nn+linkExtn) ) {
n++;
nn = fn + "_" + QString::number(n);
}
fn = nn;
}
newdoc.setFile( fn + fileExtn );
newdoc.setLinkFile( fn + linkExtn );
// Copy file
FileManager fm;
if ( !fm.copyFile( *lnk, newdoc ) )
return FALSE;
return TRUE;
}
void LnkProperties::done(int ok)
{
if ( ok ) {
bool changed=FALSE;
if ( lnk->name() != d->docname->text() ) {
lnk->setName(d->docname->text());
changed=TRUE;
}
if ( d->categoryEdit->isVisible() ) {
QArray<int> tmp = d->categoryEdit->newCategories();
if ( lnk->categories() != tmp ) {
lnk->setCategories( tmp );
changed = TRUE;
}
}
if ( d->preload->isHidden() && d->locationCombo->currentItem() != currentLocation ) {
moveLnk();
} else if ( changed ) {
lnk->writeLink();
}
if ( !d->preload->isHidden() ) {
Config cfg("Launcher");
cfg.setGroup("Preload");
QStringList apps = cfg.readListEntry("Apps",',');
QString exe = lnk->exec();
if ( apps.contains(exe) != d->preload->isChecked() ) {
if ( d->preload->isChecked() ) {
apps.append(exe);
QCopEnvelope e("QPE/Application/"+exe.local8Bit(),
"enablePreload()");
} else {
apps.remove(exe);
QCopEnvelope e("QPE/Application/"+exe.local8Bit(),
"quitIfInvisible()");
}
cfg.writeEntry("Apps",apps,',');
}
}
}
QDialog::done( ok );
}
diff --git a/library/storage.cpp b/library/storage.cpp
index 2d996fa..13639fe 100644
--- a/library/storage.cpp
+++ b/library/storage.cpp
@@ -1,196 +1,196 @@
/**********************************************************************
** Copyright (C) Holger 'zecke' Freyther <freyther@kde.org>
** 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.
**
**********************************************************************/
#include <qpe/storage.h>
#ifdef QT_QWS_CUSTOM
#include <qpe/custom.h>
#endif
#include <qfile.h>
#include <qtimer.h>
#include <qcopchannel_qws.h>
#include <stdio.h>
#if defined(_OS_LINUX_) || defined(Q_OS_LINUX)
#include <sys/vfs.h>
#include <mntent.h>
#endif
#include <qstringlist.h>
static bool isCF(const QString& m)
{
FILE* f = fopen("/var/run/stab", "r");
if (!f) f = fopen("/var/state/pcmcia/stab", "r");
if (!f) f = fopen("/var/lib/pcmcia/stab", "r");
if ( f ) {
char line[1024];
char devtype[80];
char devname[80];
while ( fgets( line, 1024, f ) ) {
// 0 ide ide-cs 0 hda 3 0
if ( sscanf(line,"%*d %s %*s %*s %s", devtype, devname )==2 )
{
if ( QString(devtype) == "ide" && m.find(devname)>0 ) {
fclose(f);
return TRUE;
}
}
}
fclose(f);
}
return FALSE;
}
StorageInfo::StorageInfo( QObject *parent )
: QObject( parent )
{
mFileSystems.setAutoDelete( TRUE );
channel = new QCopChannel( "QPE/Card", this );
connect( channel, SIGNAL(received(const QCString &, const QByteArray &)),
this, SLOT(cardMessage( const QCString &, const QByteArray &)) );
update();
}
const FileSystem *StorageInfo::fileSystemOf( const QString &filename )
{
for (QListIterator<FileSystem> i(mFileSystems); i.current(); ++i) {
if ( filename.startsWith( (*i)->path() ) )
return (*i);
}
return 0;
}
void StorageInfo::cardMessage( const QCString& msg, const QByteArray& )
{
if ( msg == "mtabChanged()" )
update();
}
// cause of the lack of a d pointer we need
// to store informations in a config file :(
void StorageInfo::update()
{
//qDebug("StorageInfo::updating");
#if defined(_OS_LINUX_) || defined(Q_OS_LINUX)
struct mntent *me;
FILE *mntfp = setmntent( "/etc/mtab", "r" );
QStringList curdisks;
QStringList curopts;
QStringList curfs;
bool rebuild = FALSE;
int n=0;
if ( mntfp ) {
while ( (me = getmntent( mntfp )) != 0 ) {
QString fs = me->mnt_fsname;
if ( fs.left(7)=="/dev/hd" || fs.left(7)=="/dev/sd"
|| fs.left(8)=="/dev/mtd" || fs.left(9) == "/dev/mmcd"
- || fs.left(8)=="/dev/ram" || fs.left(5)=="tmpfs" )
+ || fs.left(5)=="tmpfs" )
{
n++;
curdisks.append(fs);
curopts.append( me->mnt_opts );
//qDebug("-->fs %s opts %s", fs.latin1(), me->mnt_opts );
curfs.append( me->mnt_dir );
bool found = FALSE;
for (QListIterator<FileSystem> i(mFileSystems); i.current(); ++i) {
if ( (*i)->disk() == fs ) {
found = TRUE;
break;
}
}
if ( !found )
rebuild = TRUE;
}
}
endmntent( mntfp );
}
if ( rebuild || n != (int)mFileSystems.count() ) {
mFileSystems.clear();
QStringList::ConstIterator it=curdisks.begin();
QStringList::ConstIterator fsit=curfs.begin();
QStringList::ConstIterator optsIt=curopts.begin();
for (; it!=curdisks.end(); ++it, ++fsit, ++optsIt) {
QString opts = *optsIt;
QString disk = *it;
QString humanname;
bool removable = FALSE;
if ( isCF(disk) ) {
humanname = tr("CF Card");
removable = TRUE;
} else if ( disk == "/dev/hda1" ) {
humanname = tr("Hard Disk");
} else if ( disk.left(9) == "/dev/mmcd" ) {
humanname = tr("SD Card");
removable = TRUE;
} else if ( disk.left(7) == "/dev/hd" )
- humanname = tr("Hard Disk") + " " + humanname.mid(7);
+ humanname = tr("Hard Disk") + " " + disk.mid(7);
else if ( disk.left(7) == "/dev/sd" )
- humanname = tr("SCSI Hard Disk") + " " + humanname.mid(7);
+ humanname = tr("SCSI Hard Disk") + " " + disk.mid(7);
else if ( disk.left(14) == "/dev/mtdblock6" ) //openzaurus ramfs
- humanname = tr("Ram FS") + " " + humanname.mid(14);
+ humanname = tr("Internal Memory");
else if ( disk == "/dev/mtdblock1" || humanname == "/dev/mtdblock/1" )
humanname = tr("Internal Storage");
else if ( disk.left(14) == "/dev/mtdblock/" )
- humanname = tr("Internal Storage") + " " + humanname.mid(14);
+ humanname = tr("Internal Storage") + " " + disk.mid(14);
else if ( disk.left(13) == "/dev/mtdblock" )
- humanname = tr("Internal Storage") + " " + humanname.mid(13);
+ humanname = tr("Internal Storage") + " " + disk.mid(13);
else if ( disk.left(5) == "tmpfs" ) //ipaqs /mnt/ramfs
- humanname = tr("Ram FS") + " " + humanname.mid(5);
+ humanname = tr("Internal Memory");
FileSystem *fs = new FileSystem( disk, *fsit, humanname, removable, opts );
mFileSystems.append( fs );
}
emit disksChanged();
} else {
// just update them
for (QListIterator<FileSystem> i(mFileSystems); i.current(); ++i)
i.current()->update();
}
#endif
}
//---------------------------------------------------------------------------
FileSystem::FileSystem( const QString &disk, const QString &path, const QString &name, bool rem, const QString &o )
: fsdisk( disk ), fspath( path ), humanname( name ), blkSize(512), totalBlks(0), availBlks(0), removable( rem ), opts( o )
{
update();
}
void FileSystem::update()
{
#if defined(_OS_LINUX_) || defined(Q_OS_LINUX)
struct statfs fs;
if ( !statfs( fspath.latin1(), &fs ) ) {
blkSize = fs.f_bsize;
totalBlks = fs.f_blocks;
availBlks = fs.f_bavail;
} else {
blkSize = 0;
totalBlks = 0;
availBlks = 0;
}
#endif
}