author | mickeyl <mickeyl> | 2004-07-01 13:33:35 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2004-07-01 13:33:35 (UTC) |
commit | 558c37f440baa57213d40639992bd29eaed1e12f (patch) (side-by-side diff) | |
tree | 809b695bcb66794ad9d04efe3db06aae49f8ae1b | |
parent | fadef9ae9838b3fb6f770a64b4cc2d179c6e9f07 (diff) | |
download | opie-558c37f440baa57213d40639992bd29eaed1e12f.zip opie-558c37f440baa57213d40639992bd29eaed1e12f.tar.gz opie-558c37f440baa57213d40639992bd29eaed1e12f.tar.bz2 |
add a few missing includes
-rw-r--r-- | library/alarmserver.cpp | 9 | ||||
-rw-r--r-- | library/applnk.cpp | 1 | ||||
-rw-r--r-- | library/tzselect.cpp | 1 |
3 files changed, 6 insertions, 5 deletions
diff --git a/library/alarmserver.cpp b/library/alarmserver.cpp index 48ab9c1..ba7b015 100644 --- a/library/alarmserver.cpp +++ b/library/alarmserver.cpp @@ -1,507 +1,506 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#include <qdir.h> - +#include "alarmserver.h" +#include <qpe/global.h> #include <qpe/qpeapplication.h> - #include <qpe/qcopenvelope_qws.h> -#include "alarmserver.h" #include <qpe/timeconversion.h> +#include <qdir.h> + #include <sys/types.h> #include <sys/stat.h> - #include <stdlib.h> #include <unistd.h> #undef USE_ATD // not used anymore -- we run opie-alarm on suspend/resume struct timerEventItem { time_t UTCtime; QCString channel, message; int data; bool operator==( const timerEventItem &right ) const { return ( UTCtime == right.UTCtime && channel == right.channel && message == right.message && data == right.data ); } }; class TimerReceiverObject : public QObject { public: TimerReceiverObject() { } ~TimerReceiverObject() { } void resetTimer(); void setTimerEventItem(); void deleteTimer(); protected: void timerEvent( QTimerEvent *te ); #ifdef USE_ATD private: QString atfilename; #endif }; TimerReceiverObject *timerEventReceiver = NULL; QList<timerEventItem> timerEventList; timerEventItem *nearestTimerEvent = NULL; // set the timer to go off on the next event in the list void setNearestTimerEvent() { nearestTimerEvent = NULL; QListIterator<timerEventItem> it( timerEventList ); if ( *it ) nearestTimerEvent = *it; for ( ; *it; ++it ) if ( (*it)->UTCtime < nearestTimerEvent->UTCtime ) nearestTimerEvent = *it; if (nearestTimerEvent) timerEventReceiver->resetTimer(); else timerEventReceiver->deleteTimer(); } //store current state to file //Simple implementation. Should run on a timer. static void saveState() { QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" ); if ( timerEventList.isEmpty() ) { unlink( savefilename ); return ; } QFile savefile(savefilename + ".new"); if ( savefile.open(IO_WriteOnly) ) { QDataStream ds( &savefile ); //save QListIterator<timerEventItem> it( timerEventList ); for ( ; *it; ++it ) { ds << it.current()->UTCtime; ds << it.current()->channel; ds << it.current()->message; ds << it.current()->data; } savefile.close(); unlink( savefilename ); QDir d; d.rename(savefilename + ".new", savefilename); } } /*! Sets up the alarm server. Restoring to previous state (session management). */ void AlarmServer::initialize() { //read autosave file and put events in timerEventList QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" ); QFile savefile(savefilename); if ( savefile.open(IO_ReadOnly) ) { QDataStream ds( &savefile ); while ( !ds.atEnd() ) { timerEventItem *newTimerEventItem = new timerEventItem; ds >> newTimerEventItem->UTCtime; ds >> newTimerEventItem->channel; ds >> newTimerEventItem->message; ds >> newTimerEventItem->data; timerEventList.append( newTimerEventItem ); } savefile.close(); if (!timerEventReceiver) timerEventReceiver = new TimerReceiverObject; setNearestTimerEvent(); } } #ifdef USE_ATD static const char* atdir = "/var/spool/at/"; static bool triggerAtd( bool writeHWClock = FALSE ) { QFile trigger(QString(atdir) + "trigger"); if ( trigger.open(IO_WriteOnly | IO_Raw) ) { if ( trigger.writeBlock("\n", 2) != 2 ) { QMessageBox::critical( 0, QObject::tr( "Out of Space" ), QObject::tr( "Unable to schedule alarm.\nFree some memory and try again." ) ); trigger.close(); QFile::remove ( trigger.name() ); return FALSE; } return TRUE; } return FALSE; } #else static bool writeResumeAt ( time_t wakeup ) { FILE *fp = ::fopen ( "/var/run/resumeat", "w" ); if ( fp ) { ::fprintf ( fp, "%d\n", (int) wakeup ); ::fclose ( fp ); } else qWarning ( "Failed to write wakeup time to /var/run/resumeat" ); return ( fp ); } #endif void TimerReceiverObject::deleteTimer() { #ifdef USE_ATD if ( !atfilename.isEmpty() ) { unlink( atfilename ); atfilename = QString::null; triggerAtd( FALSE ); } #else writeResumeAt ( 0 ); #endif } void TimerReceiverObject::resetTimer() { const int maxsecs = 2147000; QDateTime nearest = TimeConversion::fromUTC(nearestTimerEvent->UTCtime); QDateTime now = QDateTime::currentDateTime(); if ( nearest < now ) nearest = now; int secs = TimeConversion::secsTo( now, nearest ); if ( secs > maxsecs ) { // too far for millisecond timing secs = maxsecs; } // System timer (needed so that we wake from deep sleep), // from the Epoch in seconds. // int at_secs = TimeConversion::toUTC(nearest); // qDebug("reset timer to %d seconds from Epoch",at_secs); #ifdef USE_ATD QString fn = atdir + QString::number(at_secs) + "." + QString::number(getpid()); if ( fn != atfilename ) { QFile atfile(fn + ".new"); if ( atfile.open(IO_WriteOnly | IO_Raw) ) { int total_written; // just wake up and delete the at file QString cmd = "#!/bin/sh\nrm " + fn; total_written = atfile.writeBlock(cmd.latin1(), cmd.length()); if ( total_written != int(cmd.length()) ) { QMessageBox::critical( 0, tr("Out of Space"), tr("Unable to schedule alarm.\n" "Please free up space and try again") ); atfile.close(); QFile::remove ( atfile.name() ); return ; } atfile.close(); unlink( atfilename ); QDir d; d.rename(fn + ".new", fn); chmod(fn.latin1(), 0755); atfilename = fn; triggerAtd( FALSE ); } else { qWarning("Cannot open atd file %s", fn.latin1()); } } #else writeResumeAt ( at_secs ); #endif // Qt timers (does the actual alarm) // from now in milliseconds // qDebug("AlarmServer waiting %d seconds", secs); startTimer( 1000 * secs + 500 ); } void TimerReceiverObject::timerEvent( QTimerEvent * ) { bool needSave = FALSE; killTimers(); if (nearestTimerEvent) { if ( nearestTimerEvent->UTCtime <= TimeConversion::toUTC(QDateTime::currentDateTime()) ) { #ifndef QT_NO_COP QCopEnvelope e( nearestTimerEvent->channel, nearestTimerEvent->message ); e << TimeConversion::fromUTC( nearestTimerEvent->UTCtime ) << nearestTimerEvent->data; #endif timerEventList.remove( nearestTimerEvent ); needSave = TRUE; } setNearestTimerEvent(); } else { resetTimer(); } if ( needSave ) saveState(); } /*! \class AlarmServer alarmserver.h \brief The AlarmServer class allows alarms to be scheduled and unscheduled. Applications can schedule alarms with addAlarm() and can unschedule alarms with deleteAlarm(). When the time for an alarm to go off is reached the specified \link qcop.html QCop\endlink message is sent on the specified channel (optionally with additional data). Scheduling an alarm using this class is important (rather just using a QTimer) since the machine may be asleep and needs to get woken up using the Linux kernel which implements this at the kernel level to minimize battery usage while asleep. A small example on how to use AlarmServer. First we need to connect a slot the AppMessage QCOP call. appMessage will be emitted if QPE/Application/appname gets called. \code TestApp::TestApp(QWidget *parent, const char* name, WFlags fl ) : QMainWindow(parent,name,fl){ connect(qApp,SIGNAL(appMessage(const QCString&,const QByteArray&)), this,SLOT(slotAppMessage(const QCString&,const QByteArray&))); } \endcode To add / delete an alarm, you can use the static method AlarmServer::addAlarm and AlarmServer::deleteAlarm. Note that an old (expired) alarm will automatically be deleted from the alarmserver list, but a change in timing will have the effect, that both alarms will be emitted. So if you change an Alarm be sure to delete the old one! @see addAlarm \code QDateTime oldDt = oldAlarmDateTime(); QPEApplication::execDialog(ourDlg); QDateTime newDt = ourDlg->dateTime(); if(newDt == oldDt ) return; @slash* code is missing for unsetting an alarm *@slash AlarmServer::deleteAlarm(oldDt,"QPE/Application/appname","checkAlarm(QDateTime,int)",0); AlarmServer::addAlarm( newDt,"QPE/AlarmServer/appname","checkAlarm(QDateTime,int)",0); \endcode Now once the Alarm is emitted you need to check the appMessage and then do what you want. \code void TestApp::slotAppMessage(const QCString& str, const QByteArray& ar ){ QDataStream stream(ar,IO_ReadOnly); if(str == "checkAlarm(QDateTime,int)" ){ QDateTime dt; int a; stream >> dt >> a; // fire up alarm } } \endcode \ingroup qtopiaemb \sa QCopEnvelope @see QPEApplication::appMessage(const QCString&,const QByteArray&) @see OPimMainWindow @see ODevice::alarmSound() @see Sound::soundAlarm() */ /*! Schedules an alarm to go off at (or soon after) time \a when. When the alarm goes off, the \link qcop.html QCop\endlink \a message will be sent to \a channel, with \a data as a parameter. If this function is called with exactly the same data as a previous call the subsequent call is ignored, so there is only ever one alarm with a given set of parameters. Once an alarm is emitted. The \a channel with a \a message will be emitted and data will be send. The QDateTime and int are the two parameters included in the QCOP message. You can specify channel, message and the integer parameter. QDateTime will be the datetime of the QCop call. @param when The QDateTime of the alarm @param channel The channel which gets called once the alarm is emitted @param message The message to be send to the channel @param data Additional data as integer @see QCopChannel \sa deleteAlarm() */ void AlarmServer::addAlarm ( QDateTime when, const QCString& channel, const QCString& message, int data) { if ( qApp->type() == QApplication::GuiServer ) { bool needSave = FALSE; // Here we are the server so either it has been directly called from // within the server or it has been sent to us from a client via QCop if (!timerEventReceiver) timerEventReceiver = new TimerReceiverObject; timerEventItem *newTimerEventItem = new timerEventItem; newTimerEventItem->UTCtime = TimeConversion::toUTC( when ); newTimerEventItem->channel = channel; newTimerEventItem->message = message; newTimerEventItem->data = data; // explore the case of already having the event in here... QListIterator<timerEventItem> it( timerEventList ); for ( ; *it; ++it ) if ( *(*it) == *newTimerEventItem ) return ; // if we made it here, it is okay to add the item... timerEventList.append( newTimerEventItem ); needSave = TRUE; // quicker than using setNearestTimerEvent() if ( nearestTimerEvent ) { if (newTimerEventItem->UTCtime < nearestTimerEvent->UTCtime) { nearestTimerEvent = newTimerEventItem; timerEventReceiver->killTimers(); timerEventReceiver->resetTimer(); } } else { nearestTimerEvent = newTimerEventItem; timerEventReceiver->resetTimer(); } if ( needSave ) saveState(); } else { #ifndef QT_NO_COP QCopEnvelope e( "QPE/System", "addAlarm(QDateTime,QCString,QCString,int)" ); e << when << channel << message << data; #endif } } /*! Deletes previously scheduled alarms which match \a when, \a channel, \a message, and \a data. Passing null values for \a when, \a channel, or for the \link qcop.html QCop\endlink \a message, acts as a wildcard meaning "any". Similarly, passing -1 for \a data indicates "any". If there is no matching alarm, nothing happens. \sa addAlarm() */ void AlarmServer::deleteAlarm (QDateTime when, const QCString& channel, const QCString& message, int data) { if ( qApp->type() == QApplication::GuiServer) { bool needSave = FALSE; if ( timerEventReceiver != NULL ) { timerEventReceiver->killTimers(); // iterate over the list of events QListIterator<timerEventItem> it( timerEventList ); time_t deleteTime = TimeConversion::toUTC( when ); for ( ; *it; ++it ) { // if its a match, delete it if ( ( (*it)->UTCtime == deleteTime || when.isNull() ) && ( channel.isNull() || (*it)->channel == channel ) && ( message.isNull() || (*it)->message == message ) && ( data == -1 || (*it)->data == data ) ) { // if it's first, then we need to update the timer if ( (*it) == nearestTimerEvent ) { timerEventList.remove(*it); setNearestTimerEvent(); } else { timerEventList.remove(*it); } needSave = TRUE; } } if ( nearestTimerEvent ) timerEventReceiver->resetTimer(); } if ( needSave ) saveState(); } else { #ifndef QT_NO_COP QCopEnvelope e( "QPE/System", "deleteAlarm(QDateTime,QCString,QCString,int)" ); e << when << channel << message << data; #endif } } /*! The implementation depends on the mode of AlarmServer. If the AlarmServer uses atd the current system time will be written to the hardware clock. If the AlarmServer relies on opie-alarm the time will be written once the device gets suspended. opie-alarm is used by the Zaurus, iPAQs and SIMpad */ void Global::writeHWClock() { #ifdef USE_ATD if ( !triggerAtd( TRUE ) ) { // atd not running? set it ourselves system("/sbin/hwclock --systohc"); // ##### UTC? } #else // hwclock is written on suspend #endif } diff --git a/library/applnk.cpp b/library/applnk.cpp index e9d519e..1c1a227 100644 --- a/library/applnk.cpp +++ b/library/applnk.cpp @@ -1,1496 +1,1497 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #define QTOPIA_INTERNAL_MIMEEXT #define QTOPIA_INTERNAL_PRELOADACCESS #define QTOPIA_INTERNAL_APPLNKASSIGN #include "applnk.h" #include <qpe/qpeapplication.h> #include <qpe/categories.h> #include <qpe/categoryselect.h> +#include <qpe/global.h> #include <qpe/qcopenvelope_qws.h> #include <qpe/mimetype.h> #include <qpe/config.h> #include <qpe/storage.h> #include <qpe/resource.h> #include <qdir.h> #include <stdlib.h> int AppLnk::lastId = 5000; static int smallSize = 14; static int bigSize = 32; static QString safeFileName(const QString& n) { QString safename=n; safename.replace(QRegExp("[^0-9A-Za-z.]"),"_"); safename.replace(QRegExp("^[^A-Za-z]*"),""); if ( safename.isEmpty() ) safename = "_"; return safename; } static bool prepareDirectories(const QString& lf) { if ( !QFile::exists(lf) ) { // May need to create directories QFileInfo fi(lf); if ( system(("mkdir -p "+fi.dirPath(TRUE))) ) return FALSE; } return TRUE; } class AppLnkPrivate { public: /* the size of the Pixmap */ enum Size {Normal = 0, Big }; AppLnkPrivate() { /* we want one normal and one big item */ QPixmap pix; mPixmaps.insert(0, pix ); mPixmaps.insert(1, pix); } QStringList mCatList; // always correct QArray<int> mCat; // cached value; correct if not empty QMap<int, QPixmap> mPixmaps; void updateCatListFromArray() { Categories cat( 0 ); cat.load( categoryFileName() ); // we need to update the names for the mCat... to mCatList mCatList.clear(); for (uint i = 0; i < mCat.count(); i++ ) mCatList << cat.label("Document View", mCat[i] ); } void setCatArrayDirty() { mCat.resize(0); } void ensureCatArray() { if ( mCat.count() > 0 || mCatList.count()==0 ) return; Categories cat( 0 ); cat.load( categoryFileName() ); mCat.resize( mCatList.count() ); int i; QStringList::ConstIterator it; for ( i = 0, it = mCatList.begin(); it != mCatList.end(); ++it, i++ ) { bool number; int id = (*it).toInt( &number ); if ( !number ) { id = cat.id( "Document View", *it ); if ( id == 0 ) id = cat.addCategory( "Document View", *it ); } mCat[i] = id; } } }; /*! \class AppLnk applnk.h \brief The AppLnk class represents an application available on the system. Every Qtopia application \e app has a corresponding \e app.desktop file. When one of these files is read its data is stored as an AppLnk object. The AppLnk class introduces some Qtopia-specific concepts, and provides a variety of functions, as described in the following sections. \tableofcontents \target Types \section1 Types Every AppLnk object has a \e type. For applications, games and settings the type is \c Application; for documents the type is the document's MIME type. \target files-and-links \section1 Files and Links When you create an AppLnk (or more likely, a \link doclnk.html DocLnk\endlink), you don't deal directly with filenames in the filesystem. Instead you do this: \code DocLnk d; d.setType("text/plain"); d.setName("My Nicely Named Document / Whatever"); // Yes, "/" is legal. \endcode At this point, the file() and linkFile() are unknown. Normally this is uninteresting, and the names become automatically known, and more importantly, becomes reserved, when you ask what they are: \code QString fn = d.file(); \endcode This invents a filename, and creates the file on disk (an empty reservation file) to prevent the name being used by another application. In some circumstances, you don't want to create the file if it doesn't already exist (e.g. in the Document tab, some of the \link doclnk.html DocLnk\endlink objects represented by icons are DocLnk's created just for that view - they don't have corresponding \c .desktop files. To avoid littering empty reservation files around, we check in a few places to see whether the file really needs to exist). \section1 Functionality AppLnk objects are created by calling the constructor with the name of a \e .desktop file. The object can be checked for validity using isValid(). The following functions are used to set or retrieve information about the application: \table \header \i Get Function \i Set Function \i Short Description \row \i \l name() \i \l setName() \i application's name \row \i \l pixmap() \i \e none \i application's icon \row \i \l bigPixmap() \i \e none \i application's large icon \row \i \e none \i setIcon() \i sets the icon's filename \row \i \l type() \i \l setType() \i see \link #Types Types\endlink above \row \i \l rotation() \i \e none \i 0, 90, 180 or 270 degrees \row \i \l comment() \i \l setComment() \i text for the Details dialog \row \i \l exec() \i \l setExec() \i executable's filename \row \i \l file() \i \e none \i document's filename \row \i \l linkFile() \i \l setLinkFile() \i \e .desktop filename \row \i \l mimeTypes() \i \e none \i the mime types the application can view or edit \row \i \l categories() \i \l setCategories() \i \e{see the function descriptions} \row \i \l fileKnown() \i \e none \i see \link #files-and-links Files and Links\endlink above \row \i \l linkFileKnown() \i \e none \i see \link #files-and-links Files and Links\endlink above \row \i \l property() \i \l setProperty() \i any AppLnk property can be retrieved or set (if writeable) using these \endtable To save an AppLnk to disk use writeLink(). To execute the application that the AppLnk object refers to, use execute(). AppLnk's can be deleted from disk using removeLinkFile(). To remove both the link and the application's executable use removeFiles(). Icon sizes can be globally changed (but only for AppLnk objects created after the calls) with setSmallIconSize() and setBigIconSize(). \ingroup qtopiaemb */ /*! Sets the size used for small icons to \a small pixels. Only affects AppLnk objects created after the call. \sa smallIconSize() setIcon() */ void AppLnk::setSmallIconSize(int small) { smallSize = small; } /*! Returns the size used for small icons. \sa setSmallIconSize() setIcon() */ int AppLnk::smallIconSize() { return smallSize; } /*! Sets the size used for large icons to \a big pixels. Only affects AppLnk objects created after the call. \sa bigIconSize() setIcon() */ void AppLnk::setBigIconSize(int big) { bigSize = big; } /*! Returns the size used for large icons. \sa setBigIconSize() setIcon() */ int AppLnk::bigIconSize() { return bigSize; } /*! \fn QString AppLnk::name() const Returns the Name property. This is the user-visible name for the document or application, not the filename. See \link #files-and-links Files and Links\endlink. \sa setName() */ /*! \fn QString AppLnk::exec() const Returns the Exec property. This is the name of the executable program associated with the AppLnk. \sa setExec() */ /*! \fn QString AppLnk::rotation() const Returns the Rotation property. The value is 0, 90, 180 or 270 degrees. */ /*! \fn QString AppLnk::comment() const Returns the Comment property. \sa setComment() */ /*! \fn QStringList AppLnk::mimeTypes() const Returns the MimeTypes property. This is the list of MIME types that the application can view or edit. */ /*! \fn const QArray<int>& AppLnk::categories() const Returns the Categories property. See the CategoryWidget for more details. \sa setCategories() */ const QArray<int>& AppLnk::categories() const { d->ensureCatArray(); return d->mCat; } /*! \fn int AppLnk::id() const Returns the id of the AppLnk. If the AppLnk is not in an AppLnkSet, this value is 0, otherwise it is a value that is unique for the duration of the current process. \sa AppLnkSet::find() */ /*! \fn bool AppLnk::isValid() const Returns TRUE if this AppLnk is valid; otherwise returns FALSE. */ /*! \fn bool AppLnk::fileKnown() const If the with the AppLnk associated file is not equal to QString::null */ /*! \fn bool AppLnk::linkFileKnown()const The filename of the AppLnk */ /*! \fn void AppLnk::setRotation( const QString& ) The default rotation of the associated application. This function is included inline for binary compatible issues */ /*! Creates an invalid AppLnk. \sa isValid() */ AppLnk::AppLnk() { mId = 0; d = new AppLnkPrivate(); } /*! Loads \a file (e.g. \e app.desktop) as an AppLnk. \sa writeLink() */ AppLnk::AppLnk( const QString &file ) { QStringList sl; d = new AppLnkPrivate(); if ( !file.isNull() ) { Config config( file, Config::File ); if ( config.isValid() ) { config.setGroup( "Desktop Entry" ); mName = config.readEntry( "Name", file ); mExec = config.readEntry( "Exec" ); mType = config.readEntry( "Type", QString::null ); mIconFile = config.readEntry( "Icon", QString::null ); mRotation = config.readEntry( "Rotation", "" ); mComment = config.readEntry( "Comment", QString::null ); // MIME types are case-insensitive. mMimeTypes = config.readListEntry( "MimeType", ';' ); for (QStringList::Iterator it=mMimeTypes.begin(); it!=mMimeTypes.end(); ++it) *it = (*it).lower(); mMimeTypeIcons = config.readListEntry( "MimeTypeIcons", ';' ); mLinkFile = file; mFile = config.readEntry("File", QString::null); if ( !mExec. isEmpty ( )) { mFile = QString::null; } else if ( mFile[0] != '/' ) { int slash = file.findRev('/'); if ( slash >= 0 ) { mFile = file.left(slash) + '/' + mFile; } } d->mCatList = config.readListEntry("Categories", ';'); if ( d->mCatList[0].toInt() < -1 ) { // numeric cats in file! convert to text Categories cat( 0 ); cat.load( categoryFileName() ); d->mCat.resize( d->mCatList.count() ); int i; QStringList::ConstIterator it; for ( i = 0, it = d->mCatList.begin(); it != d->mCatList.end(); ++it, i++ ) { bool number; int id = (*it).toInt( &number ); if ( !number ) { // convert from text id = cat.id( "Document View", *it ); if ( id == 0 ) id = cat.addCategory( "Document View", *it ); } d->mCat[i] = id; } d->updateCatListFromArray(); } } } mId = 0; } AppLnk& AppLnk::operator=(const AppLnk ©) { if ( this == © ) return *this; if ( mId ) qWarning("Deleting AppLnk that is in an AppLnkSet"); if ( d ) delete d; mName = copy.mName; /* remove for Qtopia 3.0 -zecke */ mPixmap = copy.mPixmap; mBigPixmap = copy.mBigPixmap; mExec = copy.mExec; mType = copy.mType; mRotation = copy.mRotation; mComment = copy.mComment; mFile = copy.mFile; mLinkFile = copy.mLinkFile; mIconFile = copy.mIconFile; mMimeTypes = copy.mMimeTypes; mMimeTypeIcons = copy.mMimeTypeIcons; mId = 0; d = new AppLnkPrivate(); d->mCat = copy.d->mCat; d->mCatList = copy.d->mCatList; d->mPixmaps = copy.d->mPixmaps; return *this; } /*! protected internally to share code should I document that at all? I don't know the TT style for that */ const QPixmap& AppLnk::pixmap( int pos, int size ) const { if ( d->mPixmaps[pos].isNull() ) { AppLnk* that = (AppLnk*)this; if ( mIconFile.isEmpty() ) { MimeType mt(type()); that->d->mPixmaps[pos] = pos ? mt.bigPixmap() : mt.pixmap(); if ( that->d->mPixmaps[pos].isNull() ) that->d->mPixmaps[pos].convertFromImage( Resource::loadImage("UnknownDocument") .smoothScale( size, size ) ); return that->d->mPixmaps[pos]; } QImage unscaledIcon = Resource::loadImage( that->mIconFile ); if ( unscaledIcon.isNull() ) { // qDebug( "Cannot find icon: %s", that->mIconFile.latin1() ); that->d->mPixmaps[pos].convertFromImage( Resource::loadImage("UnknownDocument") .smoothScale( size, size ) ); } else { that->d->mPixmaps[0].convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) ); that->d->mPixmaps[1].convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) ); } return that->d->mPixmaps[pos]; } return d->mPixmaps[pos]; } /*! Returns a small pixmap associated with the application. \sa bigPixmap() setIcon() */ const QPixmap& AppLnk::pixmap() const { if ( d->mPixmaps[0].isNull() ) { return pixmap(AppLnkPrivate::Normal, smallSize ); } return d->mPixmaps[0]; } /*! Returns a large pixmap associated with the application. \sa pixmap() setIcon() */ const QPixmap& AppLnk::bigPixmap() const { if ( d->mPixmaps[1].isNull() ) { return pixmap( AppLnkPrivate::Big, bigSize ); } return d->mPixmaps[1]; } /*! Returns the type of the AppLnk. For applications, games and settings the type is \c Application; for documents the type is the document's MIME type. */ QString AppLnk::type() const { if ( mType.isNull() ) { AppLnk* that = (AppLnk*)this; QString f = file(); if ( !f.isNull() ) { MimeType mt(f); that->mType = mt.id(); return that->mType; } } return mType; } /*! Returns the file associated with the AppLnk. \sa exec() name() */ QString AppLnk::file() const { if ( mExec.isEmpty ( ) && mFile.isNull() ) { AppLnk* that = (AppLnk*)this; QString ext = MimeType(mType).extension(); if ( !ext.isEmpty() ) ext = "." + ext; if ( !mLinkFile.isEmpty() ) { that->mFile = mLinkFile.right(8)==".desktop" // 8 = strlen(".desktop") ? mLinkFile.left(mLinkFile.length()-8) : mLinkFile; qDebug("mFile now == %s", mFile.latin1()); } else if ( mType.contains('/') ) { that->mFile = QString(getenv("HOME"))+"/Documents/"+mType+"/"+safeFileName(that->mName); /* * A file with the same name or a .desktop file already exists */ if ( QFile::exists(that->mFile+ext) || QFile::exists(that->mFile+".desktop") ) { int n=1; QString nn; while (QFile::exists((nn=(that->mFile+"_"+QString::number(n)))+ext) || QFile::exists(nn+".desktop")) n++; that->mFile = nn; } that->mLinkFile = that->mFile+".desktop"; that->mFile += ext; } prepareDirectories(that->mFile); if ( !that->mFile.isEmpty() ) { QFile f(that->mFile); if ( !f.open(IO_WriteOnly) ) that->mFile = QString::null; return that->mFile; } } return mFile; } /*! Returns the desktop file corresponding to this AppLnk. \sa file() exec() name() */ QString AppLnk::linkFile() const { if ( mLinkFile.isNull() ) { AppLnk* that = (AppLnk*)this; if ( type().contains('/') ) { StorageInfo storage; const FileSystem *fs = storage.fileSystemOf( that->mFile ); /* tmpfs + and ramfs are available too but not removable * either we fix storage or add this */ 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); /* the desktop file exists make sure we don't point to the same file */ if ( QFile::exists(that->mLinkFile+".desktop") ) { AppLnk lnk( that->mLinkFile + ".desktop" ); /* the linked is different */ if(that->file() != lnk.file() ) { int n = 1; QString nn; while (QFile::exists((nn=that->mLinkFile+"_"+QString::number(n))+".desktop")) { n++; /* just to be sure */ AppLnk lnk(nn ); if (lnk.file() == that->file() ) break; } that->mLinkFile = nn; } } that->mLinkFile += ".desktop"; 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; d->mCatList = copy.d->mCatList; d->mPixmaps = copy.d->mPixmaps; } /*! Destroys the AppLnk. Note that if the AppLnk is currently 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; } /*! \overload Executes the application associated with this AppLnk. \sa exec() */ void AppLnk::execute() const { execute( QStringList::split( ' ', property( "Arguments" ) ) ); } /*! Executes the application associated with this AppLnk, with \a args as arguments. \sa exec() */ 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, so you should not call it directly. \sa execute() */ void AppLnk::invoke(const QStringList& args) const { if ( property( "Arguments" ).isEmpty() ) Global::execute( exec(), args[0] ); else Global::execute( exec(), args.join( " " ) ); } /*! Sets the Exec property to \a exec. \sa exec() name() */ void AppLnk::setExec( const QString& exec ) { mExec = exec; } #if 0 // this was inlined for better BC /*! Sets the Rotation property to \a rot. \sa rotation() */ void AppLnk::setRotation ( const QString &rot ) { mRotation = rot; } #endif /*! 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() name() */ 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. This text is displayed in the 'Details Dialog', for example if the user uses the 'press-and-hold' gesture. \sa comment() */ void AppLnk::setComment( const QString& comment ) { mComment = comment; } /*! Sets the Type property to \a type. For applications, games and settings the type should be \c Application; for documents the type should be the document's MIME type. \sa type() */ void AppLnk::setType( const QString& type ) { mType = type; } /*! \fn QString AppLnk::icon() const Returns the Icon property. \sa setIcon() */ /*! Sets the Icon property to \a iconname. This is the filename from which the pixmap() and bigPixmap() are obtained. \sa icon() setSmallIconSize() setBigIconSize() */ void AppLnk::setIcon( const QString& iconname ) { mIconFile = iconname; QImage unscaledIcon = Resource::loadImage( mIconFile ); d->mPixmaps[0].convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) ); d->mPixmaps[1].convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) ); } /*! Sets the Categories property to \a c. See the CategoryWidget for more details. \sa categories() */ void AppLnk::setCategories( const QArray<int>& c ) { d->mCat = c; d->updateCatListFromArray(); } /*! \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; otherwise returns FALSE. You should not need to use this function. */ bool AppLnk::ensureLinkExists() const { QString lf = linkFile(); return prepareDirectories(lf); } /*! Commits the AppLnk to disk. Returns TRUE if the operation succeeded; otherwise returns FALSE. In addition, the "linkChanged(QString)" message is sent to the "QPE/System" \link qcop.html QCop\endlink channel. */ bool AppLnk::writeLink() const { // Only re-writes settable parts QString lf = linkFile(); if ( !ensureLinkExists() ) return FALSE; storeLink(); return TRUE; } /*! \internal */ void AppLnk::storeLink() const { Config config( mLinkFile, Config::File ); config.setGroup("Desktop Entry"); config.writeEntry("Name",mName); if ( !mIconFile.isNull() ) config.writeEntry("Icon",mIconFile); config.writeEntry("Type",type()); if(!rotation().isEmpty()) config.writeEntry("Rotation",rotation()); else config.removeEntry("Rotation"); if ( !mComment.isNull() ) config.writeEntry("Comment",mComment); QString f = file(); int i = 0; while ( i < (int)f.length() && i < (int)mLinkFile.length() && f[i] == mLinkFile[i] ) i++; while ( i && f[i] != '/' ) i--; // simple case where in the same directory if ( mLinkFile.find( '/', i + 1 ) < 0 ) f = f.mid(i+1); // ### could do relative ie ../../otherDocs/file.doc config.writeEntry("File",f); config.writeEntry( "Categories", d->mCatList, ';' ); #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "linkChanged(QString)"); e << mLinkFile; #endif } /*! Sets the property named \a key to \a value. \sa property() */ void AppLnk::setProperty(const QString& key, const QString& value) { if ( ensureLinkExists() ) { Config cfg(linkFile(), Config::File); cfg.writeEntry(key,value); } } /*! Returns the property named \a key. \sa setProperty() */ QString AppLnk::property(const QString& key) const { QString lf = linkFile(); if ( !QFile::exists(lf) ) return QString::null; Config cfg(lf, Config::File); return cfg.readEntry(key); } bool AppLnk::isPreloaded() const { // Preload information is stored in the Launcher config in v1.5. Config cfg("Launcher"); cfg.setGroup("Preload"); QStringList apps = cfg.readListEntry("Apps",','); if (apps.contains(exec())) return true; return false; } void AppLnk::setPreloaded(bool yesNo) { // Preload information is stored in the Launcher config in v1.5. Config cfg("Launcher"); cfg.setGroup("Preload"); QStringList apps = cfg.readListEntry("Apps", ','); if (apps.contains(exec()) && !yesNo) apps.remove(exec()); else if (yesNo && !apps.contains(exec())) apps.append(exec()); cfg.writeEntry("Apps", apps, ','); } /*! Deletes both the linkFile() and the file() associated with this AppLnk. \sa removeLinkFile() */ void AppLnk::removeFiles() { bool valid = isValid(); if ( !valid || !linkFileKnown() || QFile::remove(linkFile()) ) { if ( QFile::remove(file()) ) { #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "linkChanged(QString)"); if ( linkFileKnown() ) e << linkFile(); else e << file(); #endif } else if ( valid ) { // restore link writeLink(); } } } /*! Deletes the linkFile(), leaving any file() untouched. \sa removeFiles() */ void AppLnk::removeLinkFile() { if ( isValid() && linkFileKnown() && QFile::remove(linkFile()) ) { #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "linkChanged(QString)"); e << linkFile(); #endif } } class 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 \link applnk.html#Types types\endlink in the set. For applications, games and settings the type is \c Application; for documents the type is the document's MIME type. \sa AppLnk::type(), typeName(), typePixmap(), typeBigPixmap() */ /*! \fn const QList<AppLnk>& AppLnkSet::children() const Returns the members of the set. */ /*! Constructs an empty AppLnkSet. */ AppLnkSet::AppLnkSet() : d(new AppLnkSetPrivate) { } /*! Constructs an AppLnkSet that contains AppLnk objects representing all the files in the given \a directory (and any subdirectories recursively). \omit The directories may contain ".directory" files which override any AppLnk::type() values for AppLnk objects found in the directory. This allows simple localization of application types. \endomit */ AppLnkSet::AppLnkSet( const QString &directory ) : d(new AppLnkSetPrivate) { QDir dir( directory ); mFile = directory; findChildren(directory,QString::null,QString::null); } /*! Detaches all AppLnk objects from the set. The set become empty and the caller becomes responsible for deleting the AppLnk objects. */ void AppLnkSet::detachChildren() { QListIterator<AppLnk> it( mApps ); for ( ; it.current(); ) { AppLnk* a = *it; ++it; a->mId = 0; } mApps.clear(); } /*! Destroys the set, deleting all the AppLnk objects it contains. \sa detachChildren() */ AppLnkSet::~AppLnkSet() { QListIterator<AppLnk> it( mApps ); for ( ; it.current(); ) { AppLnk* a = *it; ++it; a->mId = 0; delete a; } delete d; } void AppLnkSet::findChildren(const QString &dr, const QString& typ, const QString& typName, int depth) { depth++; if ( depth > 10 ) return; QDir dir( dr ); QString typNameLocal = typName; if ( dir.exists( ".directory" ) ) { Config config( dr + "/.directory", Config::File ); config.setGroup( "Desktop Entry" ); typNameLocal = config.readEntry( "Name", typNameLocal ); if ( !typ.isEmpty() ) { QString iconFile = config.readEntry( "Icon", "AppsIcon" ); QImage unscaledIcon = Resource::loadImage( iconFile ); QPixmap pm, bpm; pm.convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) ); bpm.convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) ); d->typPix.insert(typ, new QPixmap(pm)); d->typPixBig.insert(typ, new QPixmap(bpm)); d->typName.insert(typ, new QString(typNameLocal)); } } const QFileInfoList *list = dir.entryInfoList(); if ( list ) { QFileInfo* fi; bool cadded=FALSE; for ( QFileInfoListIterator it(*list); (fi=*it); ++it ) { QString bn = fi->fileName(); // qDebug("findChildren "+bn); if ( bn[0] != '.' && bn != "CVS" ) { if ( fi->isDir() ) { QString c = typ.isNull() ? bn : typ+"/"+bn; QString d = typNameLocal.isNull() ? bn : typNameLocal+"/"+bn; findChildren(fi->filePath(), c, d, depth ); } else { if ( fi->extension(FALSE) == "desktop" ) { AppLnk* app = new AppLnk( fi->filePath() ); #ifdef QT_NO_QWS_MULTIPROCESS if ( !Global::isBuiltinCommand( app->exec() ) ) delete app; else #endif { if ( !typ.isEmpty() ) { if ( !cadded ) { typs.append(typ); cadded = TRUE; } app->setType(typ); } add(app); } } } } } } } /*! Adds AppLnk \a f to the set. The set takes responsibility for deleting \a f. \sa remove() */ void AppLnkSet::add( AppLnk *f ) { if ( f->mId == 0 ) { AppLnk::lastId++; f->mId = AppLnk::lastId; mApps.append( f ); } else { qWarning("Attempt to add an AppLnk twice"); } } /*! Removes AppLnk \a f to the set. The caller becomes responsible for deleting \a f. Returns TRUE if \a f was in the set; otherwise returns FALSE. \sa add() */ bool AppLnkSet::remove( AppLnk *f ) { if ( mApps.remove( f ) ) { f->mId = 0; return TRUE; } return FALSE; } /*! Returns the localized name for type \a t. For applications, games and settings the type is \c Application; for documents the type is the document's MIME type. */ QString AppLnkSet::typeName( const QString& t ) const { QString *st = d->typName.find(t); return st ? *st : QString::null; } /*! Returns the small pixmap associated with type \a t. For applications, games and settings the type is \c Application; for documents the type is the document's MIME type. */ QPixmap AppLnkSet::typePixmap( const QString& t ) const { QPixmap *pm = d->typPix.find(t); return pm ? *pm : QPixmap(); } /*! Returns the large pixmap associated with type \a t. For applications, games and settings the type is \c Application; for documents the type is the document's MIME type. */ QPixmap AppLnkSet::typeBigPixmap( const QString& t ) const { QPixmap *pm = d->typPixBig.find(t); return pm ? *pm : QPixmap(); } /*! Returns the AppLnk with the given \a id. */ const AppLnk *AppLnkSet::find( int id ) const { QListIterator<AppLnk> it( children() ); for ( ; it.current(); ++it ) { const AppLnk *app = it.current(); if ( app->id() == id ) return app; } return 0; } /*! Returns the AppLnk with the given \a exec attribute. */ const AppLnk *AppLnkSet::findExec( const QString& exec ) const { QListIterator<AppLnk> it( children() ); for ( ; it.current(); ++it ) { const AppLnk *app = it.current(); if ( app->exec() == exec ) return app; } return 0; } /*! \class DocLnkSet applnk.h \brief The DocLnkSet class is a set of DocLnk objects. */ /*! \fn const QList<DocLnk>& DocLnkSet::children() const Returns the members of the set. */ /*! Constructs an empty DocLnkSet. \sa appendFrom() */ DocLnkSet::DocLnkSet() { } /*! Constructs a DocLnkSet that contains DocLnk objects representing all the files in the \a directory (and any subdirectories, recursively). If \a mimefilter is not null, only documents with a MIME type matching \a mimefilter are selected. The value may contain multiple wild-card patterns separated by ";", such as \c{*o/mpeg;audio/x-wav}. See also \link applnk.html#files-and-links Files and Links\endlink. */ DocLnkSet::DocLnkSet( const QString &directory, const QString& mimefilter ) : AppLnkSet() { QDir dir( directory ); mFile = dir.dirName(); QDict<void> reference(1021); QStringList subFilter = QStringList::split(";", mimefilter); QValueList<QRegExp> mimeFilters; for( QStringList::Iterator it = subFilter.begin(); it != subFilter.end(); ++ it ) mimeFilters.append( QRegExp(*it, FALSE, TRUE) ); findChildren(directory, mimeFilters, reference); const QList<DocLnk> &list = children(); for ( QListIterator<DocLnk> it( list ); it.current(); ++it ) { reference.remove( (*it)->file() ); } for ( QDictIterator<void> dit(reference); dit.current(); ++dit ) { if ( dit.current() == (void*)2 ) { // Unreferenced, make an unwritten link DocLnk* dl = new DocLnk; QFileInfo fi( dit.currentKey() ); dl->setFile(fi.filePath()); dl->setName(fi.baseName()); // #### default to current path? // dl->setCategories( ... ); bool match = mimefilter.isNull(); if ( !match ) for( QValueList<QRegExp>::Iterator it = mimeFilters.begin(); it != mimeFilters.end() && !match; ++ it ) if ( (*it).match(dl->type()) >= 0 ) match = TRUE; if ( match /* && dl->type() != "application/octet-stream" */ && !!dl->exec() ) add(dl); else delete dl; } } } // other becomes empty /*! Transfers all DocLnk objects from \a other to this set. \a other becomes empty. */ void DocLnkSet::appendFrom( DocLnkSet& other ) { if ( &other == this ) return; QListIterator<AppLnk> it( other.mApps ); for ( ; it.current(); ) { mApps.append(*it); ++it; } other.mApps.clear(); } void DocLnkSet::findChildren(const QString &dr, const QValueList<QRegExp> &mimeFilters, QDict<void> &reference, int depth) { depth++; if ( depth > 10 ) return; QDir dir( dr ); /* Opie got a different approach * I guess it's geek vs. consumer * in this case to be discussed */ if ( dir.exists( ".Qtopia-ignore" ) ) return; const QFileInfoList *list = dir.entryInfoList(); if ( list ) { QFileInfo* fi; for ( QFileInfoListIterator it(*list); (fi=*it); ++it ) { QString bn = fi->fileName(); if ( bn[0] != '.' ) { if ( fi->isDir() ) { if ( bn != "CVS" && bn != "Qtopia" && bn != "QtPalmtop" ) 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 an attempt is made to read \a file as a .desktop file; if that fails it is read as a normal 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. Just like 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/tzselect.cpp b/library/tzselect.cpp index 848dfb7..8dd427f 100644 --- a/library/tzselect.cpp +++ b/library/tzselect.cpp @@ -1,302 +1,303 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #define QTOPIA_INTERNAL_TZSELECT_INC_LOCAL #include "tzselect.h" #include "resource.h" #include "config.h" #include <qtoolbutton.h> #include <qfile.h> #include <stdlib.h> #include <qcopchannel_qws.h> +#include <qpe/global.h> #include <qpe/qpeapplication.h> #include <qmessagebox.h> /*! \class TimeZoneSelector \brief The TimeZoneSelector widget allows users to configure their time zone information. \ingroup qtopiaemb */ class TimeZoneSelectorPrivate { public: TimeZoneSelectorPrivate() : includeLocal(FALSE) {} bool includeLocal; }; TZCombo::TZCombo( QWidget *p, const char* n ) : QComboBox( p, n ) { updateZones(); // check to see if TZ is set, if it is set the current item to that QString tz = getenv("TZ"); if (parent()->inherits("TimeZoneSelector")) { if ( ((TimeZoneSelector *)parent())->localIncluded() ) { // overide to the 'local' type. tz = "None"; } } if ( !tz.isNull() ) { int n = 0, index = 0; for ( QStringList::Iterator it=identifiers.begin(); it!=identifiers.end(); ++it) { if ( *it == tz ) index = n; n++; } setCurrentItem(index); } else { setCurrentItem(0); } // listen on QPE/System #if !defined(QT_NO_COP) QCopChannel *channel = new QCopChannel( "QPE/System", this ); connect( channel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(handleSystemChannel(const QCString&,const QByteArray&)) ); #endif } TZCombo::~TZCombo() { } void TZCombo::updateZones() { QString cur = currentText(); clear(); identifiers.clear(); int curix=0; QString tz = getenv("TZ"); bool tzFound = FALSE; Config cfg("CityTime"); cfg.setGroup("TimeZones"); int listIndex = 0; if (parent()->inherits("TimeZoneSelector")) { if ( ((TimeZoneSelector *)parent())->localIncluded() ) { // overide to the 'local' type. identifiers.append( "None" ); insertItem( tr("None") ); if ( cur == tr("None")) curix = 0; listIndex++; } } int cfgIndex = 0; while (1) { QString zn = cfg.readEntry("Zone"+QString::number(cfgIndex), QString::null); if ( zn.isNull() ) break; if ( zn == tz ) tzFound = TRUE; QString nm = cfg.readEntry("ZoneName"+QString::number(cfgIndex)); identifiers.append(zn); insertItem(nm); if ( nm == cur ) curix = listIndex; ++cfgIndex; ++listIndex; } if ( !listIndex ) { QStringList list = timezoneDefaults(); for ( QStringList::Iterator it = list.begin(); it!=list.end(); ++it ) { QString zn = *it; QString nm = *++it; if ( zn == tz ) tzFound = TRUE; if ( nm == cur ) curix = listIndex; identifiers.append(zn); insertItem(nm); ++listIndex; } } for (QStringList::Iterator it=extras.begin(); it!=extras.end(); ++it) { insertItem(*it); identifiers.append(*it); if ( *it == cur ) curix = listIndex; ++listIndex; } if ( !tzFound && !tz.isEmpty()) { int i = tz.find( '/' ); QString nm = tz.mid( i+1 ).replace(QRegExp("_"), " "); identifiers.append(tz); insertItem(nm); if ( nm == cur ) curix = listIndex; ++listIndex; } setCurrentItem(curix); } void TZCombo::keyPressEvent( QKeyEvent *e ) { // ### should popup() in Qt 3.0 (it's virtual there) // updateZones(); QComboBox::keyPressEvent(e); } void TZCombo::mousePressEvent(QMouseEvent*e) { // ### should popup() in Qt 3.0 (it's virtual there) // updateZones(); QComboBox::mousePressEvent(e); } QString TZCombo::currZone() const { return identifiers[currentItem()]; } void TZCombo::setCurrZone( const QString& id ) { for (int i=0; i< count(); i++) { if ( identifiers[i] == id ) { setCurrentItem(i); return; } } insertItem(id); setCurrentItem( count() - 1); identifiers.append(id); extras.append(id); } void TZCombo::handleSystemChannel(const QCString&msg, const QByteArray&) { if ( msg == "timeZoneListChange()" ) { updateZones(); } } /*! Creates a new TimeZoneSelector with parent \a p and name \a n. The combobox will be populated with the available timezones. */ TimeZoneSelector::TimeZoneSelector(QWidget* p, const char* n) : QHBox(p,n) { d = new TimeZoneSelectorPrivate(); // build the combobox before we do any updates... cmbTz = new TZCombo( this, "timezone combo" ); cmdTz = new QToolButton( this, "timezone button" ); cmdTz->setIconSet( Resource::loadIconSet( "citytime_icon" ) ); cmdTz->setMaximumSize( cmdTz->sizeHint() ); // set up a connection to catch a newly selected item and throw our // signal QObject::connect( cmbTz, SIGNAL( activated(int) ), this, SLOT( slotTzActive(int) ) ); QObject::connect( cmdTz, SIGNAL( clicked() ), this, SLOT( slotExecute() ) ); } /*! Destroys a TimeZoneSelector. */ TimeZoneSelector::~TimeZoneSelector() { } void TimeZoneSelector::setLocalIncluded(bool b) { d->includeLocal = b; cmbTz->updateZones(); } bool TimeZoneSelector::localIncluded() const { return d->includeLocal; } /*! Returns the currently selected timezone as a string in location format, e.g. \code Australia/Brisbane \endcode */ QString TimeZoneSelector::currentZone() const { return cmbTz->currZone(); } /*! Sets the current timezone to \a id. */ void TimeZoneSelector::setCurrentZone( const QString& id ) { cmbTz->setCurrZone( id ); } /*! \fn void TimeZoneSelector::signalNewTz( const QString& id ) This signal is emitted when a timezone has been selected by the user. The id is a \l QString in location format, eg \code Australia/Brisbane \endcode */ void TimeZoneSelector::slotTzActive( int ) { emit signalNewTz( cmbTz->currZone() ); } void TimeZoneSelector::slotExecute( void ) { // execute the world time application... if (QFile::exists(QPEApplication::qpeDir()+"bin/citytime")) Global::execute( "citytime" ); else QMessageBox::warning(this,tr("citytime executable not found"), tr("In order to choose the time zones,\nplease install citytime.")); } QStringList timezoneDefaults( void ) { QStringList tzs; // load up the list just like the file format (citytime.cpp) tzs.append( "America/New_York" ); tzs.append( "New York" ); tzs.append( "America/Los_Angeles" ); tzs.append( "Los Angeles" ); tzs.append( "Australia/Brisbane" ); tzs.append( "Brisbane" ); tzs.append( "Europe/Berlin" ); tzs.append( "Berlin" ); tzs.append( "Asia/Tokyo" ); tzs.append( "Tokyo" ); tzs.append( "America/Denver" ); tzs.append( "Denver" ); return tzs; } |