📄 applnk.cpp
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS. All rights reserved.**** This file is part of the Qtopia Environment.** ** This program is free software; you can redistribute it and/or modify it** under the terms of the GNU General Public License as published by the** Free Software Foundation; either version 2 of the License, or (at your** option) any later version.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** This program is distributed in the hope that it will be useful, but** WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU General Public License for more details.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** 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#ifndef QTOPIA_INTERNAL_PRELOADACCESS#define QTOPIA_INTERNAL_PRELOADACCESS#endif#include "applnk.h"#include <qtopia/qpeapplication.h>#include <qtopia/categories.h>#include <qtopia/categoryselect.h>#ifdef Q_WS_QWS#include <qtopia/qcopenvelope_qws.h>#include <qtopia/storage.h>#endif#include <qtopia/global.h>#include <qtopia/mimetype.h>#include <qtopia/config.h>#include <qtopia/resource.h>#include <qdict.h>#include <qdir.h>#include <qregexp.h>#include <qpixmapcache.h>#ifdef Q_WS_QWS#include <qgfx_qws.h>#endif#include <stdlib.h>extern bool qpe_fast_findPixmap;int AppLnk::lastId = 5000;static int smallSize = 16;static int bigSize = 32;static QString safeFileName(const QString& n){ QString safename; QChar c; QChar lowBoundChar('0'), safeSpaceChar('_'); // Replace all special ASCII characters and ensure that name does not start with a number for ( uint i = 0; i < n.length(); i++ ){ c = n.at(i); if ( c < lowBoundChar ) { safename += safeSpaceChar; }else{ if ( !(safename.isEmpty() && c.isNumber())) safename += c; } } if ( safename.isEmpty() ) safename = "_"; return safename;}/* Takes an absolute path which needs to exist. Creates all the intermediate paths up to that path as required. UNIX path seperators assumed, but will work for absolute Windows paths ie which start with "C:" ### Probably needs optimizing */bool mkdirRecursive( QString path ){ if ( path[int (path.length()) ] == '/' ) path = path.left( path.length() -1); QString wholePath = path; QFileInfo fi( path ); // find the path segment that does exist while ( !fi.isDir() && path.contains( '/' ) ) { path = path.left( path.findRev( '/' ) ); fi = QFileInfo( path ); } // make the path segments that do not exist QDir d; while ( path != wholePath ) { path = wholePath.left( wholePath.find( '/', path.length() + 1 )); d.mkdir( path ); fi = QFileInfo( path ); if ( !fi.isDir() ) return FALSE; } return TRUE;}static bool prepareDirectories(const QString& lf){ if (lf.isNull() || lf.isEmpty()) return TRUE; QFileInfo fi(lf); if (!fi.isDir()){ fi = QFileInfo(fi.dirPath(TRUE)); } QString dirPath = fi.absFilePath(); if ( !fi.exists() ) {#ifndef Q_OS_WIN32 // May need to create directories QString cmdLine(QString("mkdir -p ") + dirPath); if ( system(cmdLine.local8Bit().data())){#else if ( !mkdirRecursive( dirPath ) ) {#endif qDebug("AppLnk::prepareDirectories : System failed to create directory path %s", dirPath.latin1()); return FALSE; } } return TRUE;}class ReloadingCategories : public Categories { Q_OBJECTpublic: ReloadingCategories(QObject* parent=0) : Categories(parent) { saveId=0; load(); connect(qApp,SIGNAL(categoriesChanged()),this,SLOT(load())); } void saveSoon() { if ( !saveId ) saveId = startTimer(5); }protected: void timerEvent(QTimerEvent* e) { if ( e->timerId() == saveId ) { save(categoryFileName()); killTimer(saveId); saveId = 0; } }private slots: void load() { Categories::load( categoryFileName() ); }private: int saveId;};class AppLnkPrivate{public: // A CUT DOWN COPY OF THIS IS IN applnk1.cpp QStringList mCatList; // always correct QArray<int> mCat; // cached value; correct if not empty static ReloadingCategories* sCat; static void ensureSCat() { if ( !sCat ) sCat = new ReloadingCategories; } void updateCatListFromArray() { ensureSCat(); mCatList = sCat->globalGroup().labels( mCat ); mCatList += sCat->appGroupMap()["Document View"].labels( mCat ); // No tr } void setCatArrayDirty() { mCat.resize(0); } void ensureCatArray() { if ( mCat.count() > 0 || mCatList.count()==0 ) return; mCat.resize( mCatList.count() ); int i; QStringList::ConstIterator it; ensureSCat(); QString appname = "Document View"; // No tr for ( i = 0, it = mCatList.begin(); it != mCatList.end(); ++it, i++ ) { bool number; int id = (*it).toInt( &number ); if ( number && sCat->label(appname, id).isNull() ) number = FALSE; // Must supposed to be numeric if ( !number ) { id = sCat->id( appname, *it ); if ( id == 0 ) { id = sCat->addCategory( appname, *it ); sCat->saveSoon(); } } mCat[i] = id; } } static void setPixmaps( AppLnk *lnk, bool load_small = TRUE) { if ( !lnk ) return; QPixmap *pm = load_small ? &lnk->mPixmap : &lnk->mBigPixmap; QString suffix = load_small ? "_small" : "_big"; // No tr int size = load_small ? smallSize : bigSize; if ( lnk->mIconFile.isEmpty() ) { QString key = "_QPE_Global_" + lnk->type() + suffix; // Documents may have no icon. if (QPixmapCache::find(key, *pm)) return; // Use the icon associated with the mime-type. MimeType mt( lnk->type() ); *pm = (load_small) ? mt.pixmap() : mt.bigPixmap(); if ( !pm->isNull() ) { QPixmapCache::insert(key, *pm); return; } } else { QString key = "_QPE_" + lnk->mExec + '_' + lnk->mIconFile + suffix; // Applications have icons associated with them. if ( QPixmapCache::find(key, *pm) ) return; bool oldFast = qpe_fast_findPixmap; qpe_fast_findPixmap = TRUE; // Load up the application's icon. QImage unscaledIcon; if (size <= 16) unscaledIcon = Resource::loadImage( lnk->mExec + '/' + lnk->mIconFile + "_16" ); else if (size > 32) unscaledIcon = Resource::loadImage( lnk->mExec + '/' + lnk->mIconFile + "_48" ); if (unscaledIcon.isNull()) unscaledIcon = Resource::loadImage( lnk->mExec + '/' + lnk->mIconFile ); if( unscaledIcon.isNull() ) // last try, load it from the main pics dir with no suffix unscaledIcon = Resource::loadImage( lnk->mIconFile ); qpe_fast_findPixmap = oldFast; if ( !unscaledIcon.isNull() ) { pm->convertFromImage( unscaledIcon.smoothScale( size, size ) ); QPixmapCache::insert(key, *pm); return; } } // Fall through when we didn't find an icon QString name = "_QPE_Global_UnknownDocument" + suffix; if (QPixmapCache::find(name, *pm)) return; // Create unknown document icons as required pm->convertFromImage(Resource::loadImage("qpe/UnknownDocument").smoothScale(size,size)); QPixmapCache::insert(name, *pm); }};ReloadingCategories* AppLnkPrivate::sCat=0;/*! \class AppLnk applnk.h \brief The AppLnk class represents an application available on the system. Every Qtopia application \e app has a corresponding \e app.desktop file. When one of these files is read its data is stored as an AppLnk object. The AppLnk class introduces some Qtopia-specific concepts, and provides a variety of functions, as described in the following sections. \tableofcontents \target Types \section1 Types Every AppLnk object has a \e type. For applications, games and settings the type is \c Application; for documents the type is the document's MIME type. \target files-and-links \section1 Files and Links When you create an AppLnk (or more likely, a \link doclnk.html DocLnk\endlink), you don't deal directly with filenames in the filesystem. Instead you do this: \code DocLnk d; d.setType("text/plain"); d.setName("My Nicely Named Document / Whatever"); // Yes, "/" is legal. \endcode At this point, the file() and linkFile() are unknown. Normally this is uninteresting, and the names become automatically known, and more importantly, becomes reserved, when you ask what they are: \code QString fn = d.file(); \endcode This invents a filename, and creates the file on disk (an empty reservation file) to prevent the name being used by another application. In some circumstances, you don't want to create the file if it doesn't already exist (e.g. in the Document tab, some of the \link doclnk.html DocLnk\endlink objects represented by icons are DocLnk's created just for that view - they don't have corresponding \c .desktop files. To avoid littering empty reservation files around, we check in a few places to see whether the file really needs to exist). \section1 Functionality AppLnk objects are created by calling the constructor with the name of a \e .desktop file. The object can be checked for validity using isValid(). The following functions are used to set or retrieve information about the application: \table \header \i Get Function \i Set Function \i Short Description \row \i \l name() \i \l setName() \i application's name \row \i \l pixmap() \i \e none \i application's icon \row \i \l bigPixmap() \i \e none \i application's large icon \row \i \e none \i setIcon() \i sets the icon's filename \row \i \l type() \i \l setType() \i see \link #Types Types\endlink above \row \i \l rotation() \i \e none \i 0, 90, 180 or 270 degrees \row \i \l comment() \i \l setComment() \i text for the Details dialog \row \i \l exec() \i \l setExec() \i executable's filename \row \i \l file() \i \e none \i document's filename \row \i \l linkFile() \i \l setLinkFile() \i \e .desktop filename \row \i \l mimeTypes() \i \e none \i the mime types the application can view or edit \row \i \l categories() \i \l setCategories() \i \e{see the function descriptions} \row \i \l fileKnown() \i \e none \i see \link#files-and-links Files and Links\endlink above \row \i \l linkFileKnown() \i \e none \i see \link#files-and-links Files and Links\endlink above \row \i \l property() \i \l setProperty() \i any AppLnk property can be retrieved or set (if writeable) using these \endtable To save an AppLnk to disk use writeLink(). To execute the application that the AppLnk object refers to, use execute(). AppLnk's can be deleted from disk using removeLinkFile(). To remove both the link and the application's executable use removeFiles(). Icon sizes can be globally changed (but only for AppLnk objects created after the calls) with setSmallIconSize() and setBigIconSize(). \ingroup qtopiaemb*//*! Sets the size used for small icons to \a small pixels. Only affects AppLnk objects created after the call. \sa smallIconSize() setIcon()*/void AppLnk::setSmallIconSize(int small){ smallSize = small;}/*! Returns the size used for small icons. \sa setSmallIconSize() setIcon()*/int AppLnk::smallIconSize(){ return smallSize;}/*! Sets the size used for large icons to \a big pixels. Only affects AppLnk objects created after the call. \sa bigIconSize() setIcon()*/void AppLnk::setBigIconSize(int big){ bigSize = big;}/*! Returns the size used for large icons. \sa setBigIconSize() setIcon()*/int AppLnk::bigIconSize(){ return bigSize;}/*! \fn QString AppLnk::name() const Returns the Name property. This is the user-visible name for the document or application, not the filename. See \link #files-and-links Files and Links\endlink. \sa setName()*//*! \fn QString AppLnk::exec() const Returns the Exec property. This is the name of the executable program associated with the AppLnk. \sa setExec()*//*! \fn QString AppLnk::rotation() const Returns the Rotation property. The value is 0, 90, 180 or 270 degrees.*//*! \fn QString AppLnk::comment() const Returns the Comment property. \sa setComment()*//*! \fn QStringList AppLnk::mimeTypes() const Returns the MimeTypes property. This is the list of MIME types that the application can view or edit.*//*! \fn const QArray<int>& AppLnk::categories() const Returns a shallow copy of the Categories property. See the CategoryWidget for more details. \sa setCategories()*/const QArray<int>& AppLnk::categories() const{ d->ensureCatArray(); return d->mCat;}/*! \fn int AppLnk::id() const Returns the id of the AppLnk. If the AppLnk is not in an AppLnkSet, this value is 0, otherwise it is a value that is unique for the duration of the current process. \sa AppLnkSet::find()*//*! \fn bool AppLnk::isValid() const Returns TRUE if this AppLnk is valid; otherwise returns FALSE.*//*! Creates an invalid AppLnk. \sa isValid()*/AppLnk::AppLnk(){ mId = 0; d = new AppLnkPrivate();}/*! Loads \a file (e.g. \e app.desktop) as an AppLnk. \sa writeLink()*/AppLnk::AppLnk( const QString &file ){ QStringList sl; d = new AppLnkPrivate(); if ( !file.isNull() ) { Config config( file, Config::File ); if ( config.isValid() ) { config.setGroup( "Desktop Entry" ); mName = config.readEntry( "Name", file ); mExec = config.readEntry( "Exec" ); mType = config.readEntry( "Type", QString::null ); mIconFile = config.readEntry( "Icon", QString::null ); mRotation = config.readEntry( "Rotation", "" ); mComment = config.readEntry( "Comment", QString::null ); // MIME types are case-insensitive. mMimeTypes = config.readListEntry( "MimeType", ';' ); for (QStringList::Iterator it=mMimeTypes.begin(); it!=mMimeTypes.end(); ++it) *it = (*it).lower();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -