-rw-r--r-- | library/alarmserver.cpp | 23 | ||||
-rw-r--r-- | library/global.cpp | 6 |
2 files changed, 17 insertions, 12 deletions
diff --git a/library/alarmserver.cpp b/library/alarmserver.cpp index 2ea4025..a75fc7e 100644 --- a/library/alarmserver.cpp +++ b/library/alarmserver.cpp @@ -179,271 +179,274 @@ static bool triggerAtd( bool writeHWClock = FALSE ) } 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. - + \ingroup qtopiaemb \sa QCopEnvelope */ /*! 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. - + \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 } } /*! - Writes the system clock to the hardware clock. + 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/global.cpp b/library/global.cpp index 5c89430..90954fe 100644 --- a/library/global.cpp +++ b/library/global.cpp @@ -88,258 +88,260 @@ signals: }; class StartingAppList : public QObject { Q_OBJECT public: static void add( const QString& name ); static bool isStarting( const QString name ); private slots: void handleNewChannel( const QString &); private: StartingAppList( QObject *parent=0, const char* name=0 ) ; QDict<QTime> dict; static StartingAppList *appl; }; StartingAppList* StartingAppList::appl = 0; StartingAppList::StartingAppList( QObject *parent, const char* name ) :QObject( parent, name ) { #if QT_VERSION >= 232 && defined(QWS) connect( qwsServer, SIGNAL( newChannel(const QString&)), this, SLOT( handleNewChannel(const QString&)) ); #endif dict.setAutoDelete( TRUE ); } void StartingAppList::add( const QString& name ) { #if QT_VERSION >= 232 && !defined(QT_NO_COP) if ( !appl ) appl = new StartingAppList; QTime *t = new QTime; t->start(); appl->dict.insert( "QPE/Application/" + name, t ); #endif } bool StartingAppList::isStarting( const QString name ) { #if QT_VERSION >= 232 && !defined(QT_NO_COP) if ( appl ) { QTime *t = appl->dict.find( "QPE/Application/" + name ); if ( !t ) return FALSE; if ( t->elapsed() > 10000 ) { // timeout in case of crash or something appl->dict.remove( "QPE/Application/" + name ); return FALSE; } return TRUE; } #endif return FALSE; } void StartingAppList::handleNewChannel( const QString & name ) { #if QT_VERSION >= 232 && !defined(QT_NO_COP) dict.remove( name ); #endif } static bool docDirCreated = FALSE; static QDawg* fixed_dawg = 0; static QDict<QDawg> *named_dawg = 0; static QString qpeDir() { QString dir = getenv("OPIEDIR"); if ( dir.isEmpty() ) dir = ".."; return dir; } static QString dictDir() { return qpeDir() + "/etc/dict"; } /*! \class Global global.h \brief The Global class provides application-wide global functions. The Global functions are grouped as follows: \tableofcontents \section1 User Interface The statusMessage() function provides short-duration messages to the user. The showInputMethod() function shows the current input method, and hideInputMethod() hides the input method. \section1 Document related The findDocuments() function creates a set of \link doclnk.html DocLnk\endlink objects in a particular folder. \section1 Filesystem related Global provides an applicationFileName() function that returns the full path of an application-specific file. The execute() function runs an application. \section1 Word list related A list of words relevant to the current locale is maintained by the system. The list is held in a \link qdawg.html DAWG\endlink (implemented by the QDawg class). This list is used, for example, by the pickboard input method. The global QDawg is returned by fixedDawg(); this cannot be updated. An updatable copy of the global QDawg is returned by addedDawg(). Applications may have their own word lists stored in \l{QDawg}s which are returned by dawg(). Use addWords() to add words to the updateable copy of the global QDawg or to named application \l{QDawg}s. \section1 Quoting The shellQuote() function quotes a string suitable for passing to a shell. The stringQuote() function backslash escapes '\' and '"' characters. \section1 Hardware - The writeHWClock() function sets the hardware clock to the system - clock's date and time. + The implementation of the writeHWClock() function depends on the AlarmServer + implementation. If the AlarmServer is using atd the clock will be synced to + hardware. If opie-alarm is used the hardware clock will be synced before + suspending the device. opie-alarm is used by iPAQ and Zaurii implementation \ingroup qtopiaemb */ /*! \internal */ Global::Global() { } /*! Returns the unchangeable QDawg that contains general words for the current locale. \sa addedDawg() */ const QDawg& Global::fixedDawg() { if ( !fixed_dawg ) { if ( !docDirCreated ) createDocDir(); fixed_dawg = new QDawg; QString dawgfilename = dictDir() + "/dawg"; QString words_lang; QStringList langs = Global::languageList(); for (QStringList::ConstIterator it = langs.begin(); it!=langs.end(); ++it) { QString lang = *it; words_lang = dictDir() + "/words." + lang; QString dawgfilename_lang = dawgfilename + "." + lang; if ( QFile::exists(dawgfilename_lang) || QFile::exists(words_lang) ) { dawgfilename = dawgfilename_lang; break; } } QFile dawgfile(dawgfilename); if ( !dawgfile.exists() ) { QString fn = dictDir() + "/words"; if ( QFile::exists(words_lang) ) fn = words_lang; QFile in(fn); if ( in.open(IO_ReadOnly) ) { fixed_dawg->createFromWords(&in); dawgfile.open(IO_WriteOnly); fixed_dawg->write(&dawgfile); dawgfile.close(); } } else { fixed_dawg->readFile(dawgfilename); } } return *fixed_dawg; } /*! Returns the changeable QDawg that contains general words for the current locale. \sa fixedDawg() */ const QDawg& Global::addedDawg() { return dawg("local"); } /*! Returns the QDawg with the given \a name. This is an application-specific word list. \a name should not contain "/". */ const QDawg& Global::dawg(const QString& name) { createDocDir(); if ( !named_dawg ) named_dawg = new QDict<QDawg>; QDawg* r = named_dawg->find(name); if ( !r ) { r = new QDawg; named_dawg->insert(name,r); QString dawgfilename = applicationFileName("Dictionary", name ) + ".dawg"; QFile dawgfile(dawgfilename); if ( dawgfile.open(IO_ReadOnly) ) r->readFile(dawgfilename); } return *r; } /*! \overload Adds \a wordlist to the addedDawg(). Note that the addition of words persists between program executions (they are saved in the dictionary files), so you should confirm the words with the user before adding them. */ void Global::addWords(const QStringList& wordlist) { addWords("local",wordlist); } /*! \overload Adds \a wordlist to the addedDawg(). Note that the addition of words persists between program executions (they are saved in the dictionary files), so you should confirm the words with the user before adding them. */ void Global::addWords(const QString& dictname, const QStringList& wordlist) { QDawg& d = (QDawg&)dawg(dictname); QStringList all = d.allWords() + wordlist; d.createFromWords(all); QString dawgfilename = applicationFileName("Dictionary", dictname) + ".dawg"; QFile dawgfile(dawgfilename); if ( dawgfile.open(IO_WriteOnly) ) { d.write(&dawgfile); dawgfile.close(); } // #### Re-read the dawg here if we use mmap(). |