author | leseb <leseb> | 2002-08-30 18:10:11 (UTC) |
---|---|---|
committer | leseb <leseb> | 2002-08-30 18:10:11 (UTC) |
commit | b5ec106e5f612042987397a5a5b6683fdabaf793 (patch) (side-by-side diff) | |
tree | 58da0aac60a7a39cca162fe222107c9e3d676dac | |
parent | f6125710c0ca99fc62ffce69973a168b6604f29d (diff) | |
download | opie-b5ec106e5f612042987397a5a5b6683fdabaf793.zip opie-b5ec106e5f612042987397a5a5b6683fdabaf793.tar.gz opie-b5ec106e5f612042987397a5a5b6683fdabaf793.tar.bz2 |
Try to handle RAM storage for documents
-rw-r--r-- | library/applnk.cpp | 2 | ||||
-rw-r--r-- | library/global.cpp | 4 | ||||
-rw-r--r-- | library/lnkproperties.cpp | 7 | ||||
-rw-r--r-- | library/storage.cpp | 14 |
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,727 +1,727 @@ /********************************************************************** ** 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 © ) { 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; } diff --git a/library/global.cpp b/library/global.cpp index edb7b85..ab27b3f 100644 --- a/library/global.cpp +++ b/library/global.cpp @@ -300,427 +300,431 @@ void Global::addWords(const QString& dictname, const QStringList& wordlist) 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 } |