author | mickeyl <mickeyl> | 2004-04-07 13:36:16 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2004-04-07 13:36:16 (UTC) |
commit | 4f1d28a25ce6180850c3d26bac9b638f0f25532b (patch) (side-by-side diff) | |
tree | 59b4879b1065086c9a2e28f16f7d48540c8a9456 | |
parent | 8af35b63a277ec14dcc4a0a6ca5bbe228e276b98 (diff) | |
download | opie-4f1d28a25ce6180850c3d26bac9b638f0f25532b.zip opie-4f1d28a25ce6180850c3d26bac9b638f0f25532b.tar.gz opie-4f1d28a25ce6180850c3d26bac9b638f0f25532b.tar.bz2 |
use Opie debugging framework
-rw-r--r-- | core/launcher/applauncher.cpp | 83 | ||||
-rw-r--r-- | core/launcher/documentlist.cpp | 46 | ||||
-rw-r--r-- | core/launcher/firstuse.cpp | 44 | ||||
-rw-r--r-- | core/launcher/inputmethods.cpp | 34 | ||||
-rw-r--r-- | core/launcher/irserver.cpp | 16 | ||||
-rw-r--r-- | core/launcher/launcher.cpp | 37 | ||||
-rw-r--r-- | core/launcher/launcherview.cpp | 9 | ||||
-rw-r--r-- | core/launcher/main.cpp | 42 | ||||
-rw-r--r-- | core/launcher/packageslave.cpp | 26 | ||||
-rw-r--r-- | core/launcher/qcopbridge.cpp | 23 | ||||
-rw-r--r-- | core/launcher/qprocess.cpp | 14 | ||||
-rw-r--r-- | core/launcher/qprocess_unix.cpp | 93 | ||||
-rw-r--r-- | core/launcher/runningappbar.cpp | 24 | ||||
-rw-r--r-- | core/launcher/screensaver.cpp | 2 | ||||
-rw-r--r-- | core/launcher/server.cpp | 32 | ||||
-rw-r--r-- | core/launcher/serverapp.cpp | 26 | ||||
-rw-r--r-- | core/launcher/suspendmonitor.cpp | 2 | ||||
-rw-r--r-- | core/launcher/systray.cpp | 18 | ||||
-rw-r--r-- | core/launcher/taskbar.cpp | 7 | ||||
-rw-r--r-- | core/launcher/transferserver.cpp | 107 |
20 files changed, 334 insertions, 351 deletions
diff --git a/core/launcher/applauncher.cpp b/core/launcher/applauncher.cpp index 5a5517c..7000346 100644 --- a/core/launcher/applauncher.cpp +++ b/core/launcher/applauncher.cpp @@ -1,722 +1,719 @@ /********************************************************************** ** 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. ** **********************************************************************/ #ifndef QTOPIA_INTERNAL_PRELOADACCESS #define QTOPIA_INTERNAL_PRELOADACCESS #endif #ifndef QTOPIA_INTERNAL_FILEOPERATIONS #define QTOPIA_INTERNAL_FILEOPERATIONS #endif #ifndef QTOPIA_PROGRAM_MONITOR #define QTOPIA_PROGRAM_MONITOR #endif + +#include "applauncher.h" +#include "documentlist.h" + +/* OPIE */ +#include <opie2/odebug.h> #include <opie2/oglobal.h> +#include <qtopia/qcopenvelope_qws.h> +#include <qtopia/qpeapplication.h> +using namespace Opie::Core; -#ifndef Q_OS_WIN32 +/* QT */ +#include <qtimer.h> +#include <qwindowsystem_qws.h> +#include <qmessagebox.h> +#include <qfileinfo.h> + +/* STD */ #include <sys/stat.h> #include <sys/wait.h> #include <sys/file.h> #include <unistd.h> #include <sys/time.h> #include <sys/resource.h> #include <errno.h> -#else -#include <process.h> -#include <windows.h> -#include <winbase.h> -#endif - #include <signal.h> #include <sys/types.h> #include <stdlib.h> -#include <qtimer.h> -#include <qwindowsystem_qws.h> -#include <qmessagebox.h> -#include <qfileinfo.h> - -#include <qtopia/qcopenvelope_qws.h> -#include <qtopia/qpeapplication.h> - -#include "applauncher.h" -#include "documentlist.h" - -using namespace Opie::Core; const int AppLauncher::RAISE_TIMEOUT_MS = 5000; //--------------------------------------------------------------------------- static AppLauncher* appLauncherPtr; const int appStopEventID = 1290; class AppStoppedEvent : public QCustomEvent { public: AppStoppedEvent(int pid, int status) : QCustomEvent( appStopEventID ), mPid(pid), mStatus(status) { } int pid() { return mPid; } int status() { return mStatus; } private: int mPid, mStatus; }; AppLauncher::AppLauncher(QObject *parent, const char *name) : QObject(parent, name), qlPid(0), qlReady(FALSE), appKillerBox(0) { connect(qwsServer, SIGNAL(newChannel(const QString&)), this, SLOT(newQcopChannel(const QString&))); connect(qwsServer, SIGNAL(removedChannel(const QString&)), this, SLOT(removedQcopChannel(const QString&))); QCopChannel* channel = new QCopChannel( "QPE/System", this ); connect( channel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(received(const QCString&,const QByteArray&)) ); channel = new QCopChannel( "QPE/Server", this ); connect( channel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(received(const QCString&,const QByteArray&)) ); #ifndef Q_OS_WIN32 signal(SIGCHLD, signalHandler); #else runningAppsProc.setAutoDelete( TRUE ); #endif QString tmp = qApp->argv()[0]; int pos = tmp.findRev('/'); if ( pos > -1 ) tmp = tmp.mid(++pos); runningApps[::getpid()] = tmp; appLauncherPtr = this; QTimer::singleShot( 1000, this, SLOT(createQuickLauncher()) ); } AppLauncher::~AppLauncher() { appLauncherPtr = 0; #ifndef Q_OS_WIN32 signal(SIGCHLD, SIG_DFL); #endif if ( qlPid ) { int status; ::kill( qlPid, SIGTERM ); waitpid( qlPid, &status, 0 ); } } /* We use the QCopChannel of the app as an indicator of when it has been launched so that we can disable the busy indicators */ void AppLauncher::newQcopChannel(const QString& channelName) { -// qDebug("channel %s added", channelName.data() ); +// odebug << "channel " << channelName.data() << " added" << oendl; QString prefix("QPE/Application/"); if (channelName.startsWith(prefix)) { { QCopEnvelope e("QPE/System", "newChannel(QString)"); e << channelName; } QString appName = channelName.mid(prefix.length()); if ( appName != "quicklauncher" ) { emit connected( appName ); QCopEnvelope e("QPE/System", "notBusy(QString)"); e << appName; } } else if (channelName.startsWith("QPE/QuickLauncher-")) { - qDebug("Registered %s", channelName.latin1()); + odebug << "Registered " << channelName << "" << oendl; int pid = channelName.mid(18).toInt(); if (pid == qlPid) qlReady = TRUE; } } void AppLauncher::removedQcopChannel(const QString& channelName) { if (channelName.startsWith("QPE/Application/")) { QCopEnvelope e("QPE/System", "removedChannel(QString)"); e << channelName; } } void AppLauncher::received(const QCString& msg, const QByteArray& data) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "execute(QString)" ) { QString t; stream >> t; if ( !executeBuiltin( t, QString::null ) ) execute(t, QString::null); } else if ( msg == "execute(QString,QString)" ) { QString t,d; stream >> t >> d; if ( !executeBuiltin( t, d ) ) execute( t, d ); } else if ( msg == "processQCop(QString)" ) { // from QPE/Server QString t; stream >> t; if ( !executeBuiltin( t, QString::null ) ) execute( t, QString::null, TRUE); } else if ( msg == "raise(QString)" ) { QString appName; stream >> appName; if ( !executeBuiltin( appName, QString::null ) ) { if ( !waitingHeartbeat.contains( appName ) && appKillerName != appName ) { - //qDebug( "Raising: %s", appName.latin1() ); + //odebug << "Raising: " << appName << "" << oendl; QCString channel = "QPE/Application/"; channel += appName.latin1(); // Need to lock it to avoid race conditions with QPEApplication::processQCopFile QFile f("/tmp/qcop-msg-" + appName); if ( f.open(IO_WriteOnly | IO_Append) ) { #ifndef Q_OS_WIN32 flock(f.handle(), LOCK_EX); #endif QDataStream ds(&f); QByteArray b; QDataStream bstream(b, IO_WriteOnly); ds << channel << QCString("raise()") << b; f.flush(); #ifndef Q_OS_WIN32 flock(f.handle(), LOCK_UN); #endif f.close(); } bool alreadyRunning = isRunning( appName ); if ( execute(appName, QString::null) ) { int id = startTimer(RAISE_TIMEOUT_MS + alreadyRunning?2000:0); waitingHeartbeat.insert( appName, id ); } } } } else if ( msg == "sendRunningApps()" ) { QStringList apps; QMap<int,QString>::Iterator it; for( it = runningApps.begin(); it != runningApps.end(); ++it ) apps.append( *it ); QCopEnvelope e( "QPE/Desktop", "runningApps(QStringList)" ); e << apps; } else if ( msg == "appRaised(QString)" ) { QString appName; stream >> appName; - qDebug("Got a heartbeat from %s", appName.latin1()); + odebug << "Got a heartbeat from " << appName << "" << oendl; QMap<QString,int>::Iterator it = waitingHeartbeat.find(appName); if ( it != waitingHeartbeat.end() ) { killTimer( *it ); waitingHeartbeat.remove(it); } // Check to make sure we're not waiting on user input... if ( appKillerBox && appName == appKillerName ) { // If we are, we kill the dialog box, and the code waiting on the result // will clean us up (basically the user said "no"). delete appKillerBox; appKillerBox = 0; appKillerName = QString::null; } } } void AppLauncher::signalHandler(int) { #ifndef Q_OS_WIN32 int status; pid_t pid = waitpid(-1, &status, WNOHANG); /* if (pid == 0 || &status == 0 ) { - qDebug("hmm, could not get return value from signal"); + odebug << "hmm, could not get return value from signal" << oendl; } */ QApplication::postEvent(appLauncherPtr, new AppStoppedEvent(pid, status) ); #else - qDebug("Unhandled signal see by AppLauncher::signalHandler(int)"); + odebug << "Unhandled signal see by AppLauncher::signalHandler(int)" << oendl; #endif } bool AppLauncher::event(QEvent *e) { if ( e->type() == appStopEventID ) { AppStoppedEvent *ae = (AppStoppedEvent *) e; sigStopped(ae->pid(), ae->status() ); return TRUE; } return QObject::event(e); } void AppLauncher::timerEvent( QTimerEvent *e ) { int id = e->timerId(); QMap<QString,int>::Iterator it; for ( it = waitingHeartbeat.begin(); it != waitingHeartbeat.end(); ++it ) { if ( *it == id ) { if ( appKillerBox ) // we're already dealing with one return; appKillerName = it.key(); killTimer( id ); waitingHeartbeat.remove( it ); - // qDebug("Checking in on %s", appKillerName.latin1()); + // odebug << "Checking in on " << appKillerName << "" << oendl; // We store this incase the application responds while we're // waiting for user input so we know not to delete ourselves. appKillerBox = new QMessageBox(tr("Application Problem"), tr("<p>%1 is not responding.</p>").arg(appKillerName) + tr("<p>Would you like to force the application to exit?</p>"), QMessageBox::Warning, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default, QMessageBox::NoButton); if (appKillerBox->exec() == QMessageBox::Yes) { - // qDebug("Killing the app!!! Bwuhahahaha!"); + // odebug << "Killing the app!!! Bwuhahahaha!" << oendl; int pid = pidForName(appKillerName); if ( pid > 0 ) kill( pid ); } appKillerName = QString::null; delete appKillerBox; appKillerBox = 0; return; } } QObject::timerEvent( e ); } #ifndef Q_OS_WIN32 void AppLauncher::sigStopped(int sigPid, int sigStatus) { int exitStatus = 0; bool crashed = WIFSIGNALED(sigStatus); if ( !crashed ) { if ( WIFEXITED(sigStatus) ) exitStatus = WEXITSTATUS(sigStatus); } else { exitStatus = WTERMSIG(sigStatus); } QMap<int,QString>::Iterator it = runningApps.find( sigPid ); if ( it == runningApps.end() ) { if ( sigPid == qlPid ) { - qDebug( "quicklauncher stopped" ); + odebug << "quicklauncher stopped" << oendl; qlPid = 0; qlReady = FALSE; QFile::remove("/tmp/qcop-msg-quicklauncher" ); QTimer::singleShot( 2000, this, SLOT(createQuickLauncher()) ); } /* if ( sigPid == -1 ) - qDebug("non-qtopia application exited (disregarded)"); + odebug << "non-qtopia application exited (disregarded)" << oendl; else - qDebug("==== no pid matching %d in list, definite bug", sigPid); + odebug << "==== no pid matching " << sigPid << " in list, definite bug" << oendl; */ return; } QString appName = *it; runningApps.remove(it); QMap<QString,int>::Iterator hbit = waitingHeartbeat.find(appName); if ( hbit != waitingHeartbeat.end() ) { killTimer( *hbit ); waitingHeartbeat.remove( hbit ); } if ( appName == appKillerName ) { appKillerName = QString::null; delete appKillerBox; appKillerBox = 0; } /* we must disable preload for an app that crashes as the system logic relies on preloaded apps actually being loaded. If eg. the crash happened in the constructor, we can't automatically reload the app (withouth some timeout value for eg. 3 tries (which I think is a bad solution) */ bool preloadDisabled = FALSE; if ( !DocumentList::appLnkSet ) return; const AppLnk* app = DocumentList::appLnkSet->findExec( appName ); if ( !app ) return; // QCop messages processed to slow? if ( crashed && app->isPreloaded() ) { Config cfg("Launcher"); cfg.setGroup("Preload"); QStringList apps = cfg.readListEntry("Apps",','); QString exe = app->exec(); apps.remove(exe); cfg.writeEntry("Apps",apps,','); preloadDisabled = TRUE; } // clean up if ( exitStatus ) { QCopEnvelope e("QPE/System", "notBusy(QString)"); e << app->exec(); } /* // debug info for (it = runningApps.begin(); it != runningApps.end(); ++it) { - qDebug("running according to internal list: %s, with pid %d", (*it).data(), it.key() ); + odebug << "running according to internal list: " << (*it).data() << ", with pid " << it.key() << "" << oendl; } */ #ifdef QTOPIA_PROGRAM_MONITOR if ( crashed ) { QString sig; switch( exitStatus ) { case SIGABRT: sig = "SIGABRT"; break; case SIGALRM: sig = "SIGALRM"; break; case SIGBUS: sig = "SIGBUS"; break; case SIGFPE: sig = "SIGFPE"; break; case SIGHUP: sig = "SIGHUP"; break; case SIGILL: sig = "SIGILL"; break; case SIGKILL: sig = "SIGKILL"; break; case SIGPIPE: sig = "SIGPIPE"; break; case SIGQUIT: sig = "SIGQUIT"; break; case SIGSEGV: sig = "SIGSEGV"; break; case SIGTERM: sig = "SIGTERM"; break; case SIGTRAP: sig = "SIGTRAP"; break; default: sig = QString("Unkown %1").arg(exitStatus); } if ( preloadDisabled ) sig += tr("<qt><p>Fast loading has been disabled for this application. Tap and hold the application icon to reenable it.</qt>"); QString str = tr("<qt><b>%1</b> was terminated due to signal code %2</qt>").arg( app->name() ).arg( sig ); QMessageBox::information(0, tr("Application terminated"), str ); } else { if ( exitStatus == 255 ) { //could not find app (because global returns -1) QMessageBox::information(0, tr("Application not found"), tr("<qt>Could not locate application <b>%1</b></qt>").arg( app->exec() ) ); } else { QFileInfo fi(QString::fromLatin1("/tmp/qcop-msg-") + appName); if ( fi.exists() && fi.size() ) { emit terminated(sigPid, appName); - qWarning("Re executing obmitted for %s", appName.latin1() ); + owarn << "Re executing obmitted for " << appName << "" << oendl; // execute( appName, QString::null ); return; } } } #endif emit terminated(sigPid, appName); } #else void AppLauncher::sigStopped(int sigPid, int sigStatus) { - qDebug("Unhandled signal : AppLauncher::sigStopped(int sigPid, int sigStatus)"); + odebug << "Unhandled signal : AppLauncher::sigStopped(int sigPid, int sigStatus)" << oendl; } #endif // Q_OS_WIN32 bool AppLauncher::isRunning(const QString &app) { for (QMap<int,QString>::ConstIterator it = runningApps.begin(); it != runningApps.end(); ++it) { if ( *it == app ) { #ifdef Q_OS_UNIX pid_t t = ::__getpgid( it.key() ); if ( t == -1 ) { - qDebug("appLauncher bug, %s believed running, but pid %d is not existing", app.data(), it.key() ); + odebug << "appLauncher bug, " << app.data() << " believed running, but pid " << it.key() << " is not existing" << oendl; runningApps.remove( it.key() ); return FALSE; } #endif return TRUE; } } return FALSE; } bool AppLauncher::executeBuiltin(const QString &c, const QString &document) { Global::Command* builtin = OGlobal::builtinCommands(); QGuardedPtr<QWidget> *running = OGlobal::builtinRunning(); // Attempt to execute the app using a builtin class for the app if (builtin) { for (int i = 0; builtin[i].file; i++) { if ( builtin[i].file == c ) { if ( running[i] ) { if ( !document.isNull() && builtin[i].documentary ) Global::setDocument(running[i], document); running[i]->raise(); running[i]->show(); running[i]->setActiveWindow(); } else { running[i] = builtin[i].func( builtin[i].maximized ); } #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "notBusy(QString)" ); e << c; // that was quick ;-) #endif return TRUE; } } } // Convert the command line in to a list of arguments QStringList list = QStringList::split(QRegExp(" *"),c); QString ap=list[0]; if ( ap == "suspend" ) { // No tr QWSServer::processKeyEvent( 0xffff, Qt::Key_F34, FALSE, TRUE, FALSE ); return TRUE; } return FALSE; } bool AppLauncher::execute(const QString &c, const QString &docParam, bool noRaise) { - qWarning("AppLauncher::execute '%s' '%s'", (const char*) c, (const char*) docParam ); + owarn << "AppLauncher::execute '" << c << "' '" << docParam << "'" << oendl; // Convert the command line in to a list of arguments QStringList list = QStringList::split(QRegExp(" *"),c); QStringList arglist = QStringList::split(QRegExp(" *"),docParam); for ( QStringList::Iterator it = arglist.begin(); it != arglist.end(); ++it ) list.append( *it ); QString appName = list[0]; if ( isRunning(appName) ) { QCString channel = "QPE/Application/"; channel += appName.latin1(); // Need to lock it to avoid race conditions with QPEApplication::processQCopFile QFile f(QString::fromLatin1("/tmp/qcop-msg-") + appName); if ( !noRaise && f.open(IO_WriteOnly | IO_Append) ) { #ifndef Q_OS_WIN32 flock(f.handle(), LOCK_EX); #endif QDataStream ds(&f); QByteArray b; QDataStream bstream(b, IO_WriteOnly); if ( !f.size() ) { ds << channel << QCString("raise()") << b; if ( !waitingHeartbeat.contains( appName ) && appKillerName != appName ) { int id = startTimer(RAISE_TIMEOUT_MS); waitingHeartbeat.insert( appName, id ); } } if ( !docParam.isEmpty() ) { bstream << docParam; ds << channel << QCString("setDocument(QString)") << b; } f.flush(); #ifndef Q_OS_WIN32 flock(f.handle(), LOCK_UN); #endif f.close(); } if ( QCopChannel::isRegistered(channel) ) // avoid unnecessary warnings QCopChannel::send(channel,"QPEProcessQCop()"); return TRUE; } #ifdef QT_NO_QWS_MULTIPROCESS QMessageBox::warning( 0, tr("Error"), tr("<qt>Could not find the application %1</qt>").arg(c), tr("OK"), 0, 0, 0, 1 ); #else QStrList slist; unsigned 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; #ifndef Q_OS_WIN32 #ifdef Q_OS_MACX if ( qlPid && qlReady && QFile::exists( QPEApplication::qpeDir()+"plugins/application/lib"+args[0] + ".dylib" ) ) { #else if ( qlPid && qlReady && QFile::exists( QPEApplication::qpeDir()+"plugins/application/lib"+args[0] + ".so" ) ) { #endif /* Q_OS_MACX */ - qDebug( "Quick launching: %s", args[0] ); + odebug << "Quick launching: " << args[0] << "" << oendl; if ( getuid() == 0 ) setpriority( PRIO_PROCESS, qlPid, 0 ); QCString qlch("QPE/QuickLauncher-"); qlch += QString::number(qlPid); QCopEnvelope env( qlch, "execute(QStrList)" ); env << slist; runningApps[qlPid] = QString(args[0]); emit launched(qlPid, QString(args[0])); QCopEnvelope e("QPE/System", "busy()"); qlPid = 0; qlReady = FALSE; QTimer::singleShot( getuid() == 0 ? 800 : 1500, this, SLOT(createQuickLauncher()) ); } else { int pid = ::vfork(); if ( !pid ) { for ( int fd = 3; fd < 100; fd++ ) ::close( fd ); ::setpgid( ::getpid(), ::getppid() ); // Try bindir first, so that foo/bar works too ::execv( QPEApplication::qpeDir()+"bin/"+args[0], (char * const *)args ); ::execvp( args[0], (char * const *)args ); _exit( -1 ); } runningApps[pid] = QString(args[0]); emit launched(pid, QString(args[0])); QCopEnvelope e("QPE/System", "busy()"); } #else QProcess *proc = new QProcess(this); if (proc){ for (int i=0; i < slist.count(); i++) proc->addArgument(args[i]); connect(proc, SIGNAL(processExited()), this, SLOT(processExited())); if (!proc->start()){ - qDebug("Unable to start application %s", args[0]); + odebug << "Unable to start application " << args[0] << "" << oendl; }else{ PROCESS_INFORMATION *procInfo = (PROCESS_INFORMATION *)proc->processIdentifier(); if (procInfo){ DWORD pid = procInfo->dwProcessId; runningApps[pid] = QString(args[0]); runningAppsProc.append(proc); emit launched(pid, QString(args[0])); QCopEnvelope e("QPE/System", "busy()"); }else{ - qDebug("Unable to read process inforation #1 for %s", args[0]); + odebug << "Unable to read process inforation #1 for " << args[0] << "" << oendl; } } }else{ - qDebug("Unable to create process for application %s", args[0]); + odebug << "Unable to create process for application " << args[0] << "" << oendl; return FALSE; } #endif #endif //QT_NO_QWS_MULTIPROCESS delete [] args; return TRUE; } void AppLauncher::kill( int pid ) { #ifndef Q_OS_WIN32 ::kill( pid, SIGTERM ); #else for ( QProcess *proc = runningAppsProc.first(); proc; proc = runningAppsProc.next() ) { if ( proc->processIdentifier() == pid ) { proc->kill(); break; } } #endif } int AppLauncher::pidForName( const QString &appName ) { int pid = -1; QMap<int, QString>::Iterator it; for (it = runningApps.begin(); it!= runningApps.end(); ++it) { if (*it == appName) { pid = it.key(); break; } } return pid; } void AppLauncher::createQuickLauncher() { static bool disabled = FALSE; if (disabled) return; qlReady = FALSE; qlPid = ::vfork(); if ( !qlPid ) { char **args = new char *[2]; args[0] = "quicklauncher"; args[1] = 0; for ( int fd = 3; fd < 100; fd++ ) ::close( fd ); ::setpgid( ::getpid(), ::getppid() ); // Try bindir first, so that foo/bar works too /* * LD_BIND_NOW will change the behaviour of ld.so and dlopen * RTLD_LAZY will be made RTLD_NOW which leads to problem * with miscompiled libraries... if LD_BIND_NOW is set.. there * is no way back.. We will wait for numbers from TT to see * if using LD_BIND_NOW is worth it - zecke */ // setenv( "LD_BIND_NOW", "1", 1 ); ::execv( QPEApplication::qpeDir()+"bin/quicklauncher", args ); ::execvp( "quicklauncher", args ); delete []args; disabled = TRUE; _exit( -1 ); } else if ( qlPid == -1 ) { qlPid = 0; } else { if ( getuid() == 0 ) setpriority( PRIO_PROCESS, qlPid, 19 ); } } // Used only by Win32 void AppLauncher::processExited() { #ifdef Q_OS_WIN32 - qDebug("AppLauncher::processExited()"); + odebug << "AppLauncher::processExited()" << oendl; bool found = FALSE; QProcess *proc = (QProcess *) sender(); if (!proc){ - qDebug("Interanl error NULL proc"); + odebug << "Interanl error NULL proc" << oendl; return; } QString appName = proc->arguments()[0]; - qDebug("Removing application %s", appName.latin1()); + odebug << "Removing application " << appName << "" << oendl; runningAppsProc.remove(proc); QMap<QString,int>::Iterator hbit = waitingHeartbeat.find(appName); if ( hbit != waitingHeartbeat.end() ) { killTimer( *hbit ); waitingHeartbeat.remove( hbit ); } if ( appName == appKillerName ) { appKillerName = QString::null; delete appKillerBox; appKillerBox = 0; } // Search for the app to find its PID QMap<int, QString>::Iterator it; for (it = runningApps.begin(); it!= runningApps.end(); ++it){ if (it.data() == appName){ found = TRUE; break; } } if (found){ emit terminated(it.key(), it.data()); runningApps.remove(it.key()); }else{ - qDebug("Internal error application %s not listed as running", appName.latin1()); + odebug << "Internal error application " << appName << " not listed as running" << oendl; } #endif } diff --git a/core/launcher/documentlist.cpp b/core/launcher/documentlist.cpp index 3e0a96c..92b8c25 100644 --- a/core/launcher/documentlist.cpp +++ b/core/launcher/documentlist.cpp @@ -1,698 +1,700 @@ /********************************************************************** ** 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 "documentlist.h" #include "serverinterface.h" #include "mediadlg.h" +/* OPIE */ #include <opie2/oglobal.h> - +#include <opie2/odebug.h> #include <qtopia/config.h> #include <qtopia/mimetype.h> #include <qtopia/resource.h> #include <qtopia/private/categories.h> #include <qtopia/qpeapplication.h> #include <qtopia/applnk.h> #include <qtopia/storage.h> #ifdef Q_WS_QWS #include <qtopia/qcopenvelope_qws.h> #endif +using namespace Opie::Core; +/* QT */ #include <qtimer.h> #include <qfileinfo.h> #include <qtextstream.h> #include <qfile.h> #include <qdir.h> #include <qpainter.h> #include <qimage.h> #include <qcopchannel_qws.h> #include <qlistview.h> #include <qlist.h> #include <qpixmap.h> -using namespace Opie::Core; AppLnkSet *DocumentList::appLnkSet = 0; static const int MAX_SEARCH_DEPTH = 10; class DocumentListPrivate : public QObject { Q_OBJECT public: DocumentListPrivate( ServerInterface *gui ); ~DocumentListPrivate(); void initialize(); const QString nextFile(); const DocLnk *iterate(); bool store( DocLnk* dl ); void estimatedPercentScanned(); void appendDocpath(FileSystem*); DocLnkSet dls; QDict<void> reference; QDictIterator<void> *dit; enum { Find, RemoveKnownFiles, MakeUnknownFiles, Done } state; QStringList docPaths; unsigned int docPathsSearched; int searchDepth; QDir *listDirs[MAX_SEARCH_DEPTH]; const QFileInfoList *lists[MAX_SEARCH_DEPTH]; unsigned int listPositions[MAX_SEARCH_DEPTH]; StorageInfo *storage; int tid; ServerInterface *serverGui; bool needToSendAllDocLinks; bool sendAppLnks; bool sendDocLnks; bool scanDocs; }; /* * scandocs will be read from Config */ DocumentList::DocumentList( ServerInterface *serverGui, bool /*scanDocs*/, QObject *parent, const char *name ) : QObject( parent, name ) { appLnkSet = new AppLnkSet( MimeType::appsFolderName() ); d = new DocumentListPrivate( serverGui ); d->needToSendAllDocLinks = false; Config cfg( "Launcher" ); cfg.setGroup( "DocTab" ); d->scanDocs = cfg.readBoolEntry( "Enable", true ); - qDebug( "DocumentList::DocumentList() : scanDocs = %d", d->scanDocs ); + odebug << "DocumentList::DocumentList() : scanDocs = " << d->scanDocs << "" << oendl; QTimer::singleShot( 10, this, SLOT( startInitialScan() ) ); } void DocumentList::startInitialScan() { reloadAppLnks(); reloadDocLnks(); } DocumentList::~DocumentList() { delete appLnkSet; delete d; } void DocumentList::add( const DocLnk& doc ) { if ( d->serverGui && QFile::exists( doc.file() ) ) d->serverGui->documentAdded( doc ); } void DocumentList::start() { resume(); } void DocumentList::pause() { - //qDebug("pause %i", d->tid); + //odebug << "pause " << d->tid << "" << oendl; killTimer( d->tid ); d->tid = 0; } void DocumentList::resume() { if ( d->tid == 0 ) { d->tid = startTimer( 20 ); - //qDebug("resumed %i", d->tid); + //odebug << "resumed " << d->tid << "" << oendl; } } /* void DocumentList::resend() { // Re-emits all the added items to the list (firstly letting everyone know to // clear what they have as it is being sent again) pause(); emit allRemoved(); QTimer::singleShot( 5, this, SLOT( resendWorker() ) ); } void DocumentList::resendWorker() { const QList<DocLnk> &list = d->dls.children(); for ( QListIterator<DocLnk> it( list ); it.current(); ++it ) add( *(*it) ); resume(); } */ void DocumentList::rescan() { - //qDebug("rescan"); + //odebug << "rescan" << oendl; pause(); d->initialize(); resume(); } void DocumentList::timerEvent( QTimerEvent *te ) { if ( te->timerId() == d->tid ) { // Do 3 at a time for (int i = 0; i < 3; i++ ) { const DocLnk *lnk = d->iterate(); if ( lnk ) { add( *lnk ); } else { // stop when done pause(); if ( d->serverGui ) d->serverGui->documentScanningProgress( 100 ); if ( d->needToSendAllDocLinks ) sendAllDocLinks(); break; } } } } void DocumentList::reloadAppLnks() { if ( d->sendAppLnks && d->serverGui ) { d->serverGui->applicationScanningProgress( 0 ); d->serverGui->allApplicationsRemoved(); } delete appLnkSet; appLnkSet = new AppLnkSet( MimeType::appsFolderName() ); if ( d->sendAppLnks && d->serverGui ) { static QStringList prevTypeList; QStringList types = appLnkSet->types(); for ( QStringList::Iterator ittypes=types.begin(); ittypes!=types.end(); ++ittypes) { if ( !(*ittypes).isEmpty() ) { if ( !prevTypeList.contains(*ittypes) ) { QString name = appLnkSet->typeName(*ittypes); QPixmap pm = appLnkSet->typePixmap(*ittypes); QPixmap bgPm = appLnkSet->typeBigPixmap(*ittypes); if (pm.isNull()) { QImage img( Resource::loadImage( "UnknownDocument" ) ); pm = img.smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ); bgPm = img.smoothScale( AppLnk::bigIconSize(), AppLnk::bigIconSize() ); } - //qDebug("adding type %s", (*ittypes).latin1()); + //odebug << "adding type " << (*ittypes) << "" << oendl; // ### our current launcher expects docs tab to be last d->serverGui->typeAdded( *ittypes, name.isNull() ? (*ittypes) : name, pm, bgPm ); } prevTypeList.remove(*ittypes); } } for ( QStringList::Iterator ittypes=prevTypeList.begin(); ittypes!=prevTypeList.end(); ++ittypes) { - //qDebug("removing type %s", (*ittypes).latin1()); + //odebug << "removing type " << (*ittypes) << "" << oendl; d->serverGui->typeRemoved(*ittypes); } prevTypeList = types; } QListIterator<AppLnk> itapp( appLnkSet->children() ); AppLnk* l; while ( (l=itapp.current()) ) { ++itapp; if ( d->sendAppLnks && d->serverGui ) d->serverGui->applicationAdded( l->type(), *l ); } if ( d->sendAppLnks && d->serverGui ) d->serverGui->applicationScanningProgress( 100 ); } void DocumentList::reloadDocLnks() { if ( !d->scanDocs ) return; if ( d->sendDocLnks && d->serverGui ) { d->serverGui->documentScanningProgress( 0 ); d->serverGui->allDocumentsRemoved(); } rescan(); } void DocumentList::linkChanged( QString arg ) { - //qDebug( "linkchanged( %s )", arg.latin1() ); + //odebug << "linkchanged( " << arg << " )" << oendl; if ( arg.isNull() || OGlobal::isAppLnkFileName( arg ) ) { reloadAppLnks(); } else { const QList<DocLnk> &list = d->dls.children(); QListIterator<DocLnk> it( list ); while ( it.current() ) { DocLnk *doc = it.current(); ++it; if ( ( doc->linkFileKnown() && doc->linkFile() == arg ) || ( doc->fileKnown() && doc->file() == arg ) ) { - //qDebug( "found old link" ); + //odebug << "found old link" << oendl; DocLnk* dl = new DocLnk( arg ); // add new one if it exists and matches the mimetype if ( d->store( dl ) ) { // Existing link has been changed, send old link ref and a ref // to the new link - //qDebug( "change case" ); + //odebug << "change case" << oendl; if ( d->serverGui ) d->serverGui->documentChanged( *doc, *dl ); } else { // Link has been removed or doesn't match the mimetypes any more // so we aren't interested in it, so take it away from the list - //qDebug( "removal case" ); + //odebug << "removal case" << oendl; if ( d->serverGui ) d->serverGui->documentRemoved( *doc ); } d->dls.remove( doc ); // remove old link from docLnkSet delete doc; return; } } // Didn't find existing link, must be new DocLnk* dl = new DocLnk( arg ); if ( d->store( dl ) ) { // Add if it's a link we are interested in - //qDebug( "add case" ); + //odebug << "add case" << oendl; add( *dl ); } } } void DocumentList::restoreDone() { reloadAppLnks(); reloadDocLnks(); } void DocumentList::storageChanged() { // ### can implement better reloadAppLnks(); reloadDocLnks(); // ### Optimization opportunity // Could be a bit more intelligent and somehow work out which // mtab entry has changed and then only scan that and add and remove // links appropriately. // rescan(); } void DocumentList::sendAllDocLinks() { if ( d->tid != 0 ) { // We are in the middle of scanning, set a flag so // we do this when we finish our scanning d->needToSendAllDocLinks = true; return; } QString contents; Categories cats; for ( QListIterator<DocLnk> it( d->dls.children() ); it.current(); ++it ) { DocLnk *doc = it.current(); QFileInfo fi( doc->file() ); if ( !fi.exists() ) continue; bool fake = !doc->linkFileKnown(); if ( !fake ) { QFile f( doc->linkFile() ); if ( f.open( IO_ReadOnly ) ) { QTextStream ts( &f ); ts.setEncoding( QTextStream::UnicodeUTF8 ); contents += ts.read(); f.close(); } else fake = TRUE; } if (fake) { contents += "[Desktop Entry]\n"; // No tr contents += "Categories = " + // No tr cats.labels("Document View",doc->categories()).join(";") + "\n"; // No tr contents += "Name = "+doc->name()+"\n"; // No tr contents += "Type = "+doc->type()+"\n"; // No tr } contents += "File = "+doc->file()+"\n"; // No tr // (resolves path) contents += QString("Size = %1\n").arg( fi.size() ); // No tr } - //qDebug( "sending length %d", contents.length() ); + //odebug << "sending length " << contents.length() << "" << oendl; #ifndef QT_NO_COP QCopEnvelope e( "QPE/Desktop", "docLinks(QString)" ); e << contents; #endif - //qDebug( "================ \n\n%s\n\n===============", contents.latin1() ); + //odebug << "================ \n\n" << contents << "\n\n===============" << oendl; d->needToSendAllDocLinks = false; } DocumentListPrivate::DocumentListPrivate( ServerInterface *gui ) { storage = new StorageInfo( this ); serverGui = gui; if ( serverGui ) { sendAppLnks = serverGui->requiresApplications(); sendDocLnks = serverGui->requiresDocuments(); } else { sendAppLnks = false; sendDocLnks = false; } for ( int i = 0; i < MAX_SEARCH_DEPTH; i++ ) { listDirs[i] = 0; lists[i] = 0; listPositions[i] = 0; } initialize(); tid = 0; } void DocumentListPrivate::appendDocpath(FileSystem*fs) { QDir defPath(fs->path()+"/Documents"); QFileInfo f(fs->path()+"/.opiestorage.cf"); if (!f.exists()) { Mediadlg dlg(fs); if (QDialog::Accepted != QPEApplication::execDialog( &dlg )) { return; } } Config conf(f.filePath(), Config::File ); conf.setGroup("main"); if (!conf.readBoolEntry("check",false)) { return; } conf.setGroup("subdirs"); bool read_all = conf.readBoolEntry("wholemedia",true); if (read_all) { docPaths+=fs->path(); return; } QStringList subDirs = conf.readListEntry("subdirs",':'); if (subDirs.isEmpty()) { if (defPath.exists()) { docPaths+=defPath.path(); } return; } for (unsigned c = 0; c < subDirs.count();++c) { QDir docDir(QString(fs->path()+"/"+subDirs[c])); if (docDir.exists()) { docPaths+=docDir.path(); } } } void DocumentListPrivate::initialize() { // Reset dls.clear(); docPaths.clear(); reference.clear(); QDir docDir( QPEApplication::documentDir() ); if ( docDir.exists() ) docPaths += QPEApplication::documentDir(); int i = 1; const QList<FileSystem> &fs = storage->fileSystems(); QListIterator<FileSystem> it( fs ); for ( ; it.current(); ++it ) { if ( (*it)->isRemovable() ) { appendDocpath((*it)); ++i; } } for ( int i = 0; i < MAX_SEARCH_DEPTH; ++i ) { if ( listDirs[i] ) { delete listDirs[i]; listDirs[i] = 0; } lists[i] = 0; listPositions[i] = 0; } docPathsSearched = 0; searchDepth = -1; state = Find; dit = 0; } DocumentListPrivate::~DocumentListPrivate() { for ( int i = 0; i < MAX_SEARCH_DEPTH; i++ ) if ( listDirs[i] ) delete listDirs[i]; delete dit; } void DocumentListPrivate::estimatedPercentScanned() { double overallProgress = 0.0; double levelWeight = 75.0; int topCount = docPaths.count(); if ( topCount > 1 ) { levelWeight = levelWeight / topCount; overallProgress += (docPathsSearched - 1) * levelWeight; } for ( int d = 0; d <= searchDepth; d++ ) { if ( listDirs[d] ) { int items = lists[d]->count(); if ( items > 1 ) { levelWeight = levelWeight / items; // Take in to account "." and ".." overallProgress += (listPositions[d] - 3) * levelWeight; } } else { break; } } - // qDebug( "overallProgress: %f", overallProgress ); + // odebug << "overallProgress: " << overallProgress << "" << oendl; if ( serverGui ) serverGui->documentScanningProgress( (int)overallProgress ); } const QString DocumentListPrivate::nextFile() { while ( TRUE ) { while ( searchDepth < 0 ) { // go to next base path if ( docPathsSearched >= docPaths.count() ) { // end of base paths return QString::null; } else { QDir dir( docPaths[docPathsSearched] ); - // qDebug("now using base path: %s", docPaths[docPathsSearched].latin1() ); + // odebug << "now using base path: " << docPaths[docPathsSearched] << "" << oendl; docPathsSearched++; if ( !dir.exists( ".Qtopia-ignore" ) ) { listDirs[0] = new QDir( dir ); lists[0] = listDirs[0]->entryInfoList(); listPositions[0] = 0; searchDepth = 0; } } } const QFileInfoList *fil = lists[searchDepth]; if (!fil) { return QString::null; } QFileInfoList *fl = (QFileInfoList *)fil; unsigned int pos = listPositions[searchDepth]; if ( pos >= fl->count() ) { // go up a depth delete listDirs[searchDepth]; listDirs[searchDepth] = 0; lists[searchDepth] = 0; listPositions[searchDepth] = 0; searchDepth--; } else { const QFileInfo *fi = fl->at(pos); listPositions[searchDepth]++; QString bn = fi->fileName(); if ( bn[0] != '.' ) { if ( fi->isDir() ) { if ( bn != "CVS" && bn != "Qtopia" && bn != "QtPalmtop" ) { // go down a depth QDir dir( fi->filePath() ); - // qDebug("now going in to path: %s", bn.latin1() ); + // odebug << "now going in to path: " << bn << "" << oendl; if ( !dir.exists( ".Qtopia-ignore" ) ) { if ( searchDepth < MAX_SEARCH_DEPTH - 1) { searchDepth++; listDirs[searchDepth] = new QDir( dir ); lists[searchDepth] = listDirs[searchDepth]->entryInfoList(); listPositions[searchDepth] = 0; } } } } else { estimatedPercentScanned(); return fl->at(pos)->filePath(); } } } } return QString::null; } bool DocumentListPrivate::store( DocLnk* dl ) { // if ( dl->fileKnown() && !dl->file().isEmpty() ) { if ( dl && dl->fileKnown() ) { dls.add( dl ); // store return TRUE; } // don't store - delete delete dl; return FALSE; } #define MAGIC_NUMBER ((void*)2) const DocLnk *DocumentListPrivate::iterate() { if ( state == Find ) { - //qDebug("state Find"); + //odebug << "state Find" << oendl; QString file = nextFile(); while ( !file.isNull() ) { if ( file.right(8) == ".desktop" ) { // No tr DocLnk* dl = new DocLnk( file ); if ( store(dl) ) return dl; } else { reference.insert( file, MAGIC_NUMBER ); } file = nextFile(); } state = RemoveKnownFiles; if ( serverGui ) serverGui->documentScanningProgress( 75 ); } static int iterationI; static int iterationCount; if ( state == RemoveKnownFiles ) { - //qDebug("state RemoveKnownFiles"); + //odebug << "state RemoveKnownFiles" << oendl; const QList<DocLnk> &list = dls.children(); for ( QListIterator<DocLnk> it( list ); it.current(); ++it ) { reference.remove( (*it)->file() ); // ### does this need to be deleted? } dit = new QDictIterator<void>(reference); state = MakeUnknownFiles; iterationI = 0; iterationCount = dit->count(); } if ( state == MakeUnknownFiles ) { - //qDebug("state MakeUnknownFiles"); + //odebug << "state MakeUnknownFiles" << oendl; for (void* c; (c=dit->current()); ++(*dit) ) { if ( c == MAGIC_NUMBER ) { DocLnk* dl = new DocLnk; QFileInfo fi( dit->currentKey() ); dl->setFile( fi.filePath() ); dl->setName( fi.baseName() ); if ( store(dl) ) { ++*dit; iterationI++; if ( serverGui ) serverGui->documentScanningProgress( 75 + (25*iterationI)/iterationCount ); return dl; } } iterationI++; } delete dit; dit = 0; state = Done; } - //qDebug("state Done"); + //odebug << "state Done" << oendl; return NULL; } #include "documentlist.moc" diff --git a/core/launcher/firstuse.cpp b/core/launcher/firstuse.cpp index 4316648..e9e2d83 100644 --- a/core/launcher/firstuse.cpp +++ b/core/launcher/firstuse.cpp @@ -1,513 +1,515 @@ /********************************************************************** ** 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. ** **********************************************************************/ // I need access to some things you don't normally get access to. #ifndef _MSC_VER //### revise to allow removal of translators under MSVC #define private public #define protected public #endif #include "firstuse.h" #include "inputmethods.h" #include "applauncher.h" #include "serverapp.h" -//#include <qtopia/custom.h> - #include "calibrate.h" #include "documentlist.h" +/* OPIE */ +#include <opie2/odebug.h> #include <qtopia/resource.h> #include <qtopia/qcopenvelope_qws.h> #include <qtopia/config.h> #include <qtopia/fontmanager.h> +using namespace Opie::Core; +/* QT */ #include <qfile.h> #include <qpainter.h> #include <qsimplerichtext.h> #include <qpushbutton.h> #include <qlabel.h> #include <qtimer.h> #if defined( Q_WS_QWS ) #include <qwsdisplay_qws.h> #include <qgfx_qws.h> #endif - +/* STD */ #include <stdlib.h> #include <sys/types.h> #if defined(Q_OS_LINUX) || defined(_OS_LINUX_) #include <unistd.h> #endif struct { bool enabled; const char *app; const char *start; const char *stop; const char *desc; } settingsTable [] = { { FALSE, "language", "raise()", "accept()", // No tr QT_TR_NOOP("Language") }, { FALSE, "doctab", "raise()", "accept()", // No tr QT_TR_NOOP("DocTab") }, #ifndef Q_OS_WIN32 { FALSE, "systemtime", "raise()", "accept()", // No tr QT_TR_NOOP("Time and Date") }, #endif { FALSE, "addressbook", "editPersonalAndClose()", "accept()", // No tr QT_TR_NOOP("Personal Information") }, { FALSE, 0, 0, 0, 0 } }; FirstUse::FirstUse(QWidget* parent, const char * name, WFlags wf) : QDialog( parent, name, TRUE, wf), transApp(0), transLib(0), needCalibrate(FALSE), currApp(-1), waitForExit(-1), waitingForLaunch(FALSE), needRestart(FALSE) { ServerApplication::allowRestart = FALSE; // we force our height beyound the maximum (which we set anyway) QRect desk = qApp->desktop()->geometry(); setGeometry( 0, 0, desk.width(), desk.height() ); connect(qwsServer, SIGNAL(newChannel(const QString&)), this, SLOT(newQcopChannel(const QString&))); // Create a DocumentList so appLauncher has appLnkSet to search docList = new DocumentList( 0, FALSE ); appLauncher = new AppLauncher( this ); connect( appLauncher, SIGNAL(terminated(int,const QString&)), this, SLOT(terminated(int,const QString&)) ); // more hackery // I will be run as either the main server or as part of the main server QWSServer::setScreenSaverIntervals(0); loadPixmaps(); //check if there is a language program #ifndef Q_OS_WIN32 QString exeSuffix; #else QString exeSuffix(".exe"); #endif for ( int i = 0; settingsTable[i].app; i++ ) { QString file = QPEApplication::qpeDir() + "bin/"; file += settingsTable[i].app; file += exeSuffix; if ( QFile::exists(file) ) settingsTable[i].enabled = TRUE; } setFocusPolicy(NoFocus); taskBar = new QWidget(0, 0, WStyle_Tool | WStyle_Customize | WStyle_StaysOnTop | WGroupLeader); inputMethods = new InputMethods(taskBar); connect(inputMethods, SIGNAL(inputToggled(bool)), this, SLOT(calcMaxWindowRect())); back = new QPushButton(tr("<< Back"), taskBar); back->setFocusPolicy(NoFocus); connect(back, SIGNAL(clicked()), this, SLOT(previousDialog()) ); next = new QPushButton(tr("Next >>"), taskBar); next->setFocusPolicy(NoFocus); connect(next, SIGNAL(clicked()), this, SLOT(nextDialog()) ); // need to set the geom to lower corner QSize sz = inputMethods->sizeHint(); int buttonWidth = (width() - sz.width()) / 2; int x = 0; controlHeight = back->sizeHint().height(); inputMethods->setGeometry(0,0, sz.width(), controlHeight ); x += sz.width(); back->setGeometry(x, 0, buttonWidth, controlHeight); x += buttonWidth; next->setGeometry(x, 0, buttonWidth, controlHeight); taskBar->setGeometry( 0, height() - controlHeight, desk.width(), controlHeight); taskBar->hide(); #if defined(Q_WS_QWS) && !defined(QT_NO_COP) - qDebug("Setting up QCop to QPE/System"); + odebug << "Setting up QCop to QPE/System" << oendl; QCopChannel* sysChannel = new QCopChannel( "QPE/System", this ); connect(sysChannel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(message(const QCString&,const QByteArray&)) ); #endif calcMaxWindowRect(); m_calHandler = ( QWSServer::mouseHandler() && QWSServer::mouseHandler()->inherits("QCalibratedMouseHandler") ) ? true : false; if ( m_calHandler) { if ( !QFile::exists("/etc/pointercal") ) { needCalibrate = TRUE; grabMouse(); } } Config config("locale"); config.setGroup( "Language"); lang = config.readEntry( "Language", "en"); defaultFont = font(); //###language/font hack; should look it up somewhere #ifdef Q_WS_QWS if ( lang == "ja" || lang == "zh_CN" || lang == "zh_TW" || lang == "ko" ) { QFont fn = FontManager::unicodeFont( FontManager::Proportional ); qApp->setFont( fn, TRUE ); } #endif } FirstUse::~FirstUse() { delete appLauncher; delete docList; delete taskBar; ServerApplication::allowRestart = TRUE; } void FirstUse::calcMaxWindowRect() { #ifdef Q_WS_QWS QRect wr; int displayWidth = qApp->desktop()->width(); QRect ir = inputMethods->inputRect(); if ( ir.isValid() ) { wr.setCoords( 0, 0, displayWidth-1, ir.top()-1 ); } else { wr.setCoords( 0, 0, displayWidth-1, qApp->desktop()->height() - controlHeight-1); } #if QT_VERSION < 0x030000 QWSServer::setMaxWindowRect( qt_screen->mapToDevice(wr, QSize(qt_screen->width(),qt_screen->height())) ); #else QWSServer::setMaxWindowRect( wr ); #endif #endif } /* cancel current dialog, and bring up next */ void FirstUse::nextDialog() { int prevApp = currApp; do { currApp++; - qDebug( "currApp = %d", currApp ); + odebug << "currApp = " << currApp << "" << oendl; if ( settingsTable[currApp].app == 0 ) { if ( prevApp >= 0 && appLauncher->isRunning(settingsTable[prevApp].app) ) { // The last application is still running. // Tell it to stop, and when its done we'll come back // to nextDialog and exit. - qDebug( "Waiting for %s to exit", settingsTable[prevApp].app ); + odebug << "Waiting for " << settingsTable[prevApp].app << " to exit" << oendl; QCopEnvelope e(QCString("QPE/Application/") + settingsTable[prevApp].app, settingsTable[prevApp].stop ); currApp = prevApp; } else { - qDebug( "Done!" ); + odebug << "Done!" << oendl; Config config( "qpe" ); config.setGroup( "Startup" ); config.writeEntry( "FirstUse", FALSE ); QPixmap pix = Resource::loadPixmap("bigwait"); QLabel *lblWait = new QLabel(0, "wait hack!", // No tr QWidget::WStyle_Customize | QWidget::WDestructiveClose | QWidget::WStyle_NoBorder | QWidget::WStyle_Tool | QWidget::WStyle_StaysOnTop); lblWait->setPixmap( pix ); lblWait->setAlignment( QWidget::AlignCenter ); lblWait->setGeometry( qApp->desktop()->geometry() ); lblWait->show(); qApp->processEvents(); QTimer::singleShot( 1000, lblWait, SLOT(close()) ); repaint(); close(); ServerApplication::allowRestart = TRUE; } return; } } while ( !settingsTable[currApp].enabled ); if ( prevApp >= 0 && appLauncher->isRunning(settingsTable[prevApp].app) ) { - qDebug( "Shutdown: %s", settingsTable[prevApp].app ); + odebug << "Shutdown: " << settingsTable[prevApp].app << "" << oendl; QCopEnvelope e(QCString("QPE/Application/") + settingsTable[prevApp].app, settingsTable[prevApp].stop ); waitForExit = prevApp; } else { - qDebug( "Startup: %s", settingsTable[currApp].app ); + odebug << "Startup: " << settingsTable[currApp].app << "" << oendl; QCopEnvelope e(QCString("QPE/Application/") + settingsTable[currApp].app, settingsTable[currApp].start ); waitingForLaunch = TRUE; } updateButtons(); } /* accept current dialog and bring up previous */ void FirstUse::previousDialog() { int prevApp = currApp; do { currApp--; if ( currApp < 0 ) { currApp = prevApp; return; } } while ( !settingsTable[currApp].enabled ); if ( prevApp >= 0 ) { - qDebug( "Shutdown: %s", settingsTable[prevApp].app ); + odebug << "Shutdown: " << settingsTable[prevApp].app << "" << oendl; QCopEnvelope e(QCString("QPE/Application/") + settingsTable[prevApp].app, settingsTable[prevApp].stop ); /* if (settingsTable[prevApp].app == QString("systemtime")) QCopEnvelope e("QPE/Application/citytime", "close()"); */ waitForExit = prevApp; } else { - qDebug( "Startup: %s", settingsTable[currApp].app ); + odebug << "Startup: " << settingsTable[currApp].app << "" << oendl; QCopEnvelope e(QCString("QPE/Application/") + settingsTable[currApp].app, settingsTable[currApp].start ); waitingForLaunch = TRUE; } updateButtons(); } void FirstUse::message(const QCString &msg, const QByteArray &data) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "timeChange(QString)" ) { QString t; stream >> t; if ( t.isNull() ) unsetenv("TZ"); else setenv( "TZ", t.latin1(), 1 ); } } void FirstUse::terminated( int, const QString &app ) { - qDebug( "--- terminated: %s", app.latin1() ); + odebug << "--- terminated: " << app << "" << oendl; if ( waitForExit != -1 && settingsTable[waitForExit].app == app ) { - qDebug( "Startup: %s", settingsTable[currApp].app ); + odebug << "Startup: " << settingsTable[currApp].app << "" << oendl; if ( settingsTable[waitForExit].app == "language" ) { // No tr Config config("locale"); config.setGroup( "Language"); QString l = config.readEntry( "Language", "en"); if ( l != lang ) { reloadLanguages(); needRestart = TRUE; lang = l; } } QCopEnvelope e(QCString("QPE/Application/") + settingsTable[currApp].app, settingsTable[currApp].start ); waitingForLaunch = TRUE; updateButtons(); repaint(); waitForExit = -1; } else if ( settingsTable[currApp].app == app ) { nextDialog(); } else { back->setEnabled(TRUE); next->setEnabled(TRUE); } } void FirstUse::newQcopChannel(const QString& channelName) { - qDebug("channel %s added", channelName.data() ); + odebug << "channel " << channelName.data() << " added" << oendl; QString prefix("QPE/Application/"); if (channelName.startsWith(prefix)) { QString appName = channelName.mid(prefix.length()); if ( currApp >= 0 && appName == settingsTable[currApp].app ) { - qDebug( "Application: %s started", settingsTable[currApp].app ); + odebug << "Application: " << settingsTable[currApp].app << " started" << oendl; waitingForLaunch = FALSE; updateButtons(); repaint(); } else if (appName != "quicklauncher") { back->setEnabled(FALSE); next->setEnabled(FALSE); } } } void FirstUse::reloadLanguages() { // read language from config file. Waiting on QCop takes too long. Config config("locale"); config.setGroup( "Language"); QString l = config.readEntry( "Language", "en"); QString cl = getenv("LANG"); - qWarning("language message - " + l); + owarn << "language message - " + l << oendl; // setting anyway... if (l.isNull() ) unsetenv( "LANG" ); else { - qWarning("and its not null"); + owarn << "and its not null" << oendl; setenv( "LANG", l.latin1(), 1 ); } #ifndef QT_NO_TRANSLATION // clear old translators #ifndef _MSC_VER //### revise to allow removal of translators under MSVC if(qApp->translators) { qApp->translators->setAutoDelete(TRUE); delete (qApp->translators); qApp->translators = 0; } #endif // load translation tables transApp = new QTranslator(qApp); QString tfn = QPEApplication::qpeDir() + "i18n/"+l+"/qpe.qm"; - qWarning("loading " + tfn); + owarn << "loading " + tfn << oendl; if ( transApp->load(tfn) ) { - qWarning("installing translator"); + owarn << "installing translator" << oendl; qApp->installTranslator( transApp ); } else { delete transApp; transApp = 0; } transLib = new QTranslator(qApp); tfn = QPEApplication::qpeDir() + "i18n/"+l+"/libqpe.qm"; - qWarning("loading " + tfn); + owarn << "loading " + tfn << oendl; if ( transLib->load(tfn) ) { - qWarning("installing translator library"); + owarn << "installing translator library" << oendl; qApp->installTranslator( transLib ); } else { delete transLib; transLib = 0; } loadPixmaps(); //###language/font hack; should look it up somewhere #ifdef Q_WS_QWS if ( l == "ja" || l == "zh_CN" || l == "zh_TW" || l == "ko" ) { QFont fn = FontManager::unicodeFont( FontManager::Proportional ); qApp->setFont( fn, TRUE ); } else { qApp->setFont( defaultFont, TRUE ); } #endif #endif } void FirstUse::paintEvent( QPaintEvent * ) { QPainter p( this ); p.drawPixmap(0,0, splash); QFont f = p.font(); f.setPointSize(15); f.setItalic(FALSE); f.setBold(FALSE); p.setFont(f); if ( currApp < 0 ) { drawText(p, tr( "Tap anywhere on the screen to continue." )); } else if ( settingsTable[currApp].app ) { if ( waitingForLaunch ) drawText(p, tr("Please wait, loading %1 settings.").arg(tr(settingsTable[currApp].desc)) ); } else { drawText(p, tr("Please wait...")); } } void FirstUse::loadPixmaps() { /* create background, tr so can change image with language. images will likely contain text. */ splash.convertFromImage( Resource::loadImage(tr("FirstUseBackground")) .smoothScale( width(), height() ) ); setBackgroundPixmap(splash); } void FirstUse::drawText(QPainter &p, const QString &text) { QString altered = "<CENTER>" + text + "</CENTER>"; QSimpleRichText rt(altered, p.font()); rt.setWidth(width() - 20); int h = (height() * 3) / 10; // start at 30% if (rt.height() < height() / 2) h += ((height() / 2) - rt.height()) / 2; rt.draw(&p, 10, h, QRegion(0,0, width()-20, height()), palette()); } void FirstUse::updateButtons() { if ( currApp >= 0 ) { taskBar->show(); } int i = currApp-1; while ( i >= 0 && !settingsTable[i].enabled ) i--; back->setText(tr("<< Back")); back->setEnabled( i >= 0 && !waitingForLaunch ); i = currApp+1; while ( settingsTable[i].app && !settingsTable[i].enabled ) i++; if ( !settingsTable[i].app ) next->setText(tr("Finish")); else next->setText(tr("Next >>")); next->setEnabled( !waitingForLaunch ); } void FirstUse::keyPressEvent( QKeyEvent *e ) { // Allow cancelling at first dialog, in case display is broken. if ( e->key() == Key_Escape && currApp < 0 ) QDialog::keyPressEvent(e); } void FirstUse::mouseReleaseEvent( QMouseEvent * ) { if ( currApp < 0 ) { if ( m_calHandler && needCalibrate ) { releaseMouse(); Calibrate *cal = new Calibrate; cal->exec(); delete cal; } nextDialog(); } } diff --git a/core/launcher/inputmethods.cpp b/core/launcher/inputmethods.cpp index 19e799a..cef16bf 100644 --- a/core/launcher/inputmethods.cpp +++ b/core/launcher/inputmethods.cpp @@ -1,624 +1,620 @@ /********************************************************************** ** 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_LANGLIST #include "inputmethods.h" +/* OPIE */ +#include <opie2/odebug.h> #include <qtopia/config.h> #include <qtopia/qpeapplication.h> +using namespace Opie::Core; +/* QT */ #include <qpopupmenu.h> #include <qtoolbutton.h> #include <qwidgetstack.h> #include <qlayout.h> #include <qdir.h> -#include <stdlib.h> #include <qtl.h> - #ifdef Q_WS_QWS #include <qwindowsystem_qws.h> #include <qwsevent_qws.h> #include <qcopchannel_qws.h> #endif -/* ### SingleFloppy if someone is interested? */ -#if 0 -#ifdef QT_NO_COMPONENT -#include "../plugins/inputmethods/handwriting/handwritingimpl.h" -#include "../plugins/inputmethods/keyboard/keyboardimpl.h" -#include "../3rdparty/plugins/inputmethods/pickboard/pickboardimpl.h" -#endif -#endif +/* STD */ +#include <stdlib.h> /* XPM */ static const char * tri_xpm[]={ "9 9 2 1", "a c #000000", ". c None", ".........", ".........", ".........", "....a....", "...aaa...", "..aaaaa..", ".aaaaaaa.", ".........", "........."}; int InputMethod::operator <(const InputMethod& o) const { return name() < o.name(); } int InputMethod::operator >(const InputMethod& o) const { return name() > o.name(); } int InputMethod::operator <=(const InputMethod& o) const { return name() <= o.name(); } /* Slightly hacky: We use WStyle_Tool as a flag to say "this widget belongs to the IM system, so clicking it should not cause a reset". */ class IMToolButton : public QToolButton { public: IMToolButton::IMToolButton( QWidget *parent ) : QToolButton( parent ) { setWFlags( WStyle_Tool ); } }; InputMethods::InputMethods( QWidget *parent ) : QWidget( parent, "InputMethods", WStyle_Tool | WStyle_Customize ), mkeyboard(0), imethod(0) { Config cfg( "Launcher" ); cfg.setGroup( "InputMethods" ); inputWidgetStyle = QWidget::WStyle_Customize | QWidget::WStyle_StaysOnTop | QWidget::WGroupLeader | QWidget::WStyle_Tool; inputWidgetStyle |= cfg.readBoolEntry( "Float", false ) ? QWidget::WStyle_DialogBorder : 0; inputWidgetWidth = cfg.readNumEntry( "Width", 100 ); setBackgroundMode( PaletteBackground ); QHBoxLayout *hbox = new QHBoxLayout( this ); kbdButton = new IMToolButton( this); kbdButton->setFocusPolicy(NoFocus); kbdButton->setToggleButton( TRUE ); if (parent->sizeHint().height() > 0) kbdButton->setFixedHeight( parent->sizeHint().height() ); kbdButton->setFixedWidth( 32 ); kbdButton->setAutoRaise( TRUE ); kbdButton->setUsesBigPixmap( TRUE ); hbox->addWidget( kbdButton ); connect( kbdButton, SIGNAL(toggled(bool)), this, SLOT(showKbd(bool)) ); kbdChoice = new IMToolButton( this ); kbdChoice->setFocusPolicy(NoFocus); kbdChoice->setPixmap( QPixmap( (const char **)tri_xpm ) ); if (parent->sizeHint().height() > 0) kbdChoice->setFixedHeight( parent->sizeHint().height() ); kbdChoice->setFixedWidth( 13 ); kbdChoice->setAutoRaise( TRUE ); hbox->addWidget( kbdChoice ); connect( kbdChoice, SIGNAL(clicked()), this, SLOT(chooseKbd()) ); connect( (QPEApplication*)qApp, SIGNAL(clientMoused()), this, SLOT(resetStates()) ); imButton = new QWidgetStack( this ); // later a widget stack imButton->setFocusPolicy(NoFocus); if (parent->sizeHint().height() > 0) imButton->setFixedHeight( parent->sizeHint().height() ); hbox->addWidget(imButton); imChoice = new QToolButton( this ); imChoice->setFocusPolicy(NoFocus); imChoice->setPixmap( QPixmap( (const char **)tri_xpm ) ); if (parent->sizeHint().height() > 0) imChoice->setFixedHeight( parent->sizeHint().height() ); imChoice->setFixedWidth( 13 ); imChoice->setAutoRaise( TRUE ); hbox->addWidget( imChoice ); connect( imChoice, SIGNAL(clicked()), this, SLOT(chooseIm()) ); loadInputMethods(); QCopChannel *channel = new QCopChannel( "QPE/IME", this ); connect( channel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(qcopReceive(const QCString&,const QByteArray&)) ); } InputMethods::~InputMethods() { Config cfg("qpe"); cfg.setGroup("InputMethod"); if (imethod) cfg.writeEntry("im", imethod->name() ); if (mkeyboard) cfg.writeEntry("current", mkeyboard->name() ); unloadInputMethods(); } void InputMethods::hideInputMethod() { kbdButton->setOn( FALSE ); } void InputMethods::showInputMethod() { kbdButton->setOn( TRUE ); } void InputMethods::showInputMethod(const QString& name) { int i = 0; QValueList<InputMethod>::Iterator it; InputMethod *im = 0; for ( it = inputMethodList.begin(); it != inputMethodList.end(); ++it, i++ ) { QString lname = (*it).libName.mid((*it).libName.findRev('/') + 1); if ( (*it).name() == name || lname == name ) { im = &(*it); break; } } if ( im ) chooseKeyboard(im); } void InputMethods::resetStates() { if ( mkeyboard && !mkeyboard->newIM ) mkeyboard->interface->resetState(); } QRect InputMethods::inputRect() const { if ( !mkeyboard || !mkeyboard->widget || !mkeyboard->widget->isVisible() ) return QRect(); else return mkeyboard->widget->geometry(); } void InputMethods::unloadInputMethods() { unloadMethod( inputMethodList ); unloadMethod( inputModifierList ); inputMethodList.clear(); inputModifierList.clear(); } void InputMethods::unloadMethod( QValueList<InputMethod>& list ) { QValueList<InputMethod>::Iterator it; for (it = list.begin(); it != list.end(); ++it ) (*it).releaseInterface(); } QStringList InputMethods::plugins()const { QString path = QPEApplication::qpeDir() + "/plugins/inputmethods"; #ifdef Q_OS_MACX QDir dir( path, "lib*.dylib" ); #else QDir dir( path, "lib*.so" ); #endif /* Q_OS_MACX */ return dir.entryList(); } void InputMethods::installTranslator( const QString& type ) { QStringList langs = Global::languageList(); QStringList::ConstIterator lit; for ( lit= langs.begin(); lit!=langs.end(); ++lit) { QString lang = *lit; QTranslator * trans = new QTranslator(qApp); QString tfn = QPEApplication::qpeDir()+"/i18n/"+lang+"/"+type+".qm"; if ( trans->load( tfn )) qApp->installTranslator( trans ); else delete trans; } } void InputMethods::setPreferedHandlers() { Config cfg("qpe"); cfg.setGroup("InputMethod"); QString current = cfg.readEntry("current"); QString im = cfg.readEntry("im"); QValueList<InputMethod>::Iterator it; if (!inputModifierList.isEmpty() && !im.isEmpty() ) { for (it = inputModifierList.begin(); it != inputModifierList.end(); ++it ) if ( (*it).name() == im ) { imethod = &(*it); break; } } if (!inputMethodList.isEmpty() && !current.isEmpty() ) { for (it = inputMethodList.begin(); it != inputMethodList.end(); ++it ) if ( (*it).name() == current ) { - qWarning("preferred keyboard is %s", current.latin1() ); + owarn << "preferred keyboard is " << current << "" << oendl; mkeyboard = &(*it); kbdButton->setPixmap( *mkeyboard->icon() ); break; } } } void InputMethods::loadInputMethods() { #ifndef QT_NO_COMPONENT hideInputMethod(); mkeyboard = 0; unloadInputMethods(); QString path = QPEApplication::qpeDir() + "/plugins/inputmethods"; QStringList list = plugins(); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { InputMethodInterface *iface = 0; ExtInputMethodInterface *eface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if ( lib->queryInterface( IID_InputMethod, (QUnknownInterface**)&iface ) == QS_OK ) { InputMethod input; input.newIM = FALSE; input.library = lib; input.libName = *it; input.interface = iface; input.widget = input.interface->inputMethod( 0, inputWidgetStyle ); input.interface->onKeyPress( this, SLOT(sendKey(ushort,ushort,ushort,bool,bool)) ); inputMethodList.append( input ); } else if ( lib->queryInterface( IID_ExtInputMethod, (QUnknownInterface**)&eface ) == QS_OK ) { InputMethod input; input.newIM = TRUE; input.library = lib; input.libName = *it; input.extInterface = eface; input.widget = input.extInterface->keyboardWidget( 0, inputWidgetStyle ); // may be either a simple, or advanced. if (input.widget) { - //qDebug("its a keyboard"); + //odebug << "its a keyboard" << oendl; inputMethodList.append( input ); } else { - //qDebug("its a real im"); + //odebug << "its a real im" << oendl; input.widget = input.extInterface->statusWidget( 0, 0 ); if (input.widget) { - //qDebug("blah"); + //odebug << "blah" << oendl; inputModifierList.append( input ); imButton->addWidget(input.widget, inputModifierList.count()); } } }else{ delete lib; lib = 0l; } installTranslator( (*it).left( (*it).find(".") ) ); } qHeapSort( inputMethodList ); #endif /* killed BUILT in cause they would not compile */ QWSServer::setCurrentInputMethod( 0 ); /* set the prefered IM + handler */ setPreferedHandlers(); if ( !inputModifierList.isEmpty() ) { if (!imethod) imethod = &inputModifierList[0]; imButton->raiseWidget(imethod->widget); QWSServer::setCurrentInputMethod( imethod->extInterface->inputMethod() ); } else { imethod = 0; } // we need to update keyboards afterwards, as some of them may not be compatible with // the current input method updateKeyboards(imethod); if ( !inputModifierList.isEmpty() ) imButton->show(); else imButton->hide(); if ( inputModifierList.count() > 1 ) imChoice->show(); else imChoice->hide(); } void InputMethods::chooseKbd() { QPopupMenu pop( this ); pop.setFocusPolicy( NoFocus ); //don't reset IM QString imname; if (imethod) imname = imethod->libName.mid(imethod->libName.findRev('/') + 1); int i = 0; int firstDepKbd = 0; QValueList<InputMethod>::Iterator it; for ( it = inputMethodList.begin(); it != inputMethodList.end(); ++it, i++ ) { // add empty new items, all old items. if (!(*it).newIM || (*it).extInterface->compatible().count() == 0 ) { pop.insertItem( (*it).name(), i, firstDepKbd); if ( mkeyboard == &(*it) ) pop.setItemChecked( i, TRUE ); firstDepKbd++; } else if ( (*it).extInterface->compatible().contains(imname)) { // check if we need to insert a sep. if (firstDepKbd == i) pop.insertSeparator(); pop.insertItem( (*it).name(), i, -1); if ( mkeyboard == &(*it) ) pop.setItemChecked( i, TRUE ); } } QPoint pt = mapToGlobal(kbdChoice->geometry().topRight()); QSize s = pop.sizeHint(); pt.ry() -= s.height(); pt.rx() -= s.width(); i = pop.exec( pt ); if ( i == -1 ) return; InputMethod *im = &inputMethodList[i]; chooseKeyboard(im); } void InputMethods::chooseIm() { QPopupMenu pop( this ); int i = 0; QValueList<InputMethod>::Iterator it; for ( it = inputModifierList.begin(); it != inputModifierList.end(); ++it, i++ ) { pop.insertItem( (*it).name(), i ); if ( imethod == &(*it) ) pop.setItemChecked( i, TRUE ); } QPoint pt = mapToGlobal(imChoice->geometry().topRight()); QSize s = pop.sizeHint(); pt.ry() -= s.height(); pt.rx() -= s.width(); i = pop.exec( pt ); if ( i == -1 ) return; InputMethod *im = &inputModifierList[i]; chooseMethod(im); } void InputMethods::chooseKeyboard(InputMethod* im) { if ( im != mkeyboard ) { if ( mkeyboard && mkeyboard->widget->isVisible() ) mkeyboard->widget->hide(); mkeyboard = im; kbdButton->setPixmap( *mkeyboard->icon() ); } if ( !kbdButton->isOn() ) kbdButton->setOn( TRUE ); else showKbd( TRUE ); } static bool keyboardCompatible(InputMethod *keyb, const QString &imname ) { if ( !keyb || !keyb->newIM || !keyb->extInterface->compatible().count() ) return TRUE; if ( keyb->extInterface->compatible().contains(imname) ) return TRUE; return FALSE; } // Updates the display of the soft keyboards available to the current input method void InputMethods::updateKeyboards(InputMethod *im ) { uint count; if ( im ) { QString imname = im->libName.mid(im->libName.findRev('/') + 1); if ( mkeyboard && !keyboardCompatible(mkeyboard, imname) ) { kbdButton->setOn( FALSE ); showKbd( FALSE ); mkeyboard = 0; } count = 0; QValueList<InputMethod>::Iterator it; for ( it = inputMethodList.begin(); it != inputMethodList.end(); ++it ) { if ( keyboardCompatible( &(*it), imname ) ) { if ( !mkeyboard ) { mkeyboard = &(*it); kbdButton->setPixmap( *mkeyboard->icon() ); } count++; } } } else { count = inputMethodList.count(); if ( count && !mkeyboard ) { mkeyboard = &inputMethodList[0]; kbdButton->setPixmap( *mkeyboard->icon() ); } else if (!count){ mkeyboard = 0; //might be redundant } } if ( count > 1 ) kbdChoice->show(); else kbdChoice->hide(); if ( count ) kbdButton->show(); else kbdButton->hide(); } void InputMethods::chooseMethod(InputMethod* im) { if ( im != imethod ) { updateKeyboards( im ); Config cfg("qpe"); cfg.setGroup("InputMethod"); if (im ) cfg.writeEntry("im", im->name() ); if (mkeyboard) cfg.writeEntry("current", mkeyboard->name() ); QWSServer::setCurrentInputMethod( 0 ); imethod = im; if ( imethod && imethod->newIM ) QWSServer::setCurrentInputMethod( imethod->extInterface->inputMethod() ); else QWSServer::setCurrentInputMethod( 0 ); if ( im ) imButton->raiseWidget(im->widget); else imButton->hide(); //### good UI? make sure it is shown again! } } void InputMethods::qcopReceive( const QCString &msg, const QByteArray &data ) { if ( imethod && imethod->newIM ) imethod->extInterface->qcopReceive( msg, data ); } void InputMethods::showKbd( bool on ) { if ( !mkeyboard ) return; if ( on ) { mkeyboard->resetState(); int height = QMIN( mkeyboard->widget->sizeHint().height(), 134 ); int width = qApp->desktop()->width() * (inputWidgetWidth*0.01); int left = 0; int top = mapToGlobal( QPoint() ).y() - height; if ( inputWidgetStyle & QWidget::WStyle_DialogBorder ) { - qDebug( "InputMethods: reading geometry." ); + odebug << "InputMethods: reading geometry." << oendl; Config cfg( "Launcher" ); cfg.setGroup( "InputMethods" ); int l = cfg.readNumEntry( "absX", -1 ); int t = cfg.readNumEntry( "absY", -1 ); int w = cfg.readNumEntry( "absWidth", -1 ); int h = cfg.readNumEntry( "absHeight", -1 ); if ( l > -1 && t > -1 && w > -1 && h > -1 ) { - qDebug( "InputMethods: config values ( %d, %d, %d, %d ) are ok.", l, t, w, h ); + odebug << "InputMethods: config values ( " << l << ", " << t << ", " << w << ", " << h << " ) are ok." << oendl; left = l; top = t; width = w; height = h; } else { - qDebug( "InputMethods: config values are new or not ok." ); + odebug << "InputMethods: config values are new or not ok." << oendl; } } else { - qDebug( "InputMethods: no floating selected." ); + odebug << "InputMethods: no floating selected." << oendl; } mkeyboard->widget->resize( width, height ); mkeyboard->widget->move( left, top ); mkeyboard->widget->show(); mkeyboard->widget->installEventFilter( this ); } else { if ( inputWidgetStyle & QWidget::WStyle_DialogBorder ) { QPoint pos = mkeyboard->widget->pos(); QSize siz = mkeyboard->widget->size(); - qDebug( "InputMethods: saving geometry." ); + odebug << "InputMethods: saving geometry." << oendl; Config cfg( "Launcher" ); cfg.setGroup( "InputMethods" ); cfg.writeEntry( "absX", pos.x() ); cfg.writeEntry( "absY", pos.y() ); cfg.writeEntry( "absWidth", siz.width() ); cfg.writeEntry( "absHeight", siz.height() ); cfg.write(); mkeyboard->widget->removeEventFilter( this ); } mkeyboard->widget->hide(); } emit inputToggled( on ); } bool InputMethods::shown() const { return mkeyboard && mkeyboard->widget->isVisible(); } QString InputMethods::currentShown() const { return mkeyboard && mkeyboard->widget->isVisible() ? mkeyboard->name() : QString::null; } void InputMethods::sendKey( ushort unicode, ushort scancode, ushort mod, bool press, bool repeat ) { #if defined(Q_WS_QWS) QWSServer::sendKeyEvent( unicode, scancode, mod, press, repeat ); #endif } bool InputMethods::eventFilter( QObject* o, QEvent* e ) { if ( e->type() == QEvent::Close ) { ( (QCloseEvent*) e )->ignore(); showKbd( false ); kbdButton->setOn( false ); return true; } return false; } diff --git a/core/launcher/irserver.cpp b/core/launcher/irserver.cpp index a0e9c16..092eb0c 100644 --- a/core/launcher/irserver.cpp +++ b/core/launcher/irserver.cpp @@ -1,76 +1,76 @@ /********************************************************************** ** 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 "irserver.h" +#include "obexinterface.h" +/* OPIE */ +#include <opie2/odebug.h> #include <qtopia/qlibrary.h> #include <qtopia/qpeapplication.h> - -#include "obexinterface.h" - +/* QT */ #include <qdir.h> IrServer::IrServer( QObject *parent, const char *name ) : QObject( parent, name ), obexIface(0) { lib = 0; obexIface = 0; QString path = QPEApplication::qpeDir() + "/plugins/obex/"; #ifdef Q_OS_MACX QDir dir( path, "lib*.dylib" ); #else QDir dir( path, "lib*.so" ); #endif /* Q_OS_MACX */ QStringList list = dir.entryList(); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { QLibrary *trylib = new QLibrary( path + *it ); - //qDebug("trying lib %s", (path + (*it)).latin1() ); + //odebug << "trying lib " << (path + (*it)) << "" << oendl; if ( trylib->queryInterface( IID_ObexInterface, (QUnknownInterface**)&obexIface ) == QS_OK ) { lib = trylib; - //qDebug("found obex lib" ); + //odebug << "found obex lib" << oendl; QString lang = getenv( "LANG" ); QTranslator * trans = new QTranslator(qApp); QString type = (*it).left( (*it).find(".") ); QString tfn = QPEApplication::qpeDir()+"/i18n/"+lang+"/"+type+".qm"; - //qDebug("tr fpr obex: %s", tfn.latin1() ); + //odebug << "tr fpr obex: " << tfn << "" << oendl; if ( trans->load( tfn )) qApp->installTranslator( trans ); else delete trans; break; } else { delete lib; } } if ( !lib ) - qDebug("could not load IR plugin" ); + odebug << "could not load IR plugin" << oendl; } IrServer::~IrServer() { if ( obexIface ) obexIface->release(); delete lib; } diff --git a/core/launcher/launcher.cpp b/core/launcher/launcher.cpp index 5d0c778..bf2287d 100644 --- a/core/launcher/launcher.cpp +++ b/core/launcher/launcher.cpp @@ -1,779 +1,776 @@ /********************************************************************** ** 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 "startmenu.h" +#include "taskbar.h" +#include "serverinterface.h" +#include "launcherview.h" +#include "launcher.h" +#include "server.h" + +/* OPIE */ +#include <opie2/odebug.h> #include <qtopia/global.h> #ifdef Q_WS_QWS #include <qtopia/qcopenvelope_qws.h> #endif #include <qtopia/resource.h> #include <qtopia/applnk.h> #include <qtopia/config.h> #include <qtopia/qpeapplication.h> #include <qtopia/mimetype.h> #include <qtopia/private/categories.h> -//#include <qtopia/custom.h> +#define QTOPIA_INTERNAL_FSLP +#include <qtopia/lnkproperties.h> +/* QT */ #include <qdir.h> #ifdef Q_WS_QWS +#include <qkeyboard_qws.h> #include <qwindowsystem_qws.h> #endif #include <qtimer.h> #include <qcombobox.h> #include <qvbox.h> #include <qlayout.h> #include <qstyle.h> #include <qpushbutton.h> #include <qtabbar.h> #include <qwidgetstack.h> #include <qregexp.h> #include <qmessagebox.h> #include <qframe.h> #include <qpainter.h> #include <qlabel.h> #include <qtextstream.h> #include <qpopupmenu.h> -#include "startmenu.h" -#include "taskbar.h" - -#include "serverinterface.h" -#include "launcherview.h" -#include "launcher.h" -#include "server.h" - -#define QTOPIA_INTERNAL_FSLP -#include <qtopia/lnkproperties.h> +/* STD */ #include <stdlib.h> #include <assert.h> - #if defined(_OS_LINUX_) || defined(Q_OS_LINUX) #include <unistd.h> #include <stdio.h> #include <sys/vfs.h> #include <mntent.h> #endif -#ifdef Q_WS_QWS -#include <qkeyboard_qws.h> -#include <qpe/lnkproperties.h> -#endif - static bool isVisibleWindow( int ); //=========================================================================== LauncherTabWidget::LauncherTabWidget( Launcher* parent ) : QVBox( parent ), docview( 0 ) { docLoadingWidgetEnabled = false; docLoadingWidget = 0; docLoadingWidgetProgress = 0; launcher = parent; categoryBar = new LauncherTabBar( this ); QPalette pal = categoryBar->palette(); pal.setColor( QColorGroup::Light, pal.color(QPalette::Active,QColorGroup::Shadow) ); pal.setColor( QColorGroup::Background, pal.active().background().light(110) ); categoryBar->setPalette( pal ); stack = new QWidgetStack(this); connect( categoryBar, SIGNAL(selected(int)), this, SLOT(raiseTabWidget()) ); categoryBar->show(); stack->show(); #if defined(Q_WS_QWS) && !defined(QT_NO_COP) QCopChannel *channel = new QCopChannel( "QPE/Launcher", this ); connect( channel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(launcherMessage(const QCString&,const QByteArray&)) ); connect( qApp, SIGNAL(appMessage(const QCString&,const QByteArray&)), this, SLOT(appMessage(const QCString&,const QByteArray&))); #endif createDocLoadingWidget(); } void LauncherTabWidget::createDocLoadingWidget() { // Construct the 'doc loading widget' shown when finding documents // ### LauncherView class needs changing to be more generic so // this widget can change its background similar to the iconviews // so the background for this matches docLoadingWidget = new LauncherView( stack ); docLoadingWidget->hideIcons(); QVBox *docLoadingVBox = new QVBox( docLoadingWidget ); docLoadingVBox->setSpacing( 20 ); docLoadingVBox->setMargin( 10 ); QWidget *space1 = new QWidget( docLoadingVBox ); docLoadingVBox->setStretchFactor( space1, 1 ); QLabel *waitPixmap = new QLabel( docLoadingVBox ); waitPixmap->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, waitPixmap->sizePolicy().hasHeightForWidth() ) ); waitPixmap->setPixmap( Resource::loadPixmap( "bigwait" ) ); waitPixmap->setAlignment( int( QLabel::AlignCenter ) ); Config cfg( "Launcher" ); cfg.setGroup( "DocTab" ); bool docTabEnabled = cfg.readBoolEntry( "Enable", true ); QLabel *textLabel = new QLabel( docLoadingVBox ); textLabel->setAlignment( int( QLabel::AlignCenter ) ); docLoadingWidgetProgress = new QProgressBar( docLoadingVBox ); docLoadingWidgetProgress->setProgress( 0 ); docLoadingWidgetProgress->setCenterIndicator( TRUE ); docLoadingWidgetProgress->setBackgroundMode( NoBackground ); // No flicker setProgressStyle(); if ( docTabEnabled ) { textLabel->setText( tr( "<b>Finding Documents...</b>" ) ); } else { textLabel->setText( tr( "<b>The Documents Tab<p>has been disabled.<p>" "Use Settings->Launcher->DocTab<p>to reenable it.</b></center>" ) ); docLoadingWidgetProgress->hide(); docLoadingWidgetEnabled = true; } QWidget *space2 = new QWidget( docLoadingVBox ); docLoadingVBox->setStretchFactor( space2, 1 ); cfg.setGroup( "Tab Documents" ); // No tr setTabViewAppearance( docLoadingWidget, cfg ); stack->addWidget( docLoadingWidget, 0 ); } void LauncherTabWidget::initLayout() { layout()->activate(); docView()->setFocus(); categoryBar->showTab("Documents"); } void LauncherTabWidget::appMessage(const QCString& message, const QByteArray&) { if ( message == "nextView()" ) categoryBar->nextTab(); } void LauncherTabWidget::raiseTabWidget() { if ( categoryBar->currentView() == docView() && docLoadingWidgetEnabled ) { stack->raiseWidget( docLoadingWidget ); docLoadingWidget->updateGeometry(); } else { stack->raiseWidget( categoryBar->currentView() ); } } void LauncherTabWidget::tabProperties() { LauncherView *view = categoryBar->currentView(); QPopupMenu *m = new QPopupMenu( this ); m->insertItem( tr("Icon View"), LauncherView::Icon ); m->insertItem( tr("List View"), LauncherView::List ); m->setItemChecked( (int)view->viewMode(), TRUE ); int rv = m->exec( QCursor::pos() ); if ( rv >= 0 && rv != view->viewMode() ) { view->setViewMode( (LauncherView::ViewMode)rv ); } delete m; } void LauncherTabWidget::deleteView( const QString& id ) { LauncherTab *t = categoryBar->launcherTab(id); if ( t ) { stack->removeWidget( t->view ); delete t->view; categoryBar->removeTab( t ); } } LauncherView* LauncherTabWidget::newView( const QString& id, const QPixmap& pm, const QString& label ) { LauncherView* view = new LauncherView( stack ); connect( view, SIGNAL(clicked(const AppLnk*)), this, SIGNAL(clicked(const AppLnk*))); connect( view, SIGNAL(rightPressed(AppLnk*)), this, SIGNAL(rightPressed(AppLnk*))); int n = categoryBar->count(); stack->addWidget( view, n ); LauncherTab *tab = new LauncherTab( id, view, pm, label ); categoryBar->insertTab( tab, n-1 ); if ( id == "Documents" ) docview = view; - qDebug("inserting %s at %d", id.latin1(), n-1 ); + odebug << "inserting " << id << " at " << n-1 << "" << oendl; Config cfg("Launcher"); setTabAppearance( tab, cfg ); cfg.setGroup( "GUI" ); view->setBusyIndicatorType( cfg.readEntry( "BusyType", QString::null ) ); return view; } LauncherView *LauncherTabWidget::view( const QString &id ) { LauncherTab *t = categoryBar->launcherTab(id); if ( !t ) return 0; return t->view; } LauncherView *LauncherTabWidget::docView() { return docview; } void LauncherTabWidget::setLoadingWidgetEnabled( bool v ) { if ( v != docLoadingWidgetEnabled && docLoadingWidget ) { docLoadingWidgetEnabled = v; raiseTabWidget(); } } void LauncherTabWidget::setLoadingProgress( int percent ) { docLoadingWidgetProgress->setProgress( (percent / 4) * 4 ); } // ### this function could more to LauncherView void LauncherTabWidget::setTabViewAppearance( LauncherView *v, Config &cfg ) { // View QString view = cfg.readEntry( "View", "Icon" ); if ( view == "List" ) // No tr v->setViewMode( LauncherView::List ); QString bgType = cfg.readEntry( "BackgroundType", "Image" ); if ( bgType == "Image" ) { // No tr QString pm = cfg.readEntry( "BackgroundImage", "launcher/opie-background" ); v->setBackgroundType( LauncherView::Image, pm ); } else if ( bgType == "SolidColor" ) { QString c = cfg.readEntry( "BackgroundColor" ); v->setBackgroundType( LauncherView::SolidColor, c ); } else { v->setBackgroundType( LauncherView::Ruled, QString::null ); } QString textCol = cfg.readEntry( "TextColor" ); if ( textCol.isEmpty() ) v->setTextColor( QColor() ); else v->setTextColor( QColor(textCol) ); // bool customFont = cfg.readBoolEntry( "CustomFont", FALSE ); QStringList font = cfg.readListEntry( "Font", ',' ); if ( font.count() == 4 ) v->setViewFont( QFont(font[0], font[1].toInt(), font[2].toInt(), font[3].toInt()!=0) ); // ### FIXME TabColor TabTextColor } // ### Could move to LauncherTab void LauncherTabWidget::setTabAppearance( LauncherTab *tab, Config &cfg ) { cfg.setGroup( QString( "Tab %1" ).arg(tab->type) ); // No tr setTabViewAppearance( tab->view, cfg ); // Tabs QString tabCol = cfg.readEntry( "TabColor" ); if ( tabCol.isEmpty() ) tab->bgColor = QColor(); else tab->bgColor = QColor(tabCol); QString tabTextCol = cfg.readEntry( "TabTextColor" ); if ( tabTextCol.isEmpty() ) tab->fgColor = QColor(); else tab->fgColor = QColor(tabTextCol); } void LauncherTabWidget::paletteChange( const QPalette &p ) { QVBox::paletteChange( p ); QPalette pal = palette(); pal.setColor( QColorGroup::Light, pal.color(QPalette::Active,QColorGroup::Shadow) ); pal.setColor( QColorGroup::Background, pal.active().background().light(110) ); categoryBar->setPalette( pal ); categoryBar->update(); } void LauncherTabWidget::styleChange( QStyle & ) { QTimer::singleShot( 0, this, SLOT(setProgressStyle()) ); } void LauncherTabWidget::setProgressStyle() { if (docLoadingWidgetProgress) { docLoadingWidgetProgress->setFrameShape( QProgressBar::Box ); docLoadingWidgetProgress->setFrameShadow( QProgressBar::Plain ); docLoadingWidgetProgress->setMargin( 1 ); docLoadingWidgetProgress->setLineWidth( 1 ); } } void LauncherTabWidget::setBusy(bool on) { if ( on ) currentView()->setBusy(TRUE); else { for ( int i = 0; i < categoryBar->count(); i++ ) { LauncherView *view = ((LauncherTab *)categoryBar->tab(i))->view; view->setBusy( FALSE ); } } } void LauncherTabWidget::setBusyIndicatorType( const QString& str ) { for (int i = 0; i < categoryBar->count(); i++ ) { LauncherView* view = static_cast<LauncherTab*>( categoryBar->tab(i) )->view; view->setBusyIndicatorType( str ); } } LauncherView *LauncherTabWidget::currentView(void) { return (LauncherView*)stack->visibleWidget(); } void LauncherTabWidget::launcherMessage( const QCString &msg, const QByteArray &data) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "setTabView(QString,int)" ) { QString id; stream >> id; int mode; stream >> mode; if ( view(id) ) view(id)->setViewMode( (LauncherView::ViewMode)mode ); } else if ( msg == "setTabBackground(QString,int,QString)" ) { QString id; stream >> id; int mode; stream >> mode; QString pixmapOrColor; stream >> pixmapOrColor; if ( view(id) ) view(id)->setBackgroundType( (LauncherView::BackgroundType)mode, pixmapOrColor ); if ( id == "Documents" ) docLoadingWidget->setBackgroundType( (LauncherView::BackgroundType)mode, pixmapOrColor ); } else if ( msg == "setTextColor(QString,QString)" ) { QString id; stream >> id; QString color; stream >> color; if ( view(id) ) view(id)->setTextColor( QColor(color) ); if ( id == "Documents" ) docLoadingWidget->setTextColor( QColor(color) ); } else if ( msg == "setFont(QString,QString,int,int,int)" ) { QString id; stream >> id; QString fam; stream >> fam; int size; stream >> size; int weight; stream >> weight; int italic; stream >> italic; if ( view(id) ) { if ( !fam.isEmpty() ) { view(id)->setViewFont( QFont(fam, size, weight, italic!=0) ); - qDebug( "setFont: %s, %d, %d, %d", fam.latin1(), size, weight, italic ); + odebug << "setFont: " << fam << ", " << size << ", " << weight << ", " << italic << "" << oendl; } else { view(id)->clearViewFont(); } } }else if ( msg == "setBusyIndicatorType(QString)" ) { QString type; stream >> type; setBusyIndicatorType( type ); }else if ( msg == "home()" ) { if ( isVisibleWindow( static_cast<QWidget*>(parent())->winId() ) ) { if (categoryBar) categoryBar->nextTab(); }else static_cast<QWidget*>(parent())->raise(); } } //--------------------------------------------------------------------------- Launcher::Launcher() : QMainWindow( 0, "PDA User Interface", QWidget::WStyle_Customize | QWidget::WGroupLeader ) { tabs = 0; tb = 0; Config cfg( "Launcher" ); cfg.setGroup( "DocTab" ); docTabEnabled = cfg.readBoolEntry( "Enable", true ); } void Launcher::createGUI() { setCaption( tr("Launcher") ); // we have a pretty good idea how big we'll be setGeometry( 0, 0, qApp->desktop()->width(), qApp->desktop()->height() ); tb = new TaskBar; tabs = new LauncherTabWidget( this ); setCentralWidget( tabs ); ServerInterface::dockWidget( tb, ServerInterface::Bottom ); tb->show(); qApp->installEventFilter( this ); connect( qApp, SIGNAL(symbol()), this, SLOT(toggleSymbolInput()) ); connect( qApp, SIGNAL(numLockStateToggle()), this, SLOT(toggleNumLockState()) ); connect( qApp, SIGNAL(capsLockStateToggle()), this, SLOT(toggleCapsLockState()) ); connect( tb, SIGNAL(tabSelected(const QString&)), this, SLOT(showTab(const QString&)) ); connect( tabs, SIGNAL(selected(const QString&)), this, SLOT(viewSelected(const QString&)) ); connect( tabs, SIGNAL(clicked(const AppLnk*)), this, SLOT(select(const AppLnk*))); connect( tabs, SIGNAL(rightPressed(AppLnk*)), this, SLOT(properties(AppLnk*))); #if defined(Q_WS_QWS) && !defined(QT_NO_COP) QCopChannel* sysChannel = new QCopChannel( "QPE/System", this ); connect( sysChannel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(systemMessage(const QCString&,const QByteArray&)) ); #endif // all documents QImage img( Resource::loadImage( "DocsIcon" ) ); QPixmap pm; pm = img.smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ); // It could add this itself if it handles docs tabs->newView("Documents", pm, tr("Documents") )->setToolsEnabled( TRUE ); QTimer::singleShot( 0, tabs, SLOT( initLayout() ) ); qApp->setMainWidget( this ); QTimer::singleShot( 500, this, SLOT( makeVisible() ) ); } Launcher::~Launcher() { if ( tb ) destroyGUI(); } bool Launcher::requiresDocuments() const { Config cfg( "Launcher" ); cfg.setGroup( "DocTab" ); return cfg.readBoolEntry( "Enable", true ); } void Launcher::makeVisible() { showMaximized(); } void Launcher::destroyGUI() { delete tb; tb = 0; delete tabs; tabs =0; } bool Launcher::eventFilter( QObject*, QEvent *ev ) { #ifdef QT_QWS_CUSTOM if ( ev->type() == QEvent::KeyPress ) { QKeyEvent *ke = (QKeyEvent *)ev; if ( ke->key() == Qt::Key_F11 ) { // menu key QWidget *active = qApp->activeWindow(); if ( active && active->isPopup() ) active->close(); else { Global::terminateBuiltin("calibrate"); // No tr tb->launchStartMenu(); } return TRUE; } } #else Q_UNUSED(ev); #endif return FALSE; } void Launcher::toggleSymbolInput() { tb->toggleSymbolInput(); } void Launcher::toggleNumLockState() { tb->toggleNumLockState(); } void Launcher::toggleCapsLockState() { tb->toggleCapsLockState(); } static bool isVisibleWindow(int wid) { #ifdef Q_WS_QWS const QList<QWSWindow> &list = qwsServer->clientWindows(); QWSWindow* w; for (QListIterator<QWSWindow> it(list); (w=it.current()); ++it) { if ( w->winId() == wid ) return !w->isFullyObscured(); } #endif return FALSE; } void Launcher::viewSelected(const QString& s) { setCaption( s + tr(" - Launcher") ); } void Launcher::showTab(const QString& id) { tabs->categoryBar->showTab(id); raise(); } void Launcher::select( const AppLnk *appLnk ) { if ( appLnk->type() == "Folder" ) { // No tr // Not supported: flat is simpler for the user } else { if ( appLnk->exec().isNull() ) { int i = QMessageBox::information(this,tr("No application"), tr("<p>No application is defined for this document." "<p>Type is %1.").arg(appLnk->type()), tr("OK"), tr("View as text"), 0, 0, 1); /* ### Fixme */ if ( i == 1 ) Global::execute("textedit",appLnk->file()); return; } tabs->setBusy(TRUE); emit executing( appLnk ); appLnk->execute(); } } void Launcher::properties( AppLnk *appLnk ) { if ( appLnk->type() == "Folder" ) { // No tr // Not supported: flat is simpler for the user } else { /* ### libqtopia FIXME also moving docLnks... */ LnkProperties prop(appLnk,0 ); QPEApplication::execDialog( &prop ); } } void Launcher::storageChanged( const QList<FileSystem> &fs ) { // ### update combo boxes if we had a combo box for the storage type } void Launcher::systemMessage( const QCString &msg, const QByteArray &data) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "busy()" ) { tb->startWait(); } else if ( msg == "notBusy(QString)" ) { QString app; stream >> app; tabs->setBusy(FALSE); tb->stopWait(app); } else if (msg == "applyStyle()") { tabs->currentView()->relayout(); } } // These are the update functions from the server void Launcher::typeAdded( const QString& type, const QString& name, const QPixmap& pixmap, const QPixmap& ) { tabs->newView( type, pixmap, name ); ids.append( type ); /* this will be called in applicationScanningProgress with value 100! */ // tb->refreshStartMenu(); static bool first = TRUE; if ( first ) { first = FALSE; tabs->categoryBar->showTab(type); } tabs->view( type )->setUpdatesEnabled( FALSE ); tabs->view( type )->setSortEnabled( FALSE ); } void Launcher::typeRemoved( const QString& type ) { tabs->view( type )->removeAllItems(); tabs->deleteView( type ); ids.remove( type ); /* this will be called in applicationScanningProgress with value 100! */ // tb->refreshStartMenu(); } void Launcher::applicationAdded( const QString& type, const AppLnk& app ) { if ( app.type() == "Separator" ) // No tr return; LauncherView *view = tabs->view( type ); if ( view ) view->addItem( new AppLnk( app ), FALSE ); else qWarning("addAppLnk: No view for type %s. Can't add app %s!", type.latin1(),app.name().latin1() ); MimeType::registerApp( app ); } void Launcher::applicationRemoved( const QString& type, const AppLnk& app ) { LauncherView *view = tabs->view( type ); if ( view ) view->removeLink( app.linkFile() ); else - qWarning("removeAppLnk: No view for %s!", type.latin1() ); + owarn << "removeAppLnk: No view for " << type << "!" << oendl; } void Launcher::allApplicationsRemoved() { MimeType::clear(); for ( QStringList::ConstIterator it=ids.begin(); it!= ids.end(); ++it) tabs->view( (*it) )->removeAllItems(); } void Launcher::documentAdded( const DocLnk& doc ) { tabs->docView()->addItem( new DocLnk( doc ), FALSE ); } void Launcher::showLoadingDocs() { tabs->docView()->hide(); } void Launcher::showDocTab() { if ( tabs->categoryBar->currentView() == tabs->docView() ) tabs->docView()->show(); } void Launcher::documentRemoved( const DocLnk& doc ) { tabs->docView()->removeLink( doc.linkFile() ); } void Launcher::documentChanged( const DocLnk& oldDoc, const DocLnk& newDoc ) { documentRemoved( oldDoc ); documentAdded( newDoc ); } void Launcher::allDocumentsRemoved() { tabs->docView()->removeAllItems(); } void Launcher::applicationStateChanged( const QString& name, ApplicationState state ) { tb->setApplicationState( name, state ); } void Launcher::applicationScanningProgress( int percent ) { switch ( percent ) { case 0: { for ( QStringList::ConstIterator it=ids.begin(); it!= ids.end(); ++it) { tabs->view( (*it) )->setUpdatesEnabled( FALSE ); tabs->view( (*it) )->setSortEnabled( FALSE ); } break; } case 100: { for ( QStringList::ConstIterator it=ids.begin(); it!= ids.end(); ++it) { tabs->view( (*it) )->setUpdatesEnabled( TRUE ); tabs->view( (*it) )->setSortEnabled( TRUE ); } tb->refreshStartMenu(); break; } default: break; } } void Launcher::documentScanningProgress( int percent ) { switch ( percent ) { case 0: { tabs->setLoadingProgress( 0 ); tabs->setLoadingWidgetEnabled( TRUE ); tabs->docView()->setUpdatesEnabled( FALSE ); tabs->docView()->setSortEnabled( FALSE ); break; } case 100: { tabs->docView()->updateTools(); tabs->docView()->setSortEnabled( TRUE ); tabs->docView()->setUpdatesEnabled( TRUE ); tabs->setLoadingWidgetEnabled( FALSE ); break; } default: tabs->setLoadingProgress( percent ); break; } } diff --git a/core/launcher/launcherview.cpp b/core/launcher/launcherview.cpp index 6c7d487..71e8753 100644 --- a/core/launcher/launcherview.cpp +++ b/core/launcher/launcherview.cpp @@ -1,374 +1,377 @@ /********************************************************************** ** 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 "launcherview.h" +/* OPIE */ +#include <opie2/odebug.h> #include <qtopia/qpeapplication.h> #include <qtopia/private/categories.h> #include <qtopia/categoryselect.h> #include <qtopia/mimetype.h> #include <qtopia/resource.h> -//#include <qtopia/private/palmtoprecord.h> +using namespace Opie::Core; +/* QT */ #include <qtimer.h> #include <qfileinfo.h> #include <qiconview.h> #include <qobjectlist.h> // These define how the busy icon is animated and highlighted #define BRIGHTEN_BUSY_ICON //#define ALPHA_FADE_BUSY_ICON //#define USE_ANIMATED_BUSY_ICON_OVERLAY #define BOUNCE_BUSY_ICON class BgPixmap { public: BgPixmap( const QPixmap &p ) : pm(p), ref(1) {} QPixmap pm; int ref; }; static QMap<QString,BgPixmap*> *bgCache = 0; static void cleanup_cache() { QMap<QString,BgPixmap*>::Iterator it = bgCache->begin(); while ( it != bgCache->end() ) { QMap<QString,BgPixmap*>::Iterator curr = it; ++it; delete (*curr); bgCache->remove( curr ); } delete bgCache; bgCache = 0; } class LauncherItem : public QIconViewItem { public: LauncherItem( QIconView *parent, AppLnk* applnk, bool bigIcon=TRUE ); ~LauncherItem(); AppLnk *appLnk() const { return app; } AppLnk *takeAppLnk() { AppLnk* r=app; app=0; return r; } void animateIcon(); void resetIcon(); virtual int compare ( QIconViewItem * i ) const; void paintItem( QPainter *p, const QColorGroup &cg ); void setBusyIndicatorType ( BusyIndicatorType t ) { busyType = t; } protected: bool isBigIcon; int iteration; AppLnk* app; private: void paintAnimatedIcon( QPainter *p ); BusyIndicatorType busyType; }; class LauncherIconView : public QIconView { public: LauncherIconView( QWidget* parent, const char* name=0 ) : QIconView(parent,name), tf(""), cf(0), bsy(0), busyTimer(0), bigIcns(TRUE), bgColor(white) { sortmeth = Name; hidden.setAutoDelete(TRUE); ike = FALSE; calculateGrid( Bottom ); } ~LauncherIconView() { #if 0 // debuggery QListIterator<AppLnk> it(hidden); AppLnk* l; while ((l=it.current())) { ++it; - //qDebug("%p: hidden (should remove)",l); + //odebug << "" << l << ": hidden (should remove)" << oendl; } #endif } QIconViewItem* busyItem() const { return bsy; } #ifdef USE_ANIMATED_BUSY_ICON_OVERLAY QPixmap busyPixmap() const { return busyPix; } #endif void setBigIcons( bool bi ) { bigIcns = bi; #ifdef USE_ANIMATED_BUSY_ICON_OVERLAY busyPix.resize(0,0); #endif } void updateCategoriesAndMimeTypes(); void setBusyIndicatorType ( BusyIndicatorType t ) { busyType = t; } void doAutoScroll() { // We don't want rubberbanding (yet) } void setBusy(bool on) { #ifdef USE_ANIMATED_BUSY_ICON_OVERLAY if ( busyPix.isNull() ) { int size = ( bigIcns ) ? AppLnk::bigIconSize() : AppLnk::smallIconSize(); busyPix.convertFromImage( Resource::loadImage( "busy" ).smoothScale( size * 16, size ) ); } #endif if ( on ) { busyTimer = startTimer( 100 ); } else { if ( busyTimer ) { killTimer( busyTimer ); busyTimer = 0; } } LauncherItem *c = on ? (LauncherItem*)currentItem() : 0; if ( bsy != c ) { LauncherItem *oldBusy = bsy; bsy = c; if ( oldBusy ) { oldBusy->resetIcon(); } if ( bsy ) { bsy->setBusyIndicatorType( busyType ) ; bsy->animateIcon(); } } } bool inKeyEvent() const { return ike; } void keyPressEvent(QKeyEvent* e) { ike = TRUE; if ( e->key() == Key_F33 /* OK button */ || e->key() == Key_Space ) { if ( (e->state() & ShiftButton) ) emit mouseButtonPressed(ShiftButton, currentItem(), QPoint() ); else returnPressed(currentItem()); } QIconView::keyPressEvent(e); ike = FALSE; } void addItem(AppLnk* app, bool resort=TRUE); bool removeLink(const QString& linkfile); QStringList mimeTypes() const; QStringList categories() const; void clear() { mimes.clear(); cats.clear(); QIconView::clear(); hidden.clear(); } void addCatsAndMimes(AppLnk* app) { // QStringList c = app->categories(); // for (QStringList::ConstIterator cit=c.begin(); cit!=c.end(); ++cit) { // cats.replace(*cit,(void*)1); // } QString maj=app->type(); int sl=maj.find('/'); if (sl>=0) { QString k; k = maj.left(12) == "application/" ? maj : maj.left(sl); mimes.replace(k,(void*)1); } } void setBackgroundOrigin( QWidget::BackgroundOrigin ) { } void setBackgroundPixmap( const QPixmap &pm ) { bgPixmap = pm; } void setBackgroundColor( const QColor &c ) { bgColor = c; } void drawBackground( QPainter *p, const QRect &r ) { if ( !bgPixmap.isNull() ) { p->drawTiledPixmap( r, bgPixmap, QPoint( (r.x() + contentsX()) % bgPixmap.width(), (r.y() + contentsY()) % bgPixmap.height() ) ); } else { p->fillRect( r, bgColor ); } } void setItemTextPos( ItemTextPos pos ) { calculateGrid( pos ); QIconView::setItemTextPos( pos ); } void hideOrShowItems(bool resort); void setTypeFilter(const QString& typefilter, bool resort) { tf = QRegExp(typefilter,FALSE,TRUE); hideOrShowItems(resort); } void setCategoryFilter( int catfilter, bool resort ) { Categories cat; cat.load( categoryFileName() ); QString str; if ( catfilter == -2 ) cf = 0; else cf = catfilter; hideOrShowItems(resort); } enum SortMethod { Name, Date, Type }; void setSortMethod( SortMethod m ) { if ( sortmeth != m ) { sortmeth = m; sort(); } } int compare(const AppLnk* a, const AppLnk* b) { switch (sortmeth) { case Name: return a->name().lower().compare(b->name().lower()); case Date: { QFileInfo fa(a->linkFileKnown() ? a->linkFile() : a->file()); QFileInfo fb(b->linkFileKnown() ? b->linkFile() : b->file()); return fa.lastModified().secsTo(fb.lastModified()); } case Type: return a->type().compare(b->type()); } return 0; } protected: void timerEvent( QTimerEvent *te ) { if ( te->timerId() == busyTimer ) { if ( bsy ) bsy->animateIcon(); } else { QIconView::timerEvent( te ); } } void styleChange( QStyle &old ) { QIconView::styleChange( old ); calculateGrid( itemTextPos() ); } void calculateGrid( ItemTextPos pos ) { int dw = QApplication::desktop()->width(); int viewerWidth = dw-style().scrollBarExtent().width(); if ( pos == Bottom ) { int cols = 3; if ( viewerWidth <= 200 ) cols = 2; else if ( viewerWidth >= 400 ) cols = viewerWidth/96; setSpacing( 4 ); setGridX( (viewerWidth-(cols+1)*spacing())/cols ); setGridY( fontMetrics().height()*2+24 ); } else { int cols = 2; if ( viewerWidth < 150 ) cols = 1; else if ( viewerWidth >= 400 ) cols = viewerWidth/150; setSpacing( 2 ); setGridX( (viewerWidth-(cols+1)*spacing())/cols ); setGridY( fontMetrics().height()+2 ); } } void focusInEvent( QFocusEvent * ) {} void focusOutEvent( QFocusEvent * ) {} private: QList<AppLnk> hidden; QDict<void> mimes; QDict<void> cats; SortMethod sortmeth; QRegExp tf; int cf; LauncherItem* bsy; int busyTimer; bool ike; bool bigIcns; QPixmap bgPixmap; QColor bgColor; #ifdef USE_ANIMATED_BUSY_ICON_OVERLAY QPixmap busyPix; #endif BusyIndicatorType busyType; }; bool LauncherView::bsy=FALSE; void LauncherView::setBusy(bool on) { icons->setBusy(on); } void LauncherView::setBusyIndicatorType( const QString& type ) { if ( type. lower ( ) == "animated" ) icons->setBusyIndicatorType( BIT_Animated ) ; else icons->setBusyIndicatorType( BIT_Normal ) ; } LauncherItem::LauncherItem( QIconView *parent, AppLnk *applnk, bool bigIcon ) : QIconViewItem( parent, applnk->name(), bigIcon ? applnk->bigPixmap() :applnk->pixmap() ), @@ -776,281 +779,281 @@ QImage LauncherView::loadBackgroundImage(QString &bgName) QImageIO imgio; QSize ds = qApp->desktop()->size(); // should be launcher, not desktop bool further_scaling = TRUE; imgio.setFileName( bgName ); imgio.setParameters("GetHeaderInformation"); if (imgio.read() == FALSE) { return imgio.image(); } if (imgio.image().width() < ds.width() && imgio.image().height() < ds.height()) { further_scaling = FALSE; } if (!imgio.image().bits()) { // // Scale and load. Note we don't scale up. // QString param( "Scale( %1, %2, ScaleMin )" ); // No tr imgio.setParameters(further_scaling ? param.arg(ds.width()).arg(ds.height()).latin1() : ""); imgio.read(); } else { if (further_scaling) { int t1 = imgio.image().width() * ds.height(); int t2 = imgio.image().height() * ds.width(); int dsth = ds.height(); int dstw = ds.width(); if (t1 > t2) { dsth = t2 / imgio.image().width(); } else { dstw = t1 / imgio.image().height(); } // // Loader didn't scale for us. Do it manually. // return imgio.image().smoothScale(dstw, dsth); } } return imgio.image(); } void LauncherView::setBackgroundType( BackgroundType t, const QString &val ) { if ( !bgCache ) { bgCache = new QMap<QString,BgPixmap*>; qAddPostRoutine( cleanup_cache ); } if ( bgCache->contains( bgName ) ) (*bgCache)[bgName]->ref--; bgName = ""; QPixmap bg; switch ( t ) { case Ruled: { bgName = QString("Ruled_%1").arg(colorGroup().background().name()); // No tr if ( bgCache->contains( bgName ) ) { (*bgCache)[bgName]->ref++; bg = (*bgCache)[bgName]->pm; } else { bg.resize( width(), 9 ); QPainter painter( &bg ); for ( int i = 0; i < 3; i++ ) { painter.setPen( white ); painter.drawLine( 0, i*3, width()-1, i*3 ); painter.drawLine( 0, i*3+1, width()-1, i*3+1 ); painter.setPen( colorGroup().background().light(105) ); painter.drawLine( 0, i*3+2, width()-1, i*3+2 ); } painter.end(); bgCache->insert( bgName, new BgPixmap(bg) ); } break; } case Image: if (!val.isEmpty()) { bgName = val; if ( bgCache->contains( bgName ) ) { (*bgCache)[bgName]->ref++; bg = (*bgCache)[bgName]->pm; } else { QString imgFile = bgName; bool tile = FALSE; if ( imgFile[0]!='/' || !QFile::exists(imgFile) ) { imgFile = Resource::findPixmap( imgFile ); tile = TRUE; } QImage img = loadBackgroundImage(imgFile); if ( img.depth() == 1 ) img = img.convertDepth(8); img.setAlphaBuffer(FALSE); bg.convertFromImage(img); bgCache->insert( bgName, new BgPixmap(bg) ); } } break; case SolidColor: default: break; } const QObjectList *list = queryList( "QWidget", 0, FALSE ); QObject *obj; for ( QObjectListIt it( *list ); (obj=it.current()); ++it ) { if ( obj->isWidgetType() ) { QWidget *w = (QWidget*)obj; w->setBackgroundPixmap( bg ); if ( bgName.isEmpty() ) { // Solid Color if ( val.isEmpty() ) w->setBackgroundColor( colorGroup().base() ); else w->setBackgroundColor( val ); } else { // Ruled or Image pixmap w->setBackgroundOrigin( ParentOrigin ); } } } delete list; bgType = t; icons->viewport()->update(); QTimer::singleShot( 1000, this, SLOT(flushBgCache()) ); } void LauncherView::setTextColor( const QColor &tc ) { textCol = tc; QColorGroup cg = icons->colorGroup(); cg.setColor( QColorGroup::Text, tc ); icons->setPalette( QPalette(cg,cg,cg) ); icons->viewport()->update(); } void LauncherView::setViewFont( const QFont &f ) { icons->setFont( f ); icons->hideOrShowItems( FALSE ); } void LauncherView::clearViewFont() { icons->unsetFont(); icons->hideOrShowItems( FALSE ); } void LauncherView::resizeEvent(QResizeEvent *e) { QVBox::resizeEvent( e ); if ( e->size().width() != e->oldSize().width() ) sort(); } void LauncherView::selectionChanged() { QIconViewItem* item = icons->currentItem(); if ( item && item->isSelected() ) { AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); if ( icons->inKeyEvent() ) // not for mouse press emit clicked( appLnk ); item->setSelected(FALSE); } } void LauncherView::returnPressed( QIconViewItem *item ) { if ( item ) { AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); emit clicked( appLnk ); } } void LauncherView::itemClicked( int btn, QIconViewItem *item ) { if ( item ) { AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); if ( btn == LeftButton ) { // Make sure it's the item we execute that gets highlighted icons->setCurrentItem( item ); emit clicked( appLnk ); } item->setSelected(FALSE); } } void LauncherView::itemPressed( int btn, QIconViewItem *item ) { if ( item ) { AppLnk *appLnk = ((LauncherItem *)item)->appLnk(); if ( btn == RightButton ) emit rightPressed( appLnk ); else if ( btn == ShiftButton ) emit rightPressed( appLnk ); item->setSelected(FALSE); } } void LauncherView::removeAllItems() { icons->clear(); } bool LauncherView::removeLink(const QString& linkfile) { return icons->removeLink(linkfile); } void LauncherView::setSortEnabled( bool v ) { icons->setSorting( v ); if ( v ) sort(); } void LauncherView::setUpdatesEnabled( bool u ) { icons->setUpdatesEnabled( u ); } void LauncherView::sort() { icons->sort(); } void LauncherView::addItem(AppLnk* app, bool resort) { icons->addItem(app,resort); } void LauncherView::paletteChange( const QPalette &p ) { icons->unsetPalette(); QVBox::paletteChange( p ); if ( bgType == Ruled ) setBackgroundType( Ruled, QString::null ); QColorGroup cg = icons->colorGroup(); cg.setColor( QColorGroup::Text, textCol ); icons->setPalette( QPalette(cg,cg,cg) ); } void LauncherView::fontChanged(const QFont&) { - qDebug("LauncherView::fontChanged()"); + odebug << "LauncherView::fontChanged()" << oendl; icons->hideOrShowItems( FALSE ); } void LauncherView::relayout(void) { icons->hideOrShowItems(FALSE); } void LauncherView::flushBgCache() { if ( !bgCache ) return; // remove unreferenced backgrounds. QMap<QString,BgPixmap*>::Iterator it = bgCache->begin(); while ( it != bgCache->end() ) { QMap<QString,BgPixmap*>::Iterator curr = it; ++it; if ( (*curr)->ref == 0 ) { delete (*curr); bgCache->remove( curr ); } } } diff --git a/core/launcher/main.cpp b/core/launcher/main.cpp index 3e7e0d2..a86aca6 100644 --- a/core/launcher/main.cpp +++ b/core/launcher/main.cpp @@ -1,352 +1,346 @@ /********************************************************************** ** 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. ** **********************************************************************/ #ifndef QTOPIA_INTERNAL_FILEOPERATIONS #define QTOPIA_INTERNAL_FILEOPERATIONS #endif +#ifdef QT_QWS_LOGIN +#include "../login/qdmdialogimpl.h" +#endif +#include "calibrate.h" #include "server.h" #include "serverapp.h" #include "stabmon.h" #include "firstuse.h" +/* OPIE */ +#include <opie2/odebug.h> +#include <opie2/odevice.h> #include <opie2/oglobal.h> - #include <qtopia/network.h> -//#include <qtopia/custom.h> - +#include <qtopia/alarmserver.h> +using namespace Opie::Core; +/* QT */ #include <qdir.h> +#include <qmessagebox.h> #ifdef QWS #include <qwindowsystem_qws.h> #include <qtopia/qcopenvelope_qws.h> #endif -#include <qtopia/alarmserver.h> +#ifdef Q_WS_QWS +#include <qkeyboard_qws.h> +#endif +/* STD */ #include <stdlib.h> #include <stdio.h> #include <signal.h> #ifndef Q_OS_WIN32 #include <unistd.h> #else #include <process.h> #endif -#include "calibrate.h" - - -#ifdef QT_QWS_LOGIN -#include "../login/qdmdialogimpl.h" -#endif - -#ifdef Q_WS_QWS -#include <qkeyboard_qws.h> -#endif - -#include <qmessagebox.h> -#include <opie2/odevice.h> - -using namespace Opie::Core; - - static void cleanup() { QDir dir( "/tmp", "qcop-msg-*" ); QStringList stale = dir.entryList(); QStringList::Iterator it; for ( it = stale.begin(); it != stale.end(); ++it ) { dir.remove( *it ); } } static void refreshTimeZoneConfig() { /* ### FIXME timezone handling */ #if 0 // We need to help WorldTime in setting up its configuration for // the current translation // BEGIN no tr const char *defaultTz[] = { "America/New_York", "America/Los_Angeles", "Europe/Oslo", "Asia/Tokyo", "Asia/Hong_Kong", "Australia/Brisbane", 0 }; // END no tr TimeZone curZone; QString zoneID; int zoneIndex; Config cfg = Config( "WorldTime" ); cfg.setGroup( "TimeZones" ); if (!cfg.hasKey( "Zone0" )){ // We have no existing timezones use the defaults which are untranslated strings QString currTz = TimeZone::current().id(); QStringList zoneDefaults; zoneDefaults.append( currTz ); for ( int i = 0; defaultTz[i] && zoneDefaults.count() < 6; i++ ) { if ( defaultTz[i] != currTz ) zoneDefaults.append( defaultTz[i] ); } zoneIndex = 0; for (QStringList::Iterator it = zoneDefaults.begin(); it != zoneDefaults.end() ; ++it){ cfg.writeEntry( "Zone" + QString::number( zoneIndex ) , *it); zoneIndex++; } } // We have an existing list of timezones refresh the // translations of TimeZone name zoneIndex = 0; while (cfg.hasKey( "Zone"+ QString::number( zoneIndex ))){ zoneID = cfg.readEntry( "Zone" + QString::number( zoneIndex )); curZone = TimeZone( zoneID ); if ( !curZone.isValid() ){ - qDebug( "initEnvironment() Invalid TimeZone %s", zoneID.latin1() ); + odebug << "initEnvironment() Invalid TimeZone " << zoneID << "" << oendl; break; } cfg.writeEntry( "ZoneName" + QString::number( zoneIndex ), curZone.city() ); zoneIndex++; } #endif } void initEnvironment() { #ifdef Q_OS_WIN32 // Config file requires HOME dir which uses QDir which needs the winver qt_init_winver(); #endif Config config("locale"); config.setGroup( "Location" ); QString tz = config.readEntry( "Timezone", getenv("TZ") ).stripWhiteSpace(); // if not timezone set, pick New York if (tz.isNull() || tz.isEmpty()) tz = "America/New_York"; setenv( "TZ", tz, 1 ); config.writeEntry( "Timezone", tz); config.setGroup( "Language" ); QString lang = config.readEntry( "Language", getenv("LANG") ).stripWhiteSpace(); if( lang.isNull() || lang.isEmpty()) lang = "en_US"; setenv( "LANG", lang, 1 ); config.writeEntry("Language", lang); config.write(); #if 0 setenv( "QWS_SIZE", "240x320", 0 ); #endif QString env(getenv("QWS_DISPLAY")); if (env.contains("Transformed")) { int rot; // transformed driver default rotation is controlled by the hardware. Config config("qpe"); config.setGroup( "Rotation" ); if ( ( rot = config.readNumEntry( "Rot", -1 ) ) == -1 ) rot = ODevice::inst ( )-> rotation ( ) * 90; setenv("QWS_DISPLAY", QString("Transformed:Rot%1:0").arg(rot), 1); QPEApplication::defaultRotation ( ); /* to ensure deforient matches reality */ } } static void initKeyboard() { Config config("qpe"); config.setGroup( "Keyboard" ); int ard = config.readNumEntry( "RepeatDelay" ); int arp = config.readNumEntry( "RepeatPeriod" ); if ( ard > 0 && arp > 0 ) qwsSetKeyboardAutoRepeat( ard, arp ); QString layout = config.readEntry( "Layout", "us101" ); Server::setKeyboardLayout( layout ); } static bool firstUse() { bool needFirstUse = FALSE; if ( QWSServer::mouseHandler() && QWSServer::mouseHandler() ->inherits("QCalibratedMouseHandler") ) { if ( !QFile::exists( "/etc/pointercal" ) ) needFirstUse = TRUE; } { Config config( "qpe" ); config.setGroup( "Startup" ); needFirstUse |= config.readBoolEntry( "FirstUse", TRUE ); } if ( !needFirstUse ) return FALSE; FirstUse *fu = new FirstUse(); fu->exec(); bool rs = fu->restartNeeded(); delete fu; return rs; } int initApplication( int argc, char ** argv ) { cleanup(); initEnvironment(); //Don't flicker at startup: #ifdef QWS QWSServer::setDesktopBackground( QImage() ); #endif ServerApplication a( argc, argv, QApplication::GuiServer ); refreshTimeZoneConfig(); initKeyboard(); // Don't use first use under Windows if ( firstUse() ) { a.restart(); return 0; } ODevice::inst ( )-> setSoftSuspend ( true ); { QCopEnvelope e("QPE/System", "setBacklight(int)" ); e << -3; // Forced on } AlarmServer::initialize(); Server *s = new Server(); (void)new SysFileMonitor(s); #ifdef QWS Network::createServer(s); #endif s->show(); /* THE ARM rtc has problem holdings the time on reset */ if ( QDate::currentDate ( ). year ( ) < 2000 ) { if ( QMessageBox::information ( 0, ServerApplication::tr( "Information" ), ServerApplication::tr( "<p>The system date doesn't seem to be valid.\n(%1)</p><p>Do you want to correct the clock ?</p>" ). arg( TimeString::dateString ( QDate::currentDate ( ))), QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes ) { QCopEnvelope e ( "QPE/Application/systemtime", "setDocument(QString)" ); e << QString ( ); } } int rv = a.exec(); - qDebug("exiting..."); + odebug << "exiting..." << oendl; delete s; #ifndef Q_OS_MACX ODevice::inst()->setSoftSuspend( false ); #endif return rv; } static const char *pidfile_path = "/var/run/opie.pid"; void create_pidfile ( ) { FILE *f; if (( f = ::fopen ( pidfile_path, "w" ))) { ::fprintf ( f, "%d", getpid ( )); ::fclose ( f ); } } void remove_pidfile ( ) { ::unlink ( pidfile_path ); } void handle_sigterm ( int /* sig */ ) { if ( qApp ) qApp-> quit ( ); } #ifndef Q_OS_WIN32 int main( int argc, char ** argv ) { ::signal ( SIGCHLD, SIG_IGN ); ::signal ( SIGTERM, handle_sigterm ); ::signal ( SIGINT, handle_sigterm ); ::setsid ( ); ::setpgid ( 0, 0 ); ::atexit ( remove_pidfile ); create_pidfile ( ); int retVal = initApplication( argc, argv ); // Have we been asked to restart? if ( ServerApplication::doRestart ) { for ( int fd = 3; fd < 100; fd++ ) close( fd ); execl( (QPEApplication::qpeDir()+"bin/qpe").latin1(), "qpe", 0 ); } // Kill them. Kill them all. ::kill ( 0, SIGTERM ); ::sleep ( 1 ); ::kill ( 0, SIGKILL ); return retVal; } #else int main( int argc, char ** argv ) { int retVal = initApplication( argc, argv ); if ( DesktopApplication::doRestart ) { - qDebug("Trying to restart"); + odebug << "Trying to restart" << oendl; execl( (QPEApplication::qpeDir()+"bin\\qpe").latin1(), "qpe", 0 ); } return retVal; } #endif diff --git a/core/launcher/packageslave.cpp b/core/launcher/packageslave.cpp index 7e61b0e..a11ac86 100644 --- a/core/launcher/packageslave.cpp +++ b/core/launcher/packageslave.cpp @@ -1,339 +1,339 @@ /********************************************************************** ** 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 "packageslave.h" -#include <qtopia/qprocess.h> +/* OPIE */ +#include <opie2/odebug.h> +#include <qtopia/qprocess.h> #ifdef Q_WS_QWS #include <qtopia/qcopenvelope_qws.h> #endif +using namespace Opie::Core; +/* QT */ #ifdef Q_WS_QWS #include <qcopchannel_qws.h> #endif - #include <qtextstream.h> +/* STD */ #include <stdlib.h> #include <sys/stat.h> // mkdir() - #if defined(_OS_LINUX_) || defined(Q_OS_LINUX) #include <unistd.h> #include <sys/vfs.h> #include <mntent.h> -#elif defined(Q_OS_WIN32) -#include <windows.h> -#include <winbase.h> #elif defined(Q_OS_MACX) #include <unistd.h> #endif PackageHandler::PackageHandler( QObject *parent, char* name ) : QObject( parent, name ), packageChannel( 0 ), currentProcess( 0 ), mNoSpaceLeft( FALSE ) { // setup qcop channel #ifndef QT_NO_COP packageChannel = new QCopChannel( "QPE/Package", this ); connect( packageChannel, SIGNAL( received(const QCString&,const QByteArray&) ), this, SLOT( qcopMessage(const QCString&,const QByteArray&) ) ); #endif } void PackageHandler::qcopMessage( const QCString &msg, const QByteArray &data ) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "installPackage(QString)" ) { QString file; stream >> file; installPackage( file ); } else if ( msg == "removePackage(QString)" ) { QString file; stream >> file; removePackage( file ); } else if ( msg == "addPackageFiles(QString,QString)" ) { QString location, listfile; stream >> location >> listfile; addPackageFiles( location, listfile); } else if ( msg == "addPackages(QString)" ) { QString location; stream >> location; addPackages( location ); } else if ( msg == "cleanupPackageFiles(QString)" ) { QString listfile; stream >> listfile; cleanupPackageFiles( listfile ); } else if ( msg == "cleanupPackages(QString)" ) { QString location; stream >> location; cleanupPackages( location ); } else if ( msg == "prepareInstall(QString,QString)" ) { QString size, path; stream >> size; stream >> path; prepareInstall( size, path ); } } void PackageHandler::installPackage( const QString &package ) { if ( mNoSpaceLeft ) { mNoSpaceLeft = FALSE; // Don't emit that for now, I still couldn't test it (Wener) //sendReply( "installFailed(QString)", package ); //return; } currentProcess = new QProcess( QStringList() << "ipkg" << "install" << package ); // No tr connect( currentProcess, SIGNAL( processExited() ), SLOT( iProcessExited() ) ); connect( currentProcess, SIGNAL( readyReadStdout() ), SLOT( readyReadStdout() ) ); connect( currentProcess, SIGNAL( readyReadStderr() ), SLOT( readyReadStderr() ) ); currentPackage = package; currentProcessError=""; sendReply( "installStarted(QString)", package ); currentProcess->start(); } void PackageHandler::removePackage( const QString &package ) { currentProcess = new QProcess( QStringList() << "ipkg" << "remove" << package ); // No tr connect( currentProcess, SIGNAL( processExited() ), SLOT( rmProcessExited() ) ); connect( currentProcess, SIGNAL( readyReadStdout() ), SLOT( readyReadStdout() ) ); connect( currentProcess, SIGNAL( readyReadStderr() ), SLOT( readyReadStderr() ) ); currentPackage = package; currentProcessError=""; sendReply( "removeStarted(QString)", package ); currentProcess->start(); } void PackageHandler::sendReply( const QCString& msg, const QString& arg ) { #ifndef QT_NO_COP QCopEnvelope e( "QPE/Desktop", msg ); e << arg; #endif } void PackageHandler::addPackageFiles( const QString &location, const QString &listfile ) { QFile f(listfile); #ifndef Q_OS_WIN32 //make a copy so we can remove the symlinks later mkdir( ("/usr/lib/ipkg/info/"+location).ascii(), 0777 ); system(("cp " + f.name() + " /usr/lib/ipkg/info/"+location).ascii()); #else QDir d; //#### revise - qDebug("Copy file at %s: %s", __FILE__, __LINE__ ); + odebug << "Copy file at " << __FILE__ << ": " << __LINE__ << "" << oendl; d.mkdir(("/usr/lib/ipkg/info/" + location).ascii()); system(("copy " + f.name() + " /usr/lib/ipkg/info/"+location).ascii()); #endif if ( f.open(IO_ReadOnly) ) { QTextStream ts(&f); QString s; while ( !ts.eof() ) { // until end of file... s = ts.readLine(); // line of text excluding '\n' // for s, do link/mkdir. if ( s.right(1) == "/" ) { - qDebug("do mkdir for %s", s.ascii()); + odebug << "do mkdir for " << s.ascii() << "" << oendl; #ifndef Q_OS_WIN32 mkdir( s.ascii(), 0777 ); //possible optimization: symlink directories //that don't exist already. -- Risky. #else d.mkdir( s.ascii()); #endif } else { #ifndef Q_OS_WIN32 - qDebug("do symlink for %s", s.ascii()); + odebug << "do symlink for " << s.ascii() << "" << oendl; symlink( (location + s).ascii(), s.ascii() ); #else - qDebug("Copy file instead of a symlink for WIN32"); + odebug << "Copy file instead of a symlink for WIN32" << oendl; if (!CopyFile((TCHAR*)qt_winTchar((location + s), TRUE), (TCHAR*)qt_winTchar(s, TRUE), FALSE)) qWarning("Unable to create symlinkfor %s", (location + s).ascii()); #endif } } f.close(); } } void PackageHandler::addPackages( const QString &location ) { // get list of *.list in location/usr/lib/ipkg/info/*.list QDir dir(location + "/usr/lib/ipkg/info", "*.list", // No tr QDir::Name, QDir::Files); if ( !dir.exists() ) return; QStringList packages = dir.entryList(); for ( QStringList::Iterator it = packages.begin(); it != packages.end(); ++it ) { addPackageFiles( location, *it ); } } void PackageHandler::cleanupPackageFiles( const QString &listfile ) { QFile f(listfile); if ( f.open(IO_ReadOnly) ) { QTextStream ts(&f); QString s; while ( !ts.eof() ) { // until end of file... s = ts.readLine(); // line of text excluding '\n' // for s, do link/mkdir. if ( s.right(1) == "/" ) { //should rmdir if empty, after all files have been removed } else { #ifndef Q_OS_WIN32 - qDebug("remove symlink for %s", s.ascii()); + odebug << "remove symlink for " << s.ascii() << "" << oendl; //check if it is a symlink first (don't remove /etc/passwd...) char buf[10]; //we don't care about the contents if ( ::readlink( s.ascii(),buf, 10 >= 0 ) ) ::unlink( s.ascii() ); #else // ### revise - qWarning("Unable to remove symlink %s:%s", __FILE__, __LINE__); + owarn << "Unable to remove symlink " << __FILE__ << ":" << __LINE__ << "" << oendl; #endif } } f.close(); //remove the list file ::unlink( listfile.ascii() ); } } void PackageHandler::cleanupPackages( const QString &location ) { // get list of *.list in location/usr/lib/ipkg/info/*.list QDir dir( "/usr/lib/ipkg/info/"+location, "*.list", // No tr QDir::Name, QDir::Files); if ( !dir.exists() ) return; QStringList packages = dir.entryList(); for ( QStringList::Iterator it = packages.begin(); it != packages.end(); ++it ) { cleanupPackageFiles( *it ); } //remove the backup directory //### } void PackageHandler::prepareInstall( const QString& size, const QString& path ) { // Check whether there will be enough space to install the next package. bool ok; unsigned int s = size.toUInt( &ok ); if ( !ok ) return; // Shamelessly stolen from the sysinfo application (Werner) #if defined(_OS_LINUX_) || defined(Q_OS_LINUX) struct statfs fs; if ( statfs( path.latin1(), &fs ) == 0 ) if ( s > fs.f_bsize * fs.f_bavail ) { - //qDebug("############### Not enough space left ###############"); + //odebug << "############### Not enough space left ###############" << oendl; mNoSpaceLeft = TRUE; } #endif } void PackageHandler::iProcessExited() { if ( currentProcess->normalExit() && currentProcess->exitStatus() == 0 ) sendReply( "installDone(QString)", currentPackage ); else { #ifndef QT_NO_COP QCopEnvelope e( "QPE/Desktop", "installFailed(QString,int,QString)" ); e << currentPackage << currentProcess->exitStatus() << currentProcessError; #endif } delete currentProcess; currentProcess = 0; #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "linkChanged(QString)"); QString lf = QString::null; e << lf; #endif unlink( currentPackage ); } void PackageHandler::rmProcessExited() { if ( currentProcess->normalExit() && currentProcess->exitStatus() == 0 ) sendReply( "removeDone(QString)", currentPackage ); else sendReply( "removeFailed(QString)", currentPackage ); #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "linkChanged(QString)"); QString lf = QString::null; e << lf; #endif } void PackageHandler::readyReadStdout() { while ( currentProcess->canReadLineStdout() ) { QString line = currentProcess->readLineStdout(); currentProcessError.append("OUT:"+line); if ( line.contains( "Unpacking" ) ) // No tr sendReply( "installStep(QString)", "one" ); // No tr else if ( line.contains( "Configuring" ) ) // No tr sendReply( "installStep(QString)", "two" ); // No tr } } void PackageHandler::readyReadStderr() { while ( currentProcess->canReadLineStderr() ) { QString line = currentProcess->readLineStderr(); currentProcessError.append("ERR:"+line); } } void PackageHandler::redoPackages() { //get list of filesystems //call cleanupPackages for the ones that have disappeared //call addPackageFiles for the new ones } diff --git a/core/launcher/qcopbridge.cpp b/core/launcher/qcopbridge.cpp index 33df6c4..e339dc7 100644 --- a/core/launcher/qcopbridge.cpp +++ b/core/launcher/qcopbridge.cpp @@ -1,491 +1,490 @@ /********************************************************************** ** 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 "qcopbridge.h" #include "transferserver.h" +/* OPIE */ +#include <opie2/odebug.h> #include <opie2/oglobal.h> - #ifdef Q_WS_QWS #include <qtopia/qcopenvelope_qws.h> #endif #include <qtopia/qpeapplication.h> - #include <qtopia/version.h> +using namespace Opie::Core; +/* QT */ #include <qtextstream.h> #include <qtimer.h> #ifdef Q_WS_QWS #include <qcopchannel_qws.h> #endif +/* STD */ #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE #endif #ifndef Q_OS_WIN32 #include <pwd.h> #include <unistd.h> #include <sys/types.h> #endif #if defined(_OS_LINUX_) #include <shadow.h> #endif - -//#define INSECURE - const int block_size = 51200; -using namespace Opie::Core; QCopBridge::QCopBridge( Q_UINT16 port, QObject *parent, const char* name ) : QServerSocket( port, 1, parent, name ), desktopChannel( 0 ), cardChannel( 0 ) { if ( !ok() ) - qWarning( "Failed to bind to port %d", port ); + owarn << "Failed to bind to port " << port << "" << oendl; else { #ifndef QT_NO_COP desktopChannel = new QCopChannel( "QPE/Desktop", this ); connect( desktopChannel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(desktopMessage(const QCString&,const QByteArray&)) ); cardChannel = new QCopChannel( "QPE/Card", this ); connect( cardChannel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(desktopMessage(const QCString&,const QByteArray&)) ); #endif } sendSync = FALSE; openConnections.setAutoDelete( TRUE ); authorizeConnections(); } QCopBridge::~QCopBridge() { #ifndef QT_NO_COP delete desktopChannel; #endif } void QCopBridge::authorizeConnections() { Config cfg("Security"); cfg.setGroup("SyncMode"); m_mode = Mode(cfg.readNumEntry("Mode", Sharp )); QListIterator<QCopBridgePI> it(openConnections); while ( it.current() ) { if ( !it.current()->verifyAuthorised() ) { disconnect ( it.current(), SIGNAL( connectionClosed(QCopBridgePI*) ), this, SLOT( closed(QCopBridgePI*) ) ); openConnections.removeRef( it.current() ); } else ++it; } } void QCopBridge::newConnection( int socket ) { QCopBridgePI *pi = new QCopBridgePI( socket, this ); openConnections.append( pi ); connect ( pi, SIGNAL( connectionClosed(QCopBridgePI*) ), this, SLOT( closed(QCopBridgePI*) ) ); /* ### libqtopia merge FIXME */ #if 0 QPEApplication::setTempScreenSaverMode( QPEApplication::DisableSuspend ); #endif #ifndef QT_NO_COP QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::DisableSuspend; #endif if ( sendSync ) { pi ->startSync(); sendSync = FALSE; } } void QCopBridge::closed( QCopBridgePI *pi ) { emit connectionClosed( pi->peerAddress() ); openConnections.removeRef( pi ); if ( openConnections.count() == 0 ) { /* ### FIXME libqtopia merge */ #if 0 QPEApplication::setTempScreenSaverMode( QPEApplication::Enable ); #endif #ifndef QT_NO_COP QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable; #endif } } void QCopBridge::closeOpenConnections() { QCopBridgePI *pi; for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) pi->close(); } void QCopBridge::desktopMessage( const QCString &command, const QByteArray &data ) { if ( command == "startSync()" ) { // we need to buffer it a bit sendSync = TRUE; startTimer( 20000 ); } if ( m_mode & Qtopia1_7 ) { // send the command to all open connections QCopBridgePI *pi; for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) { pi->sendDesktopMessage( command, data ); } } if ( ( m_mode & Sharp ) || (m_mode & IntelliSync) ) sendDesktopMessageOld( command, data ); } #ifndef OPIE_NO_OLD_SYNC_CODE /* * Old compat mode */ void QCopBridge::sendDesktopMessageOld( const QCString& command, const QByteArray& args) { command.stripWhiteSpace(); int paren = command.find( "(" ); if ( paren <= 0 ) { - qDebug("DesktopMessage: bad qcop syntax"); + odebug << "DesktopMessage: bad qcop syntax" << oendl; return; } QString params = command.mid( paren + 1 ); if ( params[params.length()-1] != ')' ) { - qDebug("DesktopMessage: bad qcop syntax"); + odebug << "DesktopMessage: bad qcop syntax" << oendl; return; } params.truncate( params.length()-1 ); QStringList paramList = QStringList::split( ",", params ); QString data; if ( paramList.count() ) { QDataStream stream( args, IO_ReadOnly ); for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) { QString str; if ( *it == "QString" ) { stream >> str; } else if ( *it == "QCString" ) { QCString cstr; stream >> cstr; str = QString::fromLocal8Bit( cstr ); } else if ( *it == "int" ) { int i; stream >> i; str = QString::number( i ); } else if ( *it == "bool" ) { int i; stream >> i; str = QString::number( i ); } else { - qDebug(" cannot route the argument type %s throught the qcop bridge", (*it).latin1() ); + odebug << " cannot route the argument type " << (*it) << " throught the qcop bridge" << oendl; return; } QString estr; for (int i=0; i<(int)str.length(); i++) { QChar ch = str[i]; if ( ch.row() ) goto quick; switch (ch.cell()) { case '&': estr.append( "&" ); break; case ' ': estr.append( "&0x20;" ); break; case '\n': estr.append( "&0x0d;" ); break; case '\r': estr.append( "&0x0a;" ); break; default: quick: estr.append(ch); } } data += " " + estr; } } QString sendCommand = QString(command.data()) + data; // send the command to all open connections QCopBridgePI *pi; for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) pi->sendDesktopMessage( sendCommand ); } #endif void QCopBridge::timerEvent( QTimerEvent * ) { sendSync = FALSE; killTimers(); } QCopBridgePI::QCopBridgePI( int socket, QObject *parent, const char* name ) : QSocket( parent, name ) { setSocket( socket ); peerport = peerPort(); peeraddress = peerAddress(); #ifndef INSECURE if ( !SyncAuthentication::isAuthorized(peeraddress) ) { state = Forbidden; close(); } else #endif { state = Connected; connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); QString intro="220 Qtopia "; intro += QPE_VERSION; intro += ";"; intro += "challenge="; intro += SyncAuthentication::serverId(); intro += ";"; // No tr intro += "loginname="; intro += SyncAuthentication::loginName(); intro += ";"; intro += "displayname="; intro += SyncAuthentication::ownerName(); intro += ";"; send( intro ); state = Wait_USER; } sendSync = FALSE; connect( this, SIGNAL( connectionClosed() ), SLOT( myConnectionClosed() ) ); // idle timer to close connections when not used anymore timer = new QTimer(this); connect( timer, SIGNAL(timeout()), this, SLOT(myConnectionClosed()) ); timer->start( 300000, TRUE ); } QCopBridgePI::~QCopBridgePI() { } bool QCopBridgePI::verifyAuthorised() { if ( !SyncAuthentication::isAuthorized(peerAddress()) ) { state = Forbidden; return FALSE; } return TRUE; } void QCopBridgePI::myConnectionClosed() { emit connectionClosed( this ); } void QCopBridgePI::sendDesktopMessage( const QString &msg ) { QString str = "CALL QPE/Desktop " + msg; // No tr send ( str ); } void QCopBridgePI::sendDesktopMessage( const QCString &msg, const QByteArray& data ) { if ( !isOpen() ) // eg. Forbidden return; const char hdr[]="CALLB QPE/Desktop "; writeBlock(hdr,sizeof(hdr)-1); writeBlock(msg,msg.length()); writeBlock(" ",1); QByteArray b64 = OGlobal::encodeBase64(data); writeBlock(b64.data(),b64.size()); writeBlock("\r\n",2); } void QCopBridgePI::send( const QString& msg ) { if ( !isOpen() ) // eg. Forbidden return; QTextStream os( this ); os << msg << endl; - //qDebug( "sending qcop message: %s", msg.latin1() ); + //odebug << "sending qcop message: " << msg << "" << oendl; } void QCopBridgePI::read() { while ( canReadLine() ) { timer->start( 300000, TRUE ); process( readLine().stripWhiteSpace() ); } } void QCopBridgePI::process( const QString& message ) { - //qDebug( "Command: %s", message.latin1() ); + //odebug << "Command: " << message << "" << oendl; // split message using "," as separator QStringList msg = QStringList::split( " ", message ); if ( msg.isEmpty() ) return; // command token QString cmd = msg[0].upper(); // argument token QString arg; if ( msg.count() >= 2 ) arg = msg[1]; // we always respond to QUIT, regardless of state if ( cmd == "QUIT" ) { send( "211 Have a nice day!" ); // No tr close(); return; } // connected to client if ( Connected == state ) return; // waiting for user name if ( Wait_USER == state ) { if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) { send( "530 Please login with USER and PASS" ); // No tr return; } send( "331 User name ok, need password" ); // No tr state = Wait_PASS; return; } // waiting for password if ( Wait_PASS == state ) { if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) { send( "530 Please login with USER and PASS" ); // No tr return; } send( "230 User logged in, proceed" ); // No tr state = Ready; if ( sendSync ) { sendDesktopMessage( "startSync()" ); sendSync = FALSE; } return; } // noop (NOOP) else if ( cmd == "NOOP" ) { send( "200 Command okay" ); // No tr } // call (CALL) else if ( cmd == "CALL" ) { // example: call QPE/System execute(QString) addressbook if ( msg.count() < 3 ) { send( "500 Syntax error, command unrecognized" ); // No tr } else { QString channel = msg[1]; QString command = msg[2]; command.stripWhiteSpace(); int paren = command.find( "(" ); if ( paren <= 0 ) { send( "500 Syntax error, command unrecognized" ); // No tr return; } QString params = command.mid( paren + 1 ); if ( params[(int)params.length()-1] != ')' ) { send( "500 Syntax error, command unrecognized" ); // No tr return; } params.truncate( params.length()-1 ); QByteArray buffer; QDataStream ds( buffer, IO_WriteOnly ); int msgId = 3; QStringList paramList = QStringList::split( ",", params ); if ( paramList.count() > msg.count() - 3 ) { send( "500 Syntax error, command unrecognized" ); // No tr return; } for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) { QString arg = msg[msgId]; arg.replace( QRegExp("&0x20;"), " " ); arg.replace( QRegExp("&"), "&" ); arg.replace( QRegExp("&0x0d;"), "\n" ); arg.replace( QRegExp("&0x0a;"), "\r" ); if ( *it == "QString" ) ds << arg; else if ( *it == "QCString" ) ds << arg.local8Bit(); else if ( *it == "int" ) ds << arg.toInt(); else if ( *it == "bool" ) ds << arg.toInt(); else { send( "500 Syntax error, command unrecognized" ); // No tr return; } msgId++; } #ifndef QT_NO_COP if ( !QCopChannel::isRegistered( channel.latin1() ) ) { // send message back about it QString answer = "599 ChannelNotRegistered " + channel; send( answer ); return; } #endif #ifndef QT_NO_COP if ( paramList.count() ) QCopChannel::send( channel.latin1(), command.latin1(), buffer ); else QCopChannel::send( channel.latin1(), command.latin1() ); send( "200 Command okay" ); // No tr #endif } } // not implemented else send( "502 Command not implemented" ); // No tr } diff --git a/core/launcher/qprocess.cpp b/core/launcher/qprocess.cpp index 97bd539..3fe1238 100644 --- a/core/launcher/qprocess.cpp +++ b/core/launcher/qprocess.cpp @@ -328,312 +328,312 @@ bool QProcess::canReadLineStderr() const { QProcess *that = (QProcess*)this; return that->scanNewline( FALSE, 0 ); } /*! Reads a line of text from standard output, excluding any trailing newline or carriage return characters, and returns it. Returns QString::null if canReadLineStdout() returns FALSE. \sa canReadLineStdout() readyReadStdout() readStdout() readLineStderr() */ QString QProcess::readLineStdout() { QByteArray a; QString s; if ( scanNewline( TRUE, &a ) ) { if ( a.isEmpty() ) s = ""; else s = QString( a ); } return s; } /*! Reads a line of text from standard error, excluding any trailing newline or carriage return characters and returns it. Returns QString::null if canReadLineStderr() returns FALSE. \sa canReadLineStderr() readyReadStderr() readStderr() readLineStdout() */ QString QProcess::readLineStderr() { QByteArray a; QString s; if ( scanNewline( FALSE, &a ) ) { if ( a.isEmpty() ) s = ""; else s = QString( a ); } return s; } /*! This private function scans for any occurrence of \n or \r\n in the buffer \e buf. It stores the text in the byte array \a store if it is non-null. */ bool QProcess::scanNewline( bool stdOut, QByteArray *store ) { QByteArray *buf; if ( stdOut ) buf = bufStdout(); else buf = bufStderr(); uint n = buf->size(); uint i; for ( i=0; i<n; i++ ) { if ( buf->at(i) == '\n' ) { break; } } if ( i >= n ) return FALSE; if ( store ) { uint lineLength = i; if ( lineLength>0 && buf->at(lineLength-1) == '\r' ) lineLength--; // (if there are two \r, let one stay) store->resize( lineLength ); memcpy( store->data(), buf->data(), lineLength ); if ( stdOut ) consumeBufStdout( i+1 ); else consumeBufStderr( i+1 ); } return TRUE; } /*! \fn void QProcess::launchFinished() This signal is emitted when the process was started with launch(). If the start was successful, this signal is emitted after all the data has been written to standard input. If the start failed, then this signal is emitted immediately. \sa launch() QObject::deleteLater() */ /*! Runs the process and writes the data \a buf to the process's standard input. If all the data is written to standard input, standard input is closed. The command is searched for in the path for executable programs; you can also use an absolute path in the command itself. If \a env is null, then the process is started with the same environment as the starting process. If \a env is non-null, then the values in the stringlist are interpreted as environment setttings of the form \c {key=value} and the process is started with these environment settings. For convenience, there is a small exception to this rule under Unix: if \a env does not contain any settings for the environment variable \c LD_LIBRARY_PATH, then this variable is inherited from the starting process. Returns TRUE if the process could be started; otherwise returns FALSE. Note that you should not use the slots writeToStdin() and closeStdin() on processes started with launch(), since the result is not well-defined. If you need these slots, use start() instead. The process may or may not read the \a buf data sent to its standard input. You can call this function even when a process that was started with this instance is still running. Be aware that if you do this the standard input of the process that was launched first will be closed, with any pending data being deleted, and the process will be left to run out of your control. Similarly, if the process could not be started the standard input will be closed and the pending data deleted. (On operating systems that have zombie processes, Qt will also wait() on the old process.) The object emits the signal launchFinished() when this function call is finished. If the start was successful, this signal is emitted after all the data has been written to standard input. If the start failed, then this signal is emitted immediately. \sa start() launchFinished(); */ bool QProcess::launch( const QByteArray& buf, QStringList *env ) { if ( start( env ) ) { if ( !buf.isEmpty() ) { connect( this, SIGNAL(wroteToStdin()), this, SLOT(closeStdinLaunch()) ); writeToStdin( buf ); } else { closeStdin(); emit launchFinished(); } return TRUE; } else { emit launchFinished(); return FALSE; } } /*! \overload The data \a buf is written to standard input with writeToStdin() using the QString::local8Bit() representation of the strings. */ bool QProcess::launch( const QString& buf, QStringList *env ) { if ( start( env ) ) { if ( !buf.isEmpty() ) { connect( this, SIGNAL(wroteToStdin()), this, SLOT(closeStdinLaunch()) ); writeToStdin( buf ); } else { closeStdin(); emit launchFinished(); } return TRUE; } else { emit launchFinished(); return FALSE; } } /*! This private slot is used by the launch() functions to close standard input. */ void QProcess::closeStdinLaunch() { disconnect( this, SIGNAL(wroteToStdin()), this, SLOT(closeStdinLaunch()) ); closeStdin(); emit launchFinished(); } /*! \fn void QProcess::readyReadStdout() This signal is emitted when the process has written data to standard output. You can read the data with readStdout(). Note that this signal is only emitted when there is new data and not when there is old, but unread data. In the slot connected to this signal, you should always read everything that is available at that moment to make sure that you don't lose any data. \sa readStdout() readLineStdout() readyReadStderr() */ /*! \fn void QProcess::readyReadStderr() This signal is emitted when the process has written data to standard error. You can read the data with readStderr(). Note that this signal is only emitted when there is new data and not when there is old, but unread data. In the slot connected to this signal, you should always read everything that is available at that moment to make sure that you don't lose any data. \sa readStderr() readLineStderr() readyReadStdout() */ /*! \fn void QProcess::processExited() This signal is emitted when the process has exited. \sa isRunning() normalExit() exitStatus() start() launch() */ /*! \fn void QProcess::wroteToStdin() This signal is emitted if the data sent to standard input (via writeToStdin()) was actually written to the process. This does not imply that the process really read the data, since this class only detects when it was able to write the data to the operating system. But it is now safe to close standard input without losing pending data. \sa writeToStdin() closeStdin() */ /*! \overload The string \a buf is handled as text using the QString::local8Bit() representation. */ void QProcess::writeToStdin( const QString& buf ) { QByteArray tmp = buf.local8Bit(); tmp.resize( buf.length() ); writeToStdin( tmp ); } /* * Under Windows the implementation is not so nice: it is not that easy to * detect when one of the signals should be emitted; therefore there are some * timers that query the information. * To keep it a little efficient, use the timers only when they are needed. * They are needed, if you are interested in the signals. So use * connectNotify() and disconnectNotify() to keep track of your interest. */ /*! \reimp */ void QProcess::connectNotify( const char * signal ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::connectNotify(): signal %s has been connected", signal ); + odebug << "QProcess::connectNotify(): signal " << signal << " has been connected" << oendl; #endif if ( !ioRedirection ) if ( qstrcmp( signal, SIGNAL(readyReadStdout()) )==0 || qstrcmp( signal, SIGNAL(readyReadStderr()) )==0 ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::connectNotify(): set ioRedirection to TRUE" ); + odebug << "QProcess::connectNotify(): set ioRedirection to TRUE" << oendl; #endif setIoRedirection( TRUE ); return; } if ( !notifyOnExit && qstrcmp( signal, SIGNAL(processExited()) )==0 ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::connectNotify(): set notifyOnExit to TRUE" ); + odebug << "QProcess::connectNotify(): set notifyOnExit to TRUE" << oendl; #endif setNotifyOnExit( TRUE ); return; } if ( !wroteToStdinConnected && qstrcmp( signal, SIGNAL(wroteToStdin()) )==0 ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::connectNotify(): set wroteToStdinConnected to TRUE" ); + odebug << "QProcess::connectNotify(): set wroteToStdinConnected to TRUE" << oendl; #endif setWroteStdinConnected( TRUE ); return; } } /*! \reimp */ void QProcess::disconnectNotify( const char * ) { if ( ioRedirection && receivers( SIGNAL(readyReadStdout()) ) ==0 && receivers( SIGNAL(readyReadStderr()) ) ==0 ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::disconnectNotify(): set ioRedirection to FALSE" ); + odebug << "QProcess::disconnectNotify(): set ioRedirection to FALSE" << oendl; #endif setIoRedirection( FALSE ); } if ( notifyOnExit && receivers( SIGNAL(processExited()) ) == 0 ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::disconnectNotify(): set notifyOnExit to FALSE" ); + odebug << "QProcess::disconnectNotify(): set notifyOnExit to FALSE" << oendl; #endif setNotifyOnExit( FALSE ); } if ( wroteToStdinConnected && receivers( SIGNAL(wroteToStdin()) ) == 0 ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::disconnectNotify(): set wroteToStdinConnected to FALSE" ); + odebug << "QProcess::disconnectNotify(): set wroteToStdinConnected to FALSE" << oendl; #endif setWroteStdinConnected( FALSE ); } } #endif // QT_NO_PROCESS diff --git a/core/launcher/qprocess_unix.cpp b/core/launcher/qprocess_unix.cpp index 19a8c93..d62e4e6 100644 --- a/core/launcher/qprocess_unix.cpp +++ b/core/launcher/qprocess_unix.cpp @@ -1,1174 +1,1173 @@ /********************************************************************** ** 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 "qplatformdefs.h" - // Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED. #if defined(connect) #undef connect #endif #include "qprocess.h" -#ifndef QT_NO_PROCESS +/* OPIE */ +#include <opie2/odebug.h> +using namespace Opie::Core; -#include "qapplication.h" -#include "qqueue.h" -#include "qlist.h" -#include "qsocketnotifier.h" -#include "qtimer.h" -#include "qregexp.h" +/* QT */ +#ifndef QT_NO_PROCESS +#include <qapplication.h> +#include <qqueue.h> +#include <qlist.h> +#include <qsocketnotifier.h> +#include <qtimer.h> +#include <qregexp.h> #include "qcleanuphandler_p.h" +/* STD */ #include <stdlib.h> - -// ### FOR Qt 2.3 compat #include <unistd.h> #include <signal.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/wait.h> #include <sys/fcntl.h> - +#include <sys/resource.h> #include <errno.h> - #ifdef Q_OS_MACX #include <sys/time.h> #endif -#include <sys/resource.h> #ifdef __MIPSEL__ # ifndef SOCK_DGRAM # define SOCK_DGRAM 1 # endif # ifndef SOCK_STREAM # define SOCK_STREAM 2 # endif #endif //#define QT_QPROCESS_DEBUG #ifdef Q_C_CALLBACKS extern "C" { #endif // Q_C_CALLBACKS #define QT_SIGNAL_RETTYPE void #define QT_SIGNAL_ARGS int #define QT_SIGNAL_IGNORE SIG_IGN QT_SIGNAL_RETTYPE qt_C_sigchldHnd(QT_SIGNAL_ARGS); QT_SIGNAL_RETTYPE qt_C_sigpipeHnd(QT_SIGNAL_ARGS); #ifdef Q_C_CALLBACKS } #endif // Q_C_CALLBACKS class QProc; class QProcessManager; class QProcessPrivate { public: QProcessPrivate(); ~QProcessPrivate(); void closeOpenSocketsForChild(); void newProc( pid_t pid, QProcess *process ); QByteArray bufStdout; QByteArray bufStderr; QQueue<QByteArray> stdinBuf; QSocketNotifier *notifierStdin; QSocketNotifier *notifierStdout; QSocketNotifier *notifierStderr; ssize_t stdinBufRead; QProc *proc; bool exitValuesCalculated; bool socketReadCalled; static QProcessManager *procManager; }; /*********************************************************************** * * QProc * **********************************************************************/ /* The class QProcess does not necessarily map exactly to the running child processes: if the process is finished, the QProcess class may still be there; furthermore a user can use QProcess to start more than one process. The helper-class QProc has the semantics that one instance of this class maps directly to a running child process. */ class QProc { public: QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProc: Constructor for pid %d and QProcess %p", pid, process ); + odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl; #endif socketStdin = 0; socketStdout = 0; socketStderr = 0; } ~QProc() { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProc: Destructor for pid %d and QProcess %p", pid, process ); + odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl; #endif if ( process != 0 ) { if ( process->d->notifierStdin ) process->d->notifierStdin->setEnabled( FALSE ); if ( process->d->notifierStdout ) process->d->notifierStdout->setEnabled( FALSE ); if ( process->d->notifierStderr ) process->d->notifierStderr->setEnabled( FALSE ); process->d->proc = 0; } if( socketStdin != 0 ) ::close( socketStdin ); // ### close these sockets even on parent exit or is it better only on // sigchld (but what do I have to do with them on exit then)? if( socketStdout != 0 ) ::close( socketStdout ); if( socketStderr != 0 ) ::close( socketStderr ); } pid_t pid; int socketStdin; int socketStdout; int socketStderr; QProcess *process; }; /*********************************************************************** * * QProcessManager * **********************************************************************/ class QProcessManager : public QObject { Q_OBJECT public: QProcessManager(); ~QProcessManager(); void append( QProc *p ); void remove( QProc *p ); void cleanup(); public slots: void removeMe(); void sigchldHnd( int ); public: struct sigaction oldactChld; struct sigaction oldactPipe; QList<QProc> *procList; int sigchldFd[2]; }; QCleanupHandler<QProcessManager> qprocess_cleanup_procmanager; QProcessManager::QProcessManager() { procList = new QList<QProc>; procList->setAutoDelete( TRUE ); // The SIGCHLD handler writes to a socket to tell the manager that // something happened. This is done to get the processing in sync with the // event reporting. if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) { sigchldFd[0] = 0; sigchldFd[1] = 0; } else { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager: install socket notifier (%d)", sigchldFd[1] ); + odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl; #endif QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1], QSocketNotifier::Read, this ); connect( sn, SIGNAL(activated(int)), this, SLOT(sigchldHnd(int)) ); sn->setEnabled( TRUE ); } // install a SIGCHLD handler and ignore SIGPIPE struct sigaction act; #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager: install a SIGCHLD handler" ); + odebug << "QProcessManager: install a SIGCHLD handler" << oendl; #endif act.sa_handler = qt_C_sigchldHnd; sigemptyset( &(act.sa_mask) ); sigaddset( &(act.sa_mask), SIGCHLD ); act.sa_flags = SA_NOCLDSTOP; #if defined(SA_RESTART) act.sa_flags |= SA_RESTART; #endif if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 ) - qWarning( "Error installing SIGCHLD handler" ); + owarn << "Error installing SIGCHLD handler" << oendl; #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager: install a SIGPIPE handler (SIG_IGN)" ); + odebug << "QProcessManager: install a SIGPIPE handler (SIG_IGN)" << oendl; #endif /* Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround for a strange problem where GNU tar (called by backuprestore) would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd is never even called, yet this avoids the hang. */ act.sa_handler = qt_C_sigpipeHnd; sigemptyset( &(act.sa_mask) ); sigaddset( &(act.sa_mask), SIGPIPE ); act.sa_flags = 0; if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 ) - qWarning( "Error installing SIGPIPE handler" ); + owarn << "Error installing SIGPIPE handler" << oendl; } QProcessManager::~QProcessManager() { delete procList; if ( sigchldFd[0] != 0 ) ::close( sigchldFd[0] ); if ( sigchldFd[1] != 0 ) ::close( sigchldFd[1] ); // restore SIGCHLD handler #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager: restore old sigchild handler" ); + odebug << "QProcessManager: restore old sigchild handler" << oendl; #endif if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 ) - qWarning( "Error restoring SIGCHLD handler" ); + owarn << "Error restoring SIGCHLD handler" << oendl; #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager: restore old sigpipe handler" ); + odebug << "QProcessManager: restore old sigpipe handler" << oendl; #endif if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 ) - qWarning( "Error restoring SIGPIPE handler" ); + owarn << "Error restoring SIGPIPE handler" << oendl; } void QProcessManager::append( QProc *p ) { procList->append( p ); #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager: append process (procList.count(): %d)", procList->count() ); + odebug << "QProcessManager: append process (procList.count(): " << procList->count() << ")" << oendl; #endif } void QProcessManager::remove( QProc *p ) { procList->remove( p ); #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager: remove process (procList.count(): %d)", procList->count() ); + odebug << "QProcessManager: remove process (procList.count(): " << procList->count() << ")" << oendl; #endif cleanup(); } void QProcessManager::cleanup() { if ( procList->count() == 0 ) { QTimer::singleShot( 0, this, SLOT(removeMe()) ); } } void QProcessManager::removeMe() { if ( procList->count() == 0 ) { qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager ); QProcessPrivate::procManager = 0; delete this; } } void QProcessManager::sigchldHnd( int fd ) { char tmp; ::read( fd, &tmp, sizeof(tmp) ); #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager::sigchldHnd()" ); + odebug << "QProcessManager::sigchldHnd()" << oendl; #endif QProc *proc; QProcess *process; bool removeProc; proc = procList->first(); while ( proc != 0 ) { removeProc = FALSE; process = proc->process; QProcess *process_exit_notify=0; if ( process != 0 ) { if ( !process->isRunning() ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager::sigchldHnd() (PID: %d): process exited (QProcess available)", proc->pid ); + odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess available)" << oendl; #endif // read pending data int nbytes = 0; if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stdout", proc->pid, nbytes ); + odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stdout" << oendl; #endif process->socketRead( proc->socketStdout ); } nbytes = 0; if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stderr", proc->pid, nbytes ); + odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stderr" << oendl; #endif process->socketRead( proc->socketStderr ); } if ( process->notifyOnExit ) process_exit_notify = process; removeProc = TRUE; } } else { int status; if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessManager::sigchldHnd() (PID: %d): process exited (QProcess not available)", proc->pid ); + odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess not available)" << oendl; #endif removeProc = TRUE; } } if ( removeProc ) { QProc *oldproc = proc; proc = procList->next(); remove( oldproc ); } else { proc = procList->next(); } if ( process_exit_notify ) emit process_exit_notify->processExited(); } } #include "qprocess_unix.moc" /*********************************************************************** * * QProcessPrivate * **********************************************************************/ QProcessManager *QProcessPrivate::procManager = 0; QProcessPrivate::QProcessPrivate() { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessPrivate: Constructor" ); + odebug << "QProcessPrivate: Constructor" << oendl; #endif stdinBufRead = 0; notifierStdin = 0; notifierStdout = 0; notifierStderr = 0; exitValuesCalculated = FALSE; socketReadCalled = FALSE; proc = 0; } QProcessPrivate::~QProcessPrivate() { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcessPrivate: Destructor" ); + odebug << "QProcessPrivate: Destructor" << oendl; #endif if ( proc != 0 ) { if ( proc->socketStdin != 0 ) { ::close( proc->socketStdin ); proc->socketStdin = 0; } proc->process = 0; } while ( !stdinBuf.isEmpty() ) { delete stdinBuf.dequeue(); } delete notifierStdin; delete notifierStdout; delete notifierStderr; } /* Closes all open sockets in the child process that are not needed by the child process. Otherwise one child may have an open socket on standard input, etc. of another child. */ void QProcessPrivate::closeOpenSocketsForChild() { if ( procManager != 0 ) { if ( procManager->sigchldFd[0] != 0 ) ::close( procManager->sigchldFd[0] ); if ( procManager->sigchldFd[1] != 0 ) ::close( procManager->sigchldFd[1] ); // close also the sockets from other QProcess instances QProc *proc; for ( proc=procManager->procList->first(); proc!=0; proc=procManager->procList->next() ) { ::close( proc->socketStdin ); ::close( proc->socketStdout ); ::close( proc->socketStderr ); } } } void QProcessPrivate::newProc( pid_t pid, QProcess *process ) { proc = new QProc( pid, process ); if ( procManager == 0 ) { procManager = new QProcessManager; qprocess_cleanup_procmanager.add( &procManager ); } // the QProcessManager takes care of deleting the QProc instances procManager->append( proc ); } /*********************************************************************** * * sigchld handler callback * **********************************************************************/ QT_SIGNAL_RETTYPE qt_C_sigchldHnd( QT_SIGNAL_ARGS ) { if ( QProcessPrivate::procManager == 0 ) return; if ( QProcessPrivate::procManager->sigchldFd[0] == 0 ) return; char a = 1; ::write( QProcessPrivate::procManager->sigchldFd[0], &a, sizeof(a) ); } QT_SIGNAL_RETTYPE qt_C_sigpipeHnd( QT_SIGNAL_ARGS ) { // Ignore (but in a way somehow different to SIG_IGN). } /*********************************************************************** * * QProcess * **********************************************************************/ /*! This private class does basic initialization. */ void QProcess::init() { d = new QProcessPrivate(); exitStat = 0; exitNormal = FALSE; } /*! This private class resets the process variables, etc. so that it can be used for another process to start. */ void QProcess::reset() { delete d; d = new QProcessPrivate(); exitStat = 0; exitNormal = FALSE; d->bufStdout.resize( 0 ); d->bufStderr.resize( 0 ); } QByteArray* QProcess::bufStdout() { if ( d->proc && d->proc->socketStdout ) { // ### can this cause a blocking behaviour (maybe do a ioctl() to see // if data is available)? socketRead( d->proc->socketStdout ); } return &d->bufStdout; } QByteArray* QProcess::bufStderr() { if ( d->proc && d->proc->socketStderr ) { // ### can this cause a blocking behaviour (maybe do a ioctl() to see // if data is available)? socketRead( d->proc->socketStderr ); } return &d->bufStderr; } void QProcess::consumeBufStdout( int consume ) { uint n = d->bufStdout.size(); if ( consume==-1 || (uint)consume >= n ) { d->bufStdout.resize( 0 ); } else { QByteArray tmp( n - consume ); memcpy( tmp.data(), d->bufStdout.data()+consume, n-consume ); d->bufStdout = tmp; } } void QProcess::consumeBufStderr( int consume ) { uint n = d->bufStderr.size(); if ( consume==-1 || (uint)consume >= n ) { d->bufStderr.resize( 0 ); } else { QByteArray tmp( n - consume ); memcpy( tmp.data(), d->bufStderr.data()+consume, n-consume ); d->bufStderr = tmp; } } /*! Destroys the class. If the process is running, it is NOT terminated! Standard input, standard output and standard error of the process are closed. You can connect the destroyed() signal to the kill() slot, if you want the process to be terminated automatically when the class is destroyed. \sa tryTerminate() kill() */ QProcess::~QProcess() { delete d; } /*! Tries to run a process for the command and arguments that were specified with setArguments(), addArgument() or that were specified in the constructor. The command is searched in the path for executable programs; you can also use an absolute path to the command. If \a env is null, then the process is started with the same environment as the starting process. If \a env is non-null, then the values in the stringlist are interpreted as environment setttings of the form \c {key=value} and the process is started in these environment settings. For convenience, there is a small exception to this rule: under Unix, if \a env does not contain any settings for the environment variable \c LD_LIBRARY_PATH, then this variable is inherited from the starting process; under Windows the same applies for the enverionment varialbe \c PATH. Returns TRUE if the process could be started, otherwise FALSE. You can write data to standard input of the process with writeToStdin(), you can close standard input with closeStdin() and you can terminate the process tryTerminate() resp. kill(). You can call this function even when there already is a running process in this object. In this case, QProcess closes standard input of the old process and deletes pending data, i.e., you loose all control over that process, but the process is not terminated. This applies also if the process could not be started. (On operating systems that have zombie processes, Qt will also wait() on the old process.) \sa launch() closeStdin() */ bool QProcess::start( QStringList *env ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::start()" ); + odebug << "QProcess::start()" << oendl; #endif reset(); int sStdin[2]; int sStdout[2]; int sStderr[2]; // open sockets for piping if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) { return FALSE; } if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) { return FALSE; } if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) { return FALSE; } // the following pipe is only used to determine if the process could be // started int fd[2]; if ( pipe( fd ) < 0 ) { // non critical error, go on fd[0] = 0; fd[1] = 0; } // construct the arguments for exec QCString *arglistQ = new QCString[ _arguments.count() + 1 ]; const char** arglist = new const char*[ _arguments.count() + 1 ]; int i = 0; for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) { arglistQ[i] = (*it).local8Bit(); arglist[i] = arglistQ[i]; #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::start(): arg %d = %s", i, arglist[i] ); + odebug << "QProcess::start(): arg " << i << " = " << arglist[i] << "" << oendl; #endif i++; } arglist[i] = 0; // Must make sure signal handlers are installed before exec'ing // in case the process exits quickly. if ( d->procManager == 0 ) { d->procManager = new QProcessManager; qprocess_cleanup_procmanager.add( &d->procManager ); } // fork and exec QApplication::flushX(); pid_t pid = fork(); if ( pid == 0 ) { // child d->closeOpenSocketsForChild(); if ( comms & Stdin ) { ::close( sStdin[1] ); ::dup2( sStdin[0], STDIN_FILENO ); } if ( comms & Stdout ) { ::close( sStdout[0] ); ::dup2( sStdout[1], STDOUT_FILENO ); } if ( comms & Stderr ) { ::close( sStderr[0] ); ::dup2( sStderr[1], STDERR_FILENO ); } if ( comms & DupStderr ) { ::dup2( STDOUT_FILENO, STDERR_FILENO ); } #ifndef QT_NO_DIR ::chdir( workingDir.absPath().latin1() ); #endif if ( fd[0] ) ::close( fd[0] ); if ( fd[1] ) ::fcntl( fd[1], F_SETFD, FD_CLOEXEC ); // close on exec shows sucess if ( env == 0 ) { // inherit environment and start process ::execvp( arglist[0], (char*const*)arglist ); // ### cast not nice } else { // start process with environment settins as specified in env // construct the environment for exec int numEntries = env->count(); bool setLibraryPath = env->grep( QRegExp( "^LD_LIBRARY_PATH=" ) ).isEmpty() && getenv( "LD_LIBRARY_PATH" ) != 0; if ( setLibraryPath ) numEntries++; QCString *envlistQ = new QCString[ numEntries + 1 ]; const char** envlist = new const char*[ numEntries + 1 ]; int i = 0; if ( setLibraryPath ) { envlistQ[i] = QString( "LD_LIBRARY_PATH=%1" ).arg( getenv( "LD_LIBRARY_PATH" ) ).local8Bit(); envlist[i] = envlistQ[i]; i++; } for ( QStringList::Iterator it = env->begin(); it != env->end(); ++it ) { envlistQ[i] = (*it).local8Bit(); envlist[i] = envlistQ[i]; i++; } envlist[i] = 0; // look for the executable in the search path if ( _arguments.count()>0 && getenv("PATH")!=0 ) { QString command = _arguments[0]; if ( !command.contains( '/' ) ) { QStringList pathList = QStringList::split( ':', getenv( "PATH" ) ); for (QStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it ) { QString dir = *it; #ifdef Q_OS_MACX if(QFile::exists(dir + "/" + command + ".app")) //look in a bundle dir += "/" + command + ".app/Contents/MacOS"; #endif #ifndef QT_NO_DIR QFileInfo fileInfo( dir, command ); #else QFileInfo fileInfo( dir + "/" + command ); #endif if ( fileInfo.isExecutable() ) { arglistQ[0] = fileInfo.filePath().local8Bit(); arglist[0] = arglistQ[0]; break; } } } } ::execve( arglist[0], (char*const*)arglist, (char*const*)envlist ); // ### casts not nice } if ( fd[1] ) { char buf = 0; ::write( fd[1], &buf, 1 ); ::close( fd[1] ); } ::exit( -1 ); } else if ( pid == -1 ) { // error forking goto error; } // test if exec was successful if ( fd[1] ) ::close( fd[1] ); if ( fd[0] ) { char buf; for ( ;; ) { int n = ::read( fd[0], &buf, 1 ); if ( n==1 ) { // socket was not closed => error d->proc = 0; goto error; } else if ( n==-1 ) { if ( errno==EAGAIN || errno==EINTR ) // try it again continue; } break; } ::close( fd[0] ); } d->newProc( pid, this ); if ( comms & Stdin ) { ::close( sStdin[0] ); d->proc->socketStdin = sStdin[1]; d->notifierStdin = new QSocketNotifier( sStdin[1], QSocketNotifier::Write ); connect( d->notifierStdin, SIGNAL(activated(int)), this, SLOT(socketWrite(int)) ); // setup notifiers for the sockets if ( !d->stdinBuf.isEmpty() ) { d->notifierStdin->setEnabled( TRUE ); } } if ( comms & Stdout ) { ::close( sStdout[1] ); d->proc->socketStdout = sStdout[0]; d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read ); connect( d->notifierStdout, SIGNAL(activated(int)), this, SLOT(socketRead(int)) ); if ( ioRedirection ) d->notifierStdout->setEnabled( TRUE ); } if ( comms & Stderr ) { ::close( sStderr[1] ); d->proc->socketStderr = sStderr[0]; d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read ); connect( d->notifierStderr, SIGNAL(activated(int)), this, SLOT(socketRead(int)) ); if ( ioRedirection ) d->notifierStderr->setEnabled( TRUE ); } // cleanup and return delete[] arglistQ; delete[] arglist; return TRUE; error: #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::start(): error starting process" ); + odebug << "QProcess::start(): error starting process" << oendl; #endif if ( d->procManager ) d->procManager->cleanup(); if ( comms & Stdin ) { ::close( sStdin[1] ); ::close( sStdin[0] ); } if ( comms & Stdout ) { ::close( sStdout[0] ); ::close( sStdout[1] ); } if ( comms & Stderr ) { ::close( sStderr[0] ); ::close( sStderr[1] ); } ::close( fd[0] ); ::close( fd[1] ); delete[] arglistQ; delete[] arglist; return FALSE; } /*! Asks the process to terminate. Processes can ignore this wish. If you want to be sure that the process really terminates, you must use kill() instead. The slot returns immediately: it does not wait until the process has finished. When the process really exited, the signal processExited() is emitted. \sa kill() processExited() */ void QProcess::tryTerminate() const { if ( d->proc != 0 ) ::kill( d->proc->pid, SIGTERM ); } /*! Terminates the process. This is not a safe way to end a process since the process will not be able to do cleanup. tryTerminate() is a safer way to do it, but processes might ignore a tryTerminate(). The nice way to end a process and to be sure that it is finished, is doing something like this: \code process->tryTerminate(); QTimer::singleShot( 5000, process, SLOT( kill() ) ); \endcode This tries to terminate the process the nice way. If the process is still running after 5 seconds, it terminates the process the hard way. The timeout should be chosen depending on the time the process needs to do all the cleanup: use a higher value if the process is likely to do heavy computation on cleanup. The slot returns immediately: it does not wait until the process has finished. When the process really exited, the signal processExited() is emitted. \sa tryTerminate() processExited() */ void QProcess::kill() const { if ( d->proc != 0 ) ::kill( d->proc->pid, SIGKILL ); } /*! Returns TRUE if the process is running, otherwise FALSE. \sa normalExit() exitStatus() processExited() */ bool QProcess::isRunning() const { if ( d->exitValuesCalculated ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::isRunning(): FALSE (already computed)" ); + odebug << "QProcess::isRunning(): FALSE (already computed)" << oendl; #endif return FALSE; } if ( d->proc == 0 ) return FALSE; int status; if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid ) { // compute the exit values QProcess *that = (QProcess*)this; // mutable that->exitNormal = WIFEXITED( status ) != 0; if ( exitNormal ) { that->exitStat = (char)WEXITSTATUS( status ); } d->exitValuesCalculated = TRUE; #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::isRunning() (PID: %d): FALSE", d->proc->pid ); + odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): FALSE" << oendl; #endif return FALSE; } #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::isRunning() (PID: %d): TRUE", d->proc->pid ); + odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): TRUE" << oendl; #endif return TRUE; } /*! Writes the data \a buf to the standard input of the process. The process may or may not read this data. This function returns immediately; the QProcess class might write the data at a later point (you have to enter the event loop for that). When all the data is written to the process, the signal wroteToStdin() is emitted. This does not mean that the process really read the data, since this class only detects when it was able to write the data to the operating system. \sa wroteToStdin() closeStdin() readStdout() readStderr() */ void QProcess::writeToStdin( const QByteArray& buf ) { #if defined(QT_QPROCESS_DEBUG) -// qDebug( "QProcess::writeToStdin(): write to stdin (%d)", d->socketStdin ); +// odebug << "QProcess::writeToStdin(): write to stdin (" << d->socketStdin << ")" << oendl; #endif d->stdinBuf.enqueue( new QByteArray(buf) ); if ( d->notifierStdin != 0 ) d->notifierStdin->setEnabled( TRUE ); } /*! Closes standard input of the process. This function also deletes pending data that is not written to standard input yet. \sa wroteToStdin() */ void QProcess::closeStdin() { if ( d->proc == 0 ) return; if ( d->proc->socketStdin !=0 ) { while ( !d->stdinBuf.isEmpty() ) { delete d->stdinBuf.dequeue(); } delete d->notifierStdin; d->notifierStdin = 0; if ( ::close( d->proc->socketStdin ) != 0 ) { - qWarning( "Could not close stdin of child process" ); + owarn << "Could not close stdin of child process" << oendl; } #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::closeStdin(): stdin (%d) closed", d->proc->socketStdin ); + odebug << "QProcess::closeStdin(): stdin (" << d->proc->socketStdin << ") closed" << oendl; #endif d->proc->socketStdin = 0; } } /* This private slot is called when the process has outputted data to either standard output or standard error. */ void QProcess::socketRead( int fd ) { if ( d->socketReadCalled ) { // the slots that are connected to the readyRead...() signals might // trigger a recursive call of socketRead(). Avoid this since you get a // blocking read otherwise. return; } #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::socketRead(): %d", fd ); + odebug << "QProcess::socketRead(): " << fd << "" << oendl; #endif if ( fd == 0 ) return; const int bufsize = 4096; QByteArray *buffer = 0; uint oldSize; int n; if ( fd == d->proc->socketStdout ) { buffer = &d->bufStdout; } else if ( fd == d->proc->socketStderr ) { buffer = &d->bufStderr; } else { // this case should never happen, but just to be safe return; } // read data oldSize = buffer->size(); buffer->resize( oldSize + bufsize ); n = ::read( fd, buffer->data()+oldSize, bufsize ); if ( n > 0 ) buffer->resize( oldSize + n ); else buffer->resize( oldSize ); // eof or error? if ( n == 0 || n == -1 ) { if ( fd == d->proc->socketStdout ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::socketRead(): stdout (%d) closed", fd ); + odebug << "QProcess::socketRead(): stdout (" << fd << ") closed" << oendl; #endif d->notifierStdout->setEnabled( FALSE ); delete d->notifierStdout; d->notifierStdout = 0; ::close( d->proc->socketStdout ); d->proc->socketStdout = 0; return; } else if ( fd == d->proc->socketStderr ) { #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::socketRead(): stderr (%d) closed", fd ); + odebug << "QProcess::socketRead(): stderr (" << fd << ") closed" << oendl; #endif d->notifierStderr->setEnabled( FALSE ); delete d->notifierStderr; d->notifierStderr = 0; ::close( d->proc->socketStderr ); d->proc->socketStderr = 0; return; } } // read all data that is available while ( n == bufsize ) { oldSize = buffer->size(); buffer->resize( oldSize + bufsize ); n = ::read( fd, buffer->data()+oldSize, bufsize ); if ( n > 0 ) buffer->resize( oldSize + n ); else buffer->resize( oldSize ); } d->socketReadCalled = TRUE; if ( fd == d->proc->socketStdout ) { #if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::socketRead(): %d bytes read from stdout (%d)", buffer->size()-oldSize, fd ); #endif emit readyReadStdout(); } else if ( fd == d->proc->socketStderr ) { #if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::socketRead(): %d bytes read from stderr (%d)", buffer->size()-oldSize, fd ); #endif emit readyReadStderr(); } d->socketReadCalled = FALSE; } /* This private slot is called when the process tries to read data from standard input. */ void QProcess::socketWrite( int fd ) { if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 ) return; if ( d->stdinBuf.isEmpty() ) { d->notifierStdin->setEnabled( FALSE ); return; } #if defined(QT_QPROCESS_DEBUG) - qDebug( "QProcess::socketWrite(): write to stdin (%d)", fd ); + odebug << "QProcess::socketWrite(): write to stdin (" << fd << ")" << oendl; #endif ssize_t ret = ::write( fd, d->stdinBuf.head()->data() + d->stdinBufRead, d->stdinBuf.head()->size() - d->stdinBufRead ); if ( ret > 0 ) d->stdinBufRead += ret; if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) { d->stdinBufRead = 0; delete d->stdinBuf.dequeue(); if ( wroteToStdinConnected && d->stdinBuf.isEmpty() ) emit wroteToStdin(); socketWrite( fd ); } } /*! \internal Flushes standard input. This is useful if you want to use QProcess in a synchronous manner. This function should probably go into the public API. */ void QProcess::flushStdin() { socketWrite( d->proc->socketStdin ); } /* This private slot is only used under Windows (but moc does not know about #if defined()). */ void QProcess::timeout() { } /* This private function is used by connectNotify() and disconnectNotify() to change the value of ioRedirection (and related behaviour) */ void QProcess::setIoRedirection( bool value ) { ioRedirection = value; if ( ioRedirection ) { if ( d->notifierStdout ) d->notifierStdout->setEnabled( TRUE ); if ( d->notifierStderr ) d->notifierStderr->setEnabled( TRUE ); } else { if ( d->notifierStdout ) d->notifierStdout->setEnabled( FALSE ); if ( d->notifierStderr ) d->notifierStderr->setEnabled( FALSE ); } } /* This private function is used by connectNotify() and disconnectNotify() to change the value of notifyOnExit (and related behaviour) */ void QProcess::setNotifyOnExit( bool value ) { notifyOnExit = value; } /* This private function is used by connectNotify() and disconnectNotify() to change the value of wroteToStdinConnected (and related behaviour) */ void QProcess::setWroteStdinConnected( bool value ) { wroteToStdinConnected = value; } /*! \enum QProcess::PID \internal */ /*! Returns platform dependent information about the process. This can be used together with platform specific system calls. Under Unix the return value is the PID of the process, or -1 if no process is belonging to this object. Under Windows it is a pointer to the \c PROCESS_INFORMATION struct, or 0 if no process is belonging to this object. */ QProcess::PID QProcess::processIdentifier() { if ( d->proc == 0 ) return -1; return d->proc->pid; } int QProcess::priority() const { if ( d->proc ) return getpriority(PRIO_PROCESS,d->proc->pid); return 0; } void QProcess::setPriority(int p) { if ( d->proc ) setpriority(PRIO_PROCESS,d->proc->pid,p); } #endif // QT_NO_PROCESS diff --git a/core/launcher/runningappbar.cpp b/core/launcher/runningappbar.cpp index 2e9d2a9..a25963f 100644 --- a/core/launcher/runningappbar.cpp +++ b/core/launcher/runningappbar.cpp @@ -1,172 +1,176 @@ /********************************************************************** ** 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_PRELOADACCESS +#include "runningappbar.h" +#include "serverinterface.h" -#include <stdlib.h> +/* OPIE */ +#include <opie2/odebug.h> +#include <qtopia/qcopenvelope_qws.h> +using namespace Opie::Core; +/* QT */ #include <qpainter.h> -#include <qtopia/qcopenvelope_qws.h> - -#include "runningappbar.h" -#include "serverinterface.h" +/* STD */ +#include <stdlib.h> RunningAppBar::RunningAppBar(QWidget* parent) : QFrame(parent), selectedAppIndex(-1) { QCopChannel* channel = new QCopChannel( "QPE/System", this ); connect( channel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(received(const QCString&,const QByteArray&)) ); spacing = AppLnk::smallIconSize()+3; } RunningAppBar::~RunningAppBar() { } void RunningAppBar::received(const QCString& msg, const QByteArray& data) { // Since fast apps appear and disappear without disconnecting from their // channel we need to watch for the showing/hiding events and update according. QDataStream stream( data, IO_ReadOnly ); if ( msg == "fastAppShowing(QString)") { QString appName; stream >> appName; - // qDebug("fastAppShowing %s", appName.data() ); + // odebug << "fastAppShowing " << appName.data() << "" << oendl; const AppLnk* f = ServerInterface::appLnks().findExec(appName); if ( f ) addTask(*f); } else if ( msg == "fastAppHiding(QString)") { QString appName; stream >> appName; const AppLnk* f = ServerInterface::appLnks().findExec(appName); if ( f ) removeTask(*f); } } void RunningAppBar::addTask(const AppLnk& appLnk) { - qDebug("Added %s to app list.", appLnk.name().latin1()); + odebug << "Added " << appLnk.name() << " to app list." << oendl; AppLnk* newApp = new AppLnk(appLnk); newApp->setExec(appLnk.exec()); appList.prepend(newApp); update(); } void RunningAppBar::removeTask(const AppLnk& appLnk) { unsigned int i = 0; for (; i < appList.count() ; i++) { AppLnk* target = appList.at(i); if (target->exec() == appLnk.exec()) { - qDebug("Removing %s from app list.", appLnk.name().latin1()); + odebug << "Removing " << appLnk.name() << " from app list." << oendl; appList.remove(); delete target; } } update(); } void RunningAppBar::mousePressEvent(QMouseEvent *e) { // Find out if the user is clicking on an app icon... // If so, snag the index so when we repaint we show it // as highlighed. selectedAppIndex = 0; int x=0; QListIterator<AppLnk> it( appList ); for ( ; it.current(); ++it,++selectedAppIndex,x+=spacing ) { if ( x + spacing <= width() ) { if ( e->x() >= x && e->x() < x+spacing ) { if ( selectedAppIndex < (int)appList.count() ) { repaint(FALSE); return; } } } else { break; } } selectedAppIndex = -1; repaint( FALSE ); } void RunningAppBar::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == QMouseEvent::RightButton) return; if ( selectedAppIndex >= 0 ) { QString app = appList.at(selectedAppIndex)->exec(); QCopEnvelope e("QPE/System", "raise(QString)"); e << app; selectedAppIndex = -1; update(); } } void RunningAppBar::paintEvent( QPaintEvent * ) { QPainter p( this ); AppLnk *curApp; int x = 0; int y = (height() - AppLnk::smallIconSize()) / 2; int i = 0; p.fillRect( 0, 0, width(), height(), colorGroup().background() ); QListIterator<AppLnk> it(appList); for (; it.current(); i++, ++it ) { if ( x + spacing <= width() ) { curApp = it.current(); - qWarning("Drawing %s", curApp->name().latin1() ); + owarn << "Drawing " << curApp->name() << "" << oendl; if ( (int)i == selectedAppIndex ) p.fillRect( x, y, spacing, curApp->pixmap().height()+1, colorGroup().highlight() ); else p.eraseRect( x, y, spacing, curApp->pixmap().height()+1 ); p.drawPixmap( x, y, curApp->pixmap() ); x += spacing; } } } QSize RunningAppBar::sizeHint() const { return QSize( frameWidth(), AppLnk::smallIconSize()+frameWidth()*2+3 ); } void RunningAppBar::applicationLaunched(const QString &appName) { - qDebug("desktop:: app: %s launched with pid ", appName.data() ); + odebug << "desktop:: app: " << appName.data() << " launched with pid " << oendl; const AppLnk* newGuy = ServerInterface::appLnks().findExec(appName); if ( newGuy && !newGuy->isPreloaded() ) { addTask( *newGuy ); } } void RunningAppBar::applicationTerminated(const QString &app) { const AppLnk* gone = ServerInterface::appLnks().findExec(app); if ( gone ) { removeTask(*gone); } } diff --git a/core/launcher/screensaver.cpp b/core/launcher/screensaver.cpp index 6aaab3a..a7d23c4 100644 --- a/core/launcher/screensaver.cpp +++ b/core/launcher/screensaver.cpp @@ -1,328 +1,328 @@ #include "screensaver.h" #include <qpe/config.h> #include <qpe/network.h> #include <opie2/odevice.h> using namespace Opie::Core; OpieScreenSaver::OpieScreenSaver ( ) : QObject ( 0, "screensaver" ), QWSScreenSaver ( ) { m_disable_suspend = 100; m_enable_dim = false; m_enable_lightoff = false; m_enable_suspend = false; m_onlylcdoff = false; m_enable_dim_ac = false; m_enable_lightoff_ac = false; m_enable_suspend_ac = false; m_onlylcdoff_ac = false; m_use_light_sensor = false; m_backlight_sensor = -1; ::memset ( m_sensordata, 0xff, LS_Count * sizeof( m_sensordata [0] )); m_lcd_status = true; m_backlight_normal = -1; m_backlight_current = -1; m_backlight_forcedoff = false; m_on_ac = false; m_level = -1; // Make sure the LCD is in fact on, (if opie was killed while the LCD is off it would still be off) ODevice::inst ( )-> setDisplayStatus ( true ); setBacklight ( -1 ); } /** * Stops the screen saver */ void OpieScreenSaver::restore() { m_level = -1; if ( !m_lcd_status ) { // We must have turned it off ODevice::inst ( ) -> setDisplayStatus ( true ); m_lcd_status = true; } setBacklightInternal ( -1 ); } /** * Starts the screen saver * * @param level what level of screen saving should happen (0=lowest non-off, 1=off, * 2=suspend whole machine) * @returns true on success */ bool OpieScreenSaver::save( int level ) { m_level = level; switch ( level ) { case 0: if (( m_on_ac && m_enable_dim_ac ) || ( !m_on_ac && m_enable_dim )) { if (( m_disable_suspend > 0 ) && ( m_backlight_current > 1 ) && !m_use_light_sensor ) setBacklightInternal ( 1 ); // lowest non-off } return true; break; case 1: if (( m_on_ac && m_enable_lightoff_ac ) || ( !m_on_ac && m_enable_lightoff )) { if ( m_disable_suspend > 1 ) setBacklightInternal ( 0 ); // off } return true; break; case 2: if (( m_on_ac && !m_enable_suspend_ac ) || ( !m_on_ac && !m_enable_suspend )) { return true; } if (( m_on_ac && m_onlylcdoff_ac ) || ( !m_on_ac && m_onlylcdoff )) { ODevice::inst ( ) -> setDisplayStatus ( false ); m_lcd_status = false; return true; } // We're going to suspend the whole machine if (( m_disable_suspend > 2 ) && !Network::networkOnline ( )) { // TODO: why is this key F34 hard coded? -- schurig // Does this now only work an devices with a ODevice::filter? QWSServer::sendKeyEvent( 0xffff, Qt::Key_F34, FALSE, TRUE, FALSE ); return true; } break; } return false; } /** * Set intervals in seconds for automatic dimming, light off and suspend * * This function also sets the member variables m_m_enable_dim[_ac], * m_enable_lightoff[_ac], m_enable_suspend[_ac], m_onlylcdoff[_ac] * * @param dim time in seconds to dim, -1 to read value from config file, * 0 to disable * @param lightoff time in seconds to turn LCD backlight off, -1 to * read value from config file, 0 to disable * @param suspend time in seconds to do an APM suspend, -1 to * read value from config file, 0 to disable */ void OpieScreenSaver::setIntervals ( int dim, int lightoff, int suspend ) { Config config ( "apm" ); config. setGroup ( m_on_ac ? "AC" : "Battery" ); int v[ 4 ]; if ( dim < 0 ) dim = config. readNumEntry ( "Dim", m_on_ac ? 60 : 30 ); if ( lightoff < 0 ) lightoff = config. readNumEntry ( "LightOff", m_on_ac ? 120 : 20 ); if ( suspend < 0 ) suspend = config. readNumEntry ( "Suspend", m_on_ac ? 0 : 60 ); if ( m_on_ac ) { m_enable_dim_ac = ( dim > 0 ); m_enable_lightoff_ac = ( lightoff > 0 ); m_enable_suspend_ac = ( suspend > 0 ); m_onlylcdoff_ac = config.readBoolEntry ( "LcdOffOnly", false ); } else { m_enable_dim = ( dim > 0 ); m_enable_lightoff = ( lightoff > 0 ); m_enable_suspend = ( suspend > 0 ); m_onlylcdoff = config.readBoolEntry ( "LcdOffOnly", false ); } - //qDebug("screen saver intervals: %d %d %d", dim, lightoff, suspend); + //odebug << "screen saver intervals: " << dim << " " << lightoff << " " << suspend << "" << oendl; v [ 0 ] = QMAX( 1000 * dim, 100 ); v [ 1 ] = QMAX( 1000 * lightoff, 100 ); v [ 2 ] = QMAX( 1000 * suspend, 100 ); v [ 3 ] = 0; if ( !dim && !lightoff && !suspend ) QWSServer::setScreenSaverInterval( 0 ); else QWSServer::setScreenSaverIntervals( v ); } /** * Set suspend time. Will read the dim and lcd-off times from the config file. * * @param suspend time in seconds to go into APM suspend, -1 to * read value from config file, 0 to disable */ void OpieScreenSaver::setInterval ( int interval ) { setIntervals ( -1, -1, interval ); } void OpieScreenSaver::setMode ( int mode ) { if ( mode > m_disable_suspend ) setInterval ( -1 ); m_disable_suspend = mode; } /** * Set display brightness * * Get's default values for backlight, contrast and light sensor from config file. * * @param bright desired brighness (-1 to use automatic sensor data or value * from config file, -2 to toggle backlight on and off, -3 to * force backlight off) */ void OpieScreenSaver::setBacklight ( int bright ) { // Read from config Config config ( "apm" ); config. setGroup ( m_on_ac ? "AC" : "Battery" ); m_backlight_normal = config. readNumEntry ( "Brightness", m_on_ac ? 255 : 127 ); int contrast = config. readNumEntry ( "Contrast", 127); m_use_light_sensor = config. readBoolEntry ( "LightSensor", false ); //qDebug ( "setBacklight: %d (norm: %d) (ls: %d)", bright, m_backlight_normal, m_use_light_sensor ? 1 : 0 ); killTimers ( ); if (( bright < 0 ) && m_use_light_sensor ) { QStringList sl = config. readListEntry ( "LightSensorData", ';' ); m_sensordata [LS_SensorMin] = 40; m_sensordata [LS_SensorMax] = 215; m_sensordata [LS_LightMin] = 1; m_sensordata [LS_LightMax] = 255; m_sensordata [LS_Steps] = 12; m_sensordata [LS_Interval] = 2000; for ( uint i = 0; i < LS_Count; i++ ) { if ( i < sl. count ( )) m_sensordata [i] = sl [i]. toInt ( ); } if ( m_sensordata [LS_Steps] < 2 ) // sanity check to avoid SIGFPE m_sensordata [LS_Steps] = 2; timerEvent ( 0 ); startTimer ( m_sensordata [LS_Interval] ); } setBacklightInternal ( bright ); ODevice::inst ( )-> setDisplayContrast(contrast); } /** * Internal brightness setting method * * Get's default values for backlight and light sensor from config file. * * @param bright desired brighness (-1 to use automatic sensor data or value * from config file, -2 to toggle backlight on and off, -3 to * force backlight off) */ void OpieScreenSaver::setBacklightInternal ( int bright ) { if ( bright == -3 ) { // Forced on m_backlight_forcedoff = false; bright = -1; } if ( m_backlight_forcedoff && bright != -2 ) return ; if ( bright == -2 ) { // Toggle between off and on bright = m_backlight_current ? 0 : -1; m_backlight_forcedoff = !bright; } if ( bright == -1 ) bright = m_use_light_sensor ? m_backlight_sensor : m_backlight_normal; if ( bright != m_backlight_current ) { ODevice::inst ( )-> setDisplayBrightness ( bright ); m_backlight_current = bright; } } /** * Timer event used for automatic setting the backlight according to a light sensor * and to set the default brightness */ void OpieScreenSaver::timerEvent ( QTimerEvent * ) { int s = ODevice::inst ( )-> readLightSensor ( ) * 256 / ODevice::inst ( )-> lightSensorResolution ( ); if ( s < m_sensordata [LS_SensorMin] ) m_backlight_sensor = m_sensordata [LS_LightMax]; else if ( s >= m_sensordata [LS_SensorMax] ) m_backlight_sensor = m_sensordata [LS_LightMin]; else { int dx = m_sensordata [LS_SensorMax] - m_sensordata [LS_SensorMin]; int dy = m_sensordata [LS_LightMax] - m_sensordata [LS_LightMin]; int stepno = ( s - m_sensordata [LS_SensorMin] ) * m_sensordata [LS_Steps] / dx; // dx is never 0 m_backlight_sensor = m_sensordata [LS_LightMax] - dy * stepno / ( m_sensordata [LS_Steps] - 1 ); } //qDebug ( "f(%d) = %d [%d - %d] -> [%d - %d] / %d", s, m_backlight_sensor, m_sensordata [LS_SensorMin], m_sensordata [LS_SensorMax], m_sensordata [LS_LightMin], m_sensordata [LS_LightMax], m_sensordata [LS_Steps] ); if ( m_level <= 0 ) setBacklightInternal ( -1 ); } /** * Like ODevice::setDisplayStatus(), but keep current state in m_lcd_status. */ void OpieScreenSaver::setDisplayState ( bool on ) { if ( m_lcd_status != on ) { ODevice::inst ( ) -> setDisplayStatus ( on ); m_lcd_status = on; } } /** * Set display to default ac/battery settings when power status changed. */ void OpieScreenSaver::powerStatusChanged ( PowerStatus ps ) { bool newonac = ( ps. acStatus ( ) == PowerStatus::Online ); if ( newonac != m_on_ac ) { m_on_ac = newonac; setInterval ( -1 ); setBacklight ( -1 ); restore ( ); } } diff --git a/core/launcher/server.cpp b/core/launcher/server.cpp index 9a86a80..b9fa1e5 100644 --- a/core/launcher/server.cpp +++ b/core/launcher/server.cpp @@ -1,729 +1,729 @@ /********************************************************************** ** 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 "server.h" #include "serverapp.h" #include "startmenu.h" #include "launcher.h" #include "transferserver.h" #include "qcopbridge.h" #include "irserver.h" #include "packageslave.h" #include "calibrate.h" #include "qrsync.h" #include "syncdialog.h" #include "shutdownimpl.h" #include "applauncher.h" #if 0 #include "suspendmonitor.h" #endif #include "documentlist.h" +/* OPIE */ +#include <opie2/odebug.h> +#include <opie2/odevicebutton.h> +#include <opie2/odevice.h> #include <qtopia/applnk.h> #include <qtopia/private/categories.h> #include <qtopia/mimetype.h> #include <qtopia/config.h> #include <qtopia/resource.h> #include <qtopia/version.h> #include <qtopia/storage.h> - #include <qtopia/qcopenvelope_qws.h> -#include <qwindowsystem_qws.h> -#include <qgfx_qws.h> #include <qtopia/global.h> -//#include <qtopia/custom.h> - -#include <opie2/odevicebutton.h> -#include <opie2/odevice.h> +using namespace Opie::Core; -#include <unistd.h> +/* QT */ #include <qmainwindow.h> #include <qmessagebox.h> #include <qtimer.h> #include <qtextstream.h> +#include <qwindowsystem_qws.h> +#include <qgfx_qws.h> +/* STD */ +#include <unistd.h> #include <stdlib.h> extern QRect qt_maxWindowRect; - -using namespace Opie::Core; static QWidget *calibrate(bool) { #ifdef Q_WS_QWS Calibrate *c = new Calibrate; c->show(); return c; #else return 0; #endif } #define FACTORY(T) \ static QWidget *new##T( bool maximized ) { \ QWidget *w = new T( 0, 0, QWidget::WDestructiveClose | QWidget::WGroupLeader ); \ if ( maximized ) { \ if ( qApp->desktop()->width() <= 350 ) { \ w->showMaximized(); \ } else { \ w->resize( QSize( 300, 300 ) ); \ } \ } \ w->show(); \ return w; \ } #ifdef SINGLE_APP #define APP(a,b,c,d) FACTORY(b) #include "apps.h" #undef APP #endif // SINGLE_APP static Global::Command builtins[] = { #ifdef SINGLE_APP #define APP(a,b,c,d) { a, new##b, c, d }, #include "apps.h" #undef APP #endif /* FIXME defines need to be defined*/ #if !defined(OPIE_NO_BUILTIN_CALIBRATE) { "calibrate", calibrate, 1, 0 }, // No tr #endif #if !defined(OPIE_NO_BUILTIN_SHUTDOWN) { "shutdown", Global::shutdown, 1, 0 }, // No tr // { "run", run, 1, 0 }, // No tr #endif { 0, calibrate, 0, 0 }, }; //--------------------------------------------------------------------------- //=========================================================================== Server::Server() : QWidget( 0, 0, WStyle_Tool | WStyle_Customize ), qcopBridge( 0 ), transferServer( 0 ), packageHandler( 0 ), syncDialog( 0 ) { Global::setBuiltinCommands(builtins); tid_xfer = 0; /* ### FIXME ### */ /* tid_today = startTimer(3600*2*1000);*/ last_today_show = QDate::currentDate(); #if 0 tsmMonitor = new TempScreenSaverMode(); connect( tsmMonitor, SIGNAL(forceSuspend()), qApp, SIGNAL(power()) ); #endif serverGui = new Launcher; serverGui->createGUI(); docList = new DocumentList( serverGui ); appLauncher = new AppLauncher(this); connect(appLauncher, SIGNAL(launched(int,const QString&)), this, SLOT(applicationLaunched(int,const QString&)) ); connect(appLauncher, SIGNAL(terminated(int,const QString&)), this, SLOT(applicationTerminated(int,const QString&)) ); connect(appLauncher, SIGNAL(connected(const QString&)), this, SLOT(applicationConnected(const QString&)) ); storage = new StorageInfo( this ); connect( storage, SIGNAL(disksChanged()), this, SLOT(storageChanged()) ); // start services startTransferServer(); (void) new IrServer( this ); packageHandler = new PackageHandler( this ); connect(qApp, SIGNAL(activate(const Opie::Core::ODeviceButton*,bool)), this,SLOT(activate(const Opie::Core::ODeviceButton*,bool))); setGeometry( -10, -10, 9, 9 ); QCopChannel *channel = new QCopChannel("QPE/System", this); connect(channel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(systemMsg(const QCString&,const QByteArray&)) ); QCopChannel *tbChannel = new QCopChannel( "QPE/TaskBar", this ); connect( tbChannel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(receiveTaskBar(const QCString&,const QByteArray&)) ); connect( qApp, SIGNAL(prepareForRestart()), this, SLOT(terminateServers()) ); connect( qApp, SIGNAL(timeChanged()), this, SLOT(pokeTimeMonitors()) ); preloadApps(); } void Server::show() { ServerApplication::login(TRUE); QWidget::show(); } Server::~Server() { serverGui->destroyGUI(); delete docList; delete qcopBridge; delete transferServer; delete serverGui; #if 0 delete tsmMonitor; #endif } static bool hasVisibleWindow(const QString& clientname, bool partial) { #ifdef QWS const QList<QWSWindow> &list = qwsServer->clientWindows(); QWSWindow* w; for (QListIterator<QWSWindow> it(list); (w=it.current()); ++it) { if ( w->client()->identity() == clientname ) { if ( partial && !w->isFullyObscured() ) return TRUE; if ( !partial && !w->isFullyObscured() && !w->isPartiallyObscured() ) { # if QT_VERSION < 0x030000 QRect mwr = qt_screen->mapToDevice(qt_maxWindowRect, QSize(qt_screen->width(),qt_screen->height()) ); # else QRect mwr = qt_maxWindowRect; # endif if ( mwr.contains(w->requested().boundingRect()) ) return TRUE; } } } #endif return FALSE; } void Server::activate(const ODeviceButton* button, bool held) { Global::terminateBuiltin("calibrate"); // No tr OQCopMessage om; if ( held ) { om = button->heldAction(); } else { om = button->pressedAction(); } if ( om.channel() != "ignore" ) om.send(); // A button with no action defined, will return a null ServiceRequest. Don't attempt // to send/do anything with this as it will crash /* ### FIXME */ #if 0 if ( !sr.isNull() ) { QString app = sr.app(); bool vis = hasVisibleWindow(app, app != "qpe"); if ( sr.message() == "raise()" && vis ) { sr.setMessage("nextView()"); } else { // "back door" sr << (int)vis; } sr.send(); } #endif } #ifdef Q_WS_QWS typedef struct KeyOverride { ushort scan_code; QWSServer::KeyMap map; }; static const KeyOverride jp109keys[] = { { 0x03, { Qt::Key_2, '2' , 0x22 , 0xffff } }, { 0x07, { Qt::Key_6, '6' , '&' , 0xffff } }, { 0x08, { Qt::Key_7, '7' , '\'' , 0xffff } }, { 0x09, { Qt::Key_8, '8' , '(' , 0xffff } }, { 0x0a, { Qt::Key_9, '9' , ')' , 0xffff } }, { 0x0b, { Qt::Key_0, '0' , 0xffff , 0xffff } }, { 0x0c, { Qt::Key_Minus, '-' , '=' , 0xffff } }, { 0x0d, { Qt::Key_AsciiCircum,'^' , '~' , '^' - 64 } }, { 0x1a, { Qt::Key_At, '@' , '`' , 0xffff } }, { 0x1b, { Qt::Key_BraceLeft, '[' , '{' , '[' - 64 } }, { 0x27, { Qt::Key_Semicolon, ';' , '+' , 0xffff } }, { 0x28, { Qt::Key_Colon, ':' , '*' , 0xffff } }, { 0x29, { Qt::Key_Zenkaku_Hankaku, 0xffff , 0xffff , 0xffff } }, { 0x2b, { Qt::Key_BraceRight, ']' , '}' , ']'-64 } }, { 0x70, { Qt::Key_Hiragana_Katakana, 0xffff , 0xffff , 0xffff } }, { 0x73, { Qt::Key_Backslash, '\\' , '_' , 0xffff } }, { 0x79, { Qt::Key_Henkan, 0xffff , 0xffff , 0xffff } }, { 0x7b, { Qt::Key_Muhenkan, 0xffff , 0xffff , 0xffff } }, { 0x7d, { Qt::Key_yen, 0x00a5 , '|' , 0xffff } }, { 0x00, { 0, 0xffff , 0xffff , 0xffff } } }; bool Server::setKeyboardLayout( const QString &kb ) { //quick demo version that can be extended QIntDict<QWSServer::KeyMap> *om = 0; if ( kb == "us101" ) { // No tr om = 0; } else if ( kb == "jp109" ) { om = new QIntDict<QWSServer::KeyMap>(37); const KeyOverride *k = jp109keys; while ( k->scan_code ) { om->insert( k->scan_code, &k->map ); k++; } } QWSServer::setOverrideKeys( om ); return TRUE; } #endif void Server::systemMsg(const QCString &msg, const QByteArray &data) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "securityChanged()" ) { if ( transferServer ) transferServer->authorizeConnections(); if ( qcopBridge ) qcopBridge->authorizeConnections(); } /* ### FIXME support TempScreenSaverMode */ #if 0 else if ( msg == "setTempScreenSaverMode(int,int)" ) { int mode, pid; stream >> mode >> pid; tsmMonitor->setTempMode(mode, pid); } #endif else if ( msg == "linkChanged(QString)" ) { QString link; stream >> link; - qDebug( "desktop.cpp systemMsg -> linkchanged( %s )", link.latin1() ); + odebug << "desktop.cpp systemMsg -> linkchanged( " << link << " )" << oendl; docList->linkChanged(link); } else if ( msg == "serviceChanged(QString)" ) { MimeType::updateApplications(); } else if ( msg == "mkdir(QString)" ) { QString dir; stream >> dir; if ( !dir.isEmpty() ) mkdir( dir ); } else if ( msg == "rdiffGenSig(QString,QString)" ) { QString baseFile, sigFile; stream >> baseFile >> sigFile; QRsync::generateSignature( baseFile, sigFile ); } else if ( msg == "rdiffGenDiff(QString,QString,QString)" ) { QString baseFile, sigFile, deltaFile; stream >> baseFile >> sigFile >> deltaFile; QRsync::generateDiff( baseFile, sigFile, deltaFile ); } else if ( msg == "rdiffApplyPatch(QString,QString)" ) { QString baseFile, deltaFile; stream >> baseFile >> deltaFile; if ( !QFile::exists( baseFile ) ) { QFile f( baseFile ); f.open( IO_WriteOnly ); f.close(); } QRsync::applyDiff( baseFile, deltaFile ); #ifndef QT_NO_COP QCopEnvelope e( "QPE/Desktop", "patchApplied(QString)" ); e << baseFile; #endif } else if ( msg == "rdiffCleanup()" ) { mkdir( "/tmp/rdiff" ); QDir dir; dir.setPath( "/tmp/rdiff" ); QStringList entries = dir.entryList(); for ( QStringList::Iterator it = entries.begin(); it != entries.end(); ++it ) dir.remove( *it ); } else if ( msg == "sendHandshakeInfo()" ) { QString home = getenv( "HOME" ); #ifndef QT_NO_COP QCopEnvelope e( "QPE/Desktop", "handshakeInfo(QString,bool)" ); e << home; int locked = (int) ServerApplication::screenLocked(); e << locked; #endif } /* * QtopiaDesktop relies on the major number * to start with 1. We're at 0.9 * so wee need to fake at least 1.4 to be able * to sync with QtopiaDesktop1.6 */ else if ( msg == "sendVersionInfo()" ) { QCopEnvelope e( "QPE/Desktop", "versionInfo(QString,QString)" ); /* ### FIXME Architecture ### */ e << QString::fromLatin1("1.7") << "Uncustomized Device"; } else if ( msg == "sendCardInfo()" ) { #ifndef QT_NO_COP QCopEnvelope e( "QPE/Desktop", "cardInfo(QString)" ); #endif storage->update(); const QList<FileSystem> &fs = storage->fileSystems(); QListIterator<FileSystem> it ( fs ); QString s; QString homeDir = getenv("HOME"); QString homeFs, homeFsPath; for ( ; it.current(); ++it ) { int k4 = (*it)->blockSize()/256; if ( (*it)->isRemovable() ) { s += (*it)->name() + "=" + (*it)->path() + "/Documents " // No tr + QString::number( (*it)->availBlocks() * k4/4 ) + "K " + (*it)->options() + ";"; } else if ( homeDir.contains( (*it)->path() ) && (*it)->path().length() > homeFsPath.length() ) { homeFsPath = (*it)->path(); homeFs = (*it)->name() + "=" + homeDir + "/Documents " // No tr + QString::number( (*it)->availBlocks() * k4/4 ) + "K " + (*it)->options() + ";"; } } if ( !homeFs.isEmpty() ) s += homeFs; #ifndef QT_NO_COP e << s; #endif } else if ( msg == "sendSyncDate(QString)" ) { QString app; stream >> app; Config cfg( "qpe" ); cfg.setGroup("SyncDate"); #ifndef QT_NO_COP QCopEnvelope e( "QPE/Desktop", "syncDate(QString,QString)" ); e << app << cfg.readEntry( app ); #endif //qDebug("QPE/System sendSyncDate for %s: response %s", app.latin1(), //cfg.readEntry( app ).latin1() ); } else if ( msg == "setSyncDate(QString,QString)" ) { QString app, date; stream >> app >> date; Config cfg( "qpe" ); cfg.setGroup("SyncDate"); cfg.writeEntry( app, date ); - //qDebug("setSyncDate(QString,QString) %s %s", app.latin1(), date.latin1()); + //odebug << "setSyncDate(QString,QString) " << app << " " << date << "" << oendl; } else if ( msg == "startSync(QString)" ) { QString what; stream >> what; delete syncDialog; syncDialog = new SyncDialog( this, what ); syncDialog->show(); connect( syncDialog, SIGNAL(cancel()), SLOT(cancelSync()) ); } else if ( msg == "stopSync()") { delete syncDialog; syncDialog = 0; } else if (msg == "restoreDone(QString)") { docList->restoreDone(); } else if ( msg == "getAllDocLinks()" ) { docList->sendAllDocLinks(); } #ifdef Q_WS_QWS else if ( msg == "setMouseProto(QString)" ) { QString mice; stream >> mice; setenv("QWS_MOUSE_PROTO",mice.latin1(),1); qwsServer->openMouse(); } else if ( msg == "setKeyboard(QString)" ) { QString kb; stream >> kb; setenv("QWS_KEYBOARD",kb.latin1(),1); qwsServer->openKeyboard(); } else if ( msg == "setKeyboardAutoRepeat(int,int)" ) { int delay, period; stream >> delay >> period; qwsSetKeyboardAutoRepeat( delay, period ); Config cfg( "qpe" ); cfg.setGroup("Keyboard"); cfg.writeEntry( "RepeatDelay", delay ); cfg.writeEntry( "RepeatPeriod", period ); } else if ( msg == "setKeyboardLayout(QString)" ) { QString kb; stream >> kb; setKeyboardLayout( kb ); Config cfg( "qpe" ); cfg.setGroup("Keyboard"); cfg.writeEntry( "Layout", kb ); } else if ( msg == "autoStart(QString)" ) { QString appName; stream >> appName; Config cfg( "autostart" ); cfg.setGroup( "AutoStart" ); if ( appName.compare("clear") == 0){ cfg.writeEntry("Apps", ""); } } else if ( msg == "autoStart(QString,QString)" ) { QString modifier, appName; stream >> modifier >> appName; Config cfg( "autostart" ); cfg.setGroup( "AutoStart" ); if ( modifier.compare("add") == 0 ){ // only add if appname is entered if (!appName.isEmpty()) { cfg.writeEntry("Apps", appName); } } else if (modifier.compare("remove") == 0 ) { // need to change for multiple entries // actually remove is right now simular to clear, but in future there // should be multiple apps in autostart possible. QString checkName; checkName = cfg.readEntry("Apps", ""); if (checkName == appName) { cfg.writeEntry("Apps", ""); } } // case the autostart feature should be delayed } else if ( msg == "autoStart(QString,QString,QString)") { QString modifier, appName, delay; stream >> modifier >> appName >> delay; Config cfg( "autostart" ); cfg.setGroup( "AutoStart" ); if ( modifier.compare("add") == 0 ){ // only add it appname is entered if (!appName.isEmpty()) { cfg.writeEntry("Apps", appName); cfg.writeEntry("Delay", delay); } } else { } } #endif } void Server::receiveTaskBar(const QCString &msg, const QByteArray &data) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "reloadApps()" ) { docList->reloadAppLnks(); } else if ( msg == "soundAlarm()" ) { ServerApplication::soundAlarm(); } else if ( msg == "setLed(int,bool)" ) { int led, status; stream >> led >> status; QValueList <OLed> ll = ODevice::inst ( )-> ledList ( ); if ( ll. count ( )) { OLed l = ll. contains ( Led_Mail ) ? Led_Mail : ll [0]; bool canblink = ODevice::inst ( )-> ledStateList ( l ). contains ( Led_BlinkSlow ); ODevice::inst ( )-> setLedState ( l, status ? ( canblink ? Led_BlinkSlow : Led_On ) : Led_Off ); } } } void Server::cancelSync() { #ifndef QT_NO_COP QCopEnvelope e( "QPE/Desktop", "cancelSync()" ); #endif delete syncDialog; syncDialog = 0; } bool Server::mkdir(const QString &localPath) { QDir fullDir(localPath); if (fullDir.exists()) return true; // at this point the directory doesn't exist // go through the directory tree and start creating the direcotories // that don't exist; if we can't create the directories, return false QString dirSeps = "/"; int dirIndex = localPath.find(dirSeps); QString checkedPath; // didn't find any seps; weird, use the cur dir instead if (dirIndex == -1) { - //qDebug("No seperators found in path %s", localPath.latin1()); + //odebug << "No seperators found in path " << localPath << "" << oendl; checkedPath = QDir::currentDirPath(); } while (checkedPath != localPath) { // no more seperators found, use the local path if (dirIndex == -1) checkedPath = localPath; else { // the next directory to check checkedPath = localPath.left(dirIndex) + "/"; // advance the iterator; the next dir seperator dirIndex = localPath.find(dirSeps, dirIndex+1); } QDir checkDir(checkedPath); if (!checkDir.exists()) { - //qDebug("mkdir making dir %s", checkedPath.latin1()); + //odebug << "mkdir making dir " << checkedPath << "" << oendl; if (!checkDir.mkdir(checkedPath)) { - qDebug("Unable to make directory %s", checkedPath.latin1()); + odebug << "Unable to make directory " << checkedPath << "" << oendl; return FALSE; } } } return TRUE; } void Server::styleChange( QStyle &s ) { QWidget::styleChange( s ); } void Server::startTransferServer() { if ( !qcopBridge ) { // start qcop bridge server qcopBridge = new QCopBridge( 4243 ); if ( qcopBridge->ok() ) { // ... OK connect( qcopBridge, SIGNAL(connectionClosed(const QHostAddress&)), this, SLOT(syncConnectionClosed(const QHostAddress&)) ); } else { delete qcopBridge; qcopBridge = 0; } } if ( !transferServer ) { // start transfer server transferServer = new TransferServer( 4242 ); if ( transferServer->ok() ) { // ... OK } else { delete transferServer; transferServer = 0; } } if ( !transferServer || !qcopBridge ) tid_xfer = startTimer( 2000 ); } void Server::timerEvent( QTimerEvent *e ) { if ( e->timerId() == tid_xfer ) { killTimer( tid_xfer ); tid_xfer = 0; startTransferServer(); } /* ### FIXME today startin */ #if 0 else if ( e->timerId() == tid_today ) { QDate today = QDate::currentDate(); if ( today != last_today_show ) { last_today_show = today; Config cfg("today"); cfg.setGroup("Start"); #ifndef QPE_DEFAULT_TODAY_MODE #define QPE_DEFAULT_TODAY_MODE "Never" #endif if ( cfg.readEntry("Mode",QPE_DEFAULT_TODAY_MODE) == "Daily" ) { QCopEnvelope env(Service::channel("today"),"raise()"); } } } #endif } void Server::terminateServers() { delete transferServer; delete qcopBridge; transferServer = 0; qcopBridge = 0; } void Server::syncConnectionClosed( const QHostAddress & ) { - qDebug( "Lost sync connection" ); + odebug << "Lost sync connection" << oendl; delete syncDialog; syncDialog = 0; } void Server::pokeTimeMonitors() { #if 0 // inform all TimeMonitors QStrList tms = Service::channels("TimeMonitor"); for (const char* ch = tms.first(); ch; ch=tms.next()) { QString t = getenv("TZ"); QCopEnvelope e(ch, "timeChange(QString)"); e << t; } #endif } void Server::applicationLaunched(int, const QString &app) { serverGui->applicationStateChanged( app, ServerInterface::Launching ); } void Server::applicationTerminated(int pid, const QString &app) { serverGui->applicationStateChanged( app, ServerInterface::Terminated ); #if 0 tsmMonitor->applicationTerminated( pid ); #endif } void Server::applicationConnected(const QString &app) { serverGui->applicationStateChanged( app, ServerInterface::Running ); } void Server::storageChanged() { system( "opie-update-symlinks" ); serverGui->storageChanged( storage->fileSystems() ); docList->storageChanged(); } void Server::preloadApps() { Config cfg("Launcher"); cfg.setGroup("Preload"); QStringList apps = cfg.readListEntry("Apps",','); for (QStringList::ConstIterator it=apps.begin(); it!=apps.end(); ++it) { #ifndef QT_NO_COP QCopEnvelope e("QPE/Application/"+(*it).local8Bit(), "enablePreload()"); #endif } } diff --git a/core/launcher/serverapp.cpp b/core/launcher/serverapp.cpp index e4e16f2..cf543ce 100644 --- a/core/launcher/serverapp.cpp +++ b/core/launcher/serverapp.cpp @@ -1,314 +1,314 @@ /********************************************************************** ** Copyright (C) 2000-2003 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 "serverapp.h" +#include "screensaver.h" +/* OPIE */ +#include <opie2/odebug.h> #include <opie2/odevice.h> - #include <qtopia/password.h> #include <qtopia/config.h> #include <qtopia/power.h> #ifdef Q_WS_QWS #include <qtopia/qcopenvelope_qws.h> #endif #include <qtopia/global.h> -//#include <qtopia/custom.h> +using namespace Opie::Core; +/* QT */ #ifdef Q_WS_QWS #include <qgfx_qws.h> #endif -#ifdef Q_OS_WIN32 -#include <io.h> -#include <process.h> -#else -#include <unistd.h> -#endif #include <qmessagebox.h> #include <qtimer.h> #include <qpainter.h> #include <qfile.h> #include <qpixmapcache.h> +/* STD */ +#ifdef Q_OS_WIN32 +#include <io.h> +#include <process.h> +#else +#include <unistd.h> +#endif #include <stdlib.h> -#include "screensaver.h" static ServerApplication *serverApp = 0; static int loggedin=0; -using namespace Opie; - -using namespace Opie::Core; QCopKeyRegister::QCopKeyRegister() : m_keyCode( 0 ) { } QCopKeyRegister::QCopKeyRegister( int k, const QCString& c, const QCString& m ) :m_keyCode( k ), m_channel( c ), m_message( m ) { } int QCopKeyRegister::keyCode()const { return m_keyCode; } QCString QCopKeyRegister::channel()const { return m_channel; } QCString QCopKeyRegister::message()const { return m_message; } bool QCopKeyRegister::send() { if (m_channel.isNull() ) return false; QCopEnvelope( m_channel, m_message ); return true; } //--------------------------------------------------------------------------- /* Priority is number of alerts that are needed to pop up alert. */ class DesktopPowerAlerter : public QMessageBox { Q_OBJECT public: DesktopPowerAlerter( QWidget *parent, const char *name = 0 ) : QMessageBox( tr("Battery Status"), tr("Low Battery"), QMessageBox::Critical, QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton, QMessageBox::NoButton, parent, name, FALSE ) { currentPriority = INT_MAX; alertCount = 0; } void alert( const QString &text, int priority ); void hideEvent( QHideEvent * ); private: int currentPriority; int alertCount; }; void DesktopPowerAlerter::alert( const QString &text, int priority ) { alertCount++; if ( alertCount < priority ) return; if ( priority > currentPriority ) return; currentPriority = priority; setText( text ); show(); } void DesktopPowerAlerter::hideEvent( QHideEvent *e ) { QMessageBox::hideEvent( e ); alertCount = 0; currentPriority = INT_MAX; } //--------------------------------------------------------------------------- KeyFilter::KeyFilter(QObject* parent) : QObject(parent), held_tid(0), heldButton(0) { /* We don't do this cause it would interfere with ODevice */ #if 0 qwsServer->setKeyboardFilter(this); #endif } void KeyFilter::timerEvent(QTimerEvent* e) { if ( e->timerId() == held_tid ) { killTimer(held_tid); // button held if ( heldButton ) { emit activate(heldButton, TRUE); heldButton = 0; } held_tid = 0; } } void KeyFilter::registerKey( const QCopKeyRegister& key ) { m_keys.insert( key.keyCode(), key ); } void KeyFilter::unregisterKey( const QCopKeyRegister& key ) { m_keys.remove( key.keyCode() ); } bool KeyFilter::keyRegistered( int key ) { /* * Check if we've a key registered */ if ( !m_keys[key].send()) return false; else return true; } bool KeyFilter::checkButtonAction(bool db, int keycode, int press, int autoRepeat) { if ( !loggedin // Permitted keys && keycode != Key_F34 // power && keycode != Key_F30 // select && keycode != Key_Enter && keycode != Key_Return && keycode != Key_Space && keycode != Key_Left && keycode != Key_Right && keycode != Key_Up && keycode != Key_Down ) return TRUE; /* check if it was registered */ if (!db ) { if (keycode != 0 &&press && !autoRepeat && keyRegistered(keycode) ) return true; }else { // First check to see if DeviceButtonManager knows something about this button: const ODeviceButton* button = ODevice::inst()->buttonForKeycode(keycode); if (button && !autoRepeat) { if ( held_tid ) { killTimer(held_tid); held_tid = 0; } if ( button->heldAction().isNull() ) { if ( press ) emit activate(button, FALSE); } else if ( press ) { heldButton = button; held_tid = startTimer( ODevice::inst ()->buttonHoldTime () ); } else if ( heldButton ) { heldButton = 0; emit activate(button, FALSE); } QWSServer::screenSaverActivate(FALSE); return TRUE; } return false; } if ( keycode == HardKey_Suspend ) { if ( press ) emit power(); return TRUE; } if ( keycode == HardKey_Backlight ) { if ( press ) emit backlight(); return TRUE; } if ( keycode == Key_F32 ) { #ifndef QT_NO_COP if ( press ) QCopEnvelope e( "QPE/Desktop", "startSync()" ); #endif return TRUE; } if ( keycode == Key_F31 ) { if ( press ) emit symbol(); QWSServer::screenSaverActivate(FALSE); return TRUE; } if ( keycode == Key_NumLock ) if ( press ) emit numLockStateToggle(); if ( keycode == Key_CapsLock ) if ( press ) emit capsLockStateToggle(); if ( serverApp ) serverApp->keyClick(keycode,press,autoRepeat); return FALSE; } enum MemState { MemUnknown, MemVeryLow, MemLow, MemNormal } memstate=MemUnknown; #if defined(QPE_HAVE_MEMALERTER) QPE_MEMALERTER_IMPL #endif //--------------------------------------------------------------------------- bool ServerApplication::doRestart = FALSE; bool ServerApplication::allowRestart = TRUE; bool ServerApplication::ms_is_starting = TRUE; void ServerApplication::switchLCD( bool on ) { if ( !qApp ) return; ServerApplication *dapp = ServerApplication::me() ; if ( !dapp-> m_screensaver ) return; if ( on ) { dapp-> m_screensaver-> setDisplayState ( true ); dapp-> m_screensaver-> setBacklight ( -3 ); }else dapp-> m_screensaver-> setDisplayState ( false ); } ServerApplication::ServerApplication( int& argc, char **argv, Type t ) : QPEApplication( argc, argv, t ) { ms_is_starting = true; // We know we'll have lots of cached pixmaps due to App/DocLnks QPixmapCache::setCacheLimit(512); m_ps = new PowerStatus; m_ps_last = new PowerStatus; pa = new DesktopPowerAlerter( 0 ); m_apm_timer = new QTimer( this ); connect(m_apm_timer, SIGNAL( timeout() ), this, SLOT( apmTimeout() ) ); reloadPowerWarnSettings(); QCopChannel *channel = new QCopChannel( "QPE/System", this ); connect(channel, SIGNAL(received(const QCString&,const QByteArray&) ), this, SLOT(systemMessage(const QCString&,const QByteArray&) ) ); channel = new QCopChannel("QPE/Launcher", this ); connect(channel, SIGNAL(received(const QCString&,const QByteArray&) ), this, SLOT(launcherMessage(const QCString&,const QByteArray&) ) ); m_screensaver = new OpieScreenSaver(); m_screensaver->setInterval( -1 ); QWSServer::setScreenSaver( m_screensaver ); @@ -603,261 +603,261 @@ void ServerApplication::togglePower() execAutoStart(m_suspendTime); //qcopBridge->closeOpenConnections(); excllock = false; } void ServerApplication::toggleLight() { #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "setBacklight(int)"); e << -2; // toggle #endif } /* * We still listen to key events but handle them in * a special class */ bool ServerApplication::eventFilter( QObject *o, QEvent *e) { if ( e->type() != QEvent::KeyPress && e->type() != QEvent::KeyRelease ) return QPEApplication::eventFilter( o, e ); QKeyEvent *ke = static_cast<QKeyEvent*>( e ); if ( kf->checkButtonAction( true, ke->key(), e->type() == QEvent::KeyPress, ke-> isAutoRepeat() )) return true; return QPEApplication::eventFilter( o, e ); } #ifdef Q_WS_QWS bool ServerApplication::qwsEventFilter( QWSEvent *e ) { checkMemory(); if ( e->type == QWSEvent::Mouse ) { QWSMouseEvent *me = (QWSMouseEvent *)e; static bool up = TRUE; if ( me->simpleData.state&LeftButton ) { if ( up ) { up = FALSE; screenClick(TRUE); } } else if ( !up ) { up = TRUE; screenClick(FALSE); } }else if ( e->type == QWSEvent::Key ) { QWSKeyEvent * ke = static_cast<QWSKeyEvent*>( e ); if ( kf->checkButtonAction( false, ke-> simpleData.keycode, ke-> simpleData.is_press, ke-> simpleData.is_auto_repeat ) ) return true; } return QPEApplication::qwsEventFilter( e ); } #endif /* ### FIXME libqtopia Plugin Safe Mode */ void ServerApplication::showSafeMode() { #if 0 if ( QMessageBox::warning(0, tr("Safe Mode"), tr("<P>A system startup error occurred, " "and the system is now in Safe Mode. " "Plugins are not loaded in Safe Mode. " "You can use the Plugin Manager to " "disable plugins that cause system error."), tr("OK"), tr("Plugin Manager..."), 0) == 1 ) { Global::execute( "pluginmanager" ); } #endif } void ServerApplication::clearSafeMode() { #if 0 // If we've been running OK for a while then we won't bother going into // safe mode immediately on the next crash. Config cfg( "PluginLoader" ); cfg.setGroup( "Global" ); QString mode = cfg.readEntry( "Mode", "Normal" ); if ( mode == "MaybeSafe" ) { cfg.writeEntry( "Mode", "Normal" ); } #endif } void ServerApplication::shutdown() { if ( type() != GuiServer ) return; ShutdownImpl *sd = new ShutdownImpl( 0, 0, WDestructiveClose ); connect( sd, SIGNAL(shutdown(ShutdownImpl::Type)), this, SLOT(shutdown(ShutdownImpl::Type)) ); QPEApplication::showWidget( sd ); } void ServerApplication::shutdown( ShutdownImpl::Type t ) { char *opt = 0; switch ( t ) { case ShutdownImpl::ShutdownSystem: opt = "-h"; // fall through case ShutdownImpl::RebootSystem: if ( opt == 0 ) opt = "-r"; if ( execl( "/sbin/shutdown", "shutdown", opt, "now", ( void* ) 0) < 0 ) perror("shutdown"); // ::syslog ( LOG_ERR, "Erroring execing shutdown\n" ); break; case ShutdownImpl::RestartDesktop: restart(); break; case ShutdownImpl::TerminateDesktop: prepareForTermination( FALSE ); // This is a workaround for a Qt bug // clipboard applet has to stop its poll timer, or Qt/E // will hang on quit() right before it emits aboutToQuit() emit aboutToQuit ( ); quit(); break; } } void ServerApplication::restart() { if ( allowRestart ) { /* * Applets and restart is a problem. Some applets delete * their widgets even if ownership gets transfered to the * parent (Systray ) but deleting the applet may be unsafe * as well ( double deletion ). Some have topLevel widgets * and when we dlclose and then delete the widget we will * crash and an crash during restart is not nice */ #ifdef ALL_APPLETS_ON_THIS_WORLD_ARE_FIXED /* same as above */ emit aboutToQuit(); prepareForTermination(TRUE); doRestart = TRUE; quit(); #else prepareForTermination( true ); for ( int fd = 3; fd < 100; fd++ ) close( fd ); execl( ( qpeDir() + "/bin/qpe" ).latin1(), "qpe", 0 ); exit( 1 ); #endif } } void ServerApplication::rereadVolumes() { Config cfg( "qpe" ); cfg. setGroup ( "Volume" ); m_screentap_sound = cfg. readBoolEntry ( "TouchSound" ); m_keyclick_sound = cfg. readBoolEntry ( "KeySound" ); m_alarm_sound = cfg. readBoolEntry ( "AlarmSound" ); } void ServerApplication::checkMemory() { #if defined(QPE_HAVE_MEMALERTER) static bool ignoreNormal=TRUE; static bool existingMessage=FALSE; if(existingMessage) return; // don't show a second message while still on first existingMessage = TRUE; switch ( memstate ) { case MemUnknown: break; case MemLow: memstate = MemUnknown; if ( !recoverMemory() ) { QMessageBox::warning( 0 , tr("Memory Status"), tr("Memory Low\nPlease save data.") ); ignoreNormal = FALSE; } break; case MemNormal: memstate = MemUnknown; if ( !ignoreNormal ) { ignoreNormal = TRUE; QMessageBox::information ( 0 , tr("Memory Status"), "Memory OK" ); } break; case MemVeryLow: memstate = MemUnknown; QMessageBox::critical( 0 , tr("Memory Status"), tr("Critical Memory Shortage\n" "Please end this application\n" "immediately.") ); recoverMemory(); } existingMessage = FALSE; #endif } bool ServerApplication::recoverMemory() { return FALSE; } void ServerApplication::keyClick(int , bool press, bool ) { if ( press && m_keyclick_sound ) ODevice::inst() -> playKeySound(); } void ServerApplication::screenClick(bool press) { if ( press && m_screentap_sound ) ODevice::inst() -> playTouchSound(); } void ServerApplication::soundAlarm() { if ( me ()->m_alarm_sound ) ODevice::inst()->playAlarmSound(); } ServerApplication *ServerApplication::me ( ) { return static_cast<ServerApplication*>( qApp ); } bool ServerApplication::isStarting() { return ms_is_starting; } int ServerApplication::exec() { ms_is_starting = true; - qDebug("Serverapp - exec"); + odebug << "Serverapp - exec" << oendl; return QPEApplication::exec(); } #include "serverapp.moc" diff --git a/core/launcher/suspendmonitor.cpp b/core/launcher/suspendmonitor.cpp index f555e84..50bc56f 100644 --- a/core/launcher/suspendmonitor.cpp +++ b/core/launcher/suspendmonitor.cpp @@ -1,167 +1,167 @@ /********************************************************************** ** 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 <qtopia/qcopenvelope_qws.h> #include <qtopia/qpeapplication.h> #include "suspendmonitor.h" #ifdef QTOPIA_MAX_SCREEN_DISABLE_TIME #define QTOPIA_MIN_SCREEN_DISABLE_TIME ((int) 300) // min 5 minutes before forced suspend kicks in #endif TempScreenSaverMonitor::TempScreenSaverMonitor(QObject *parent, const char *name) : QObject(parent, name) { currentMode = QPEApplication::Enable; timerId = 0; } void TempScreenSaverMonitor::setTempMode(int mode, int pid) { removeOld(pid); switch(mode) { case QPEApplication::Disable: sStatus[0].append(pid); break; case QPEApplication::DisableLightOff: sStatus[1].append(pid); break; case QPEApplication::DisableSuspend: sStatus[2].append(pid); break; case QPEApplication::Enable: break; default: - qWarning("Unrecognized temp power setting. Ignored"); + owarn << "Unrecognized temp power setting. Ignored" << oendl; return; } updateAll(); } // Returns true if app had set a temp Mode earlier bool TempScreenSaverMonitor::removeOld(int pid) { QValueList<int>::Iterator it; for (int i = 0; i < 3; i++) { it = sStatus[i].find(pid); if ( it != sStatus[i].end() ) { sStatus[i].remove( it ); return TRUE; } } return FALSE; } void TempScreenSaverMonitor::updateAll() { int mode = QPEApplication::Enable; if ( sStatus[0].count() ) { mode = QPEApplication::Disable; } else if ( sStatus[1].count() ) { mode = QPEApplication::DisableLightOff; } else if ( sStatus[2].count() ) { mode = QPEApplication::DisableSuspend; } if ( mode != currentMode ) { #ifdef QTOPIA_MAX_SCREEN_DISABLE_TIME if ( currentMode == QPEApplication::Enable) { int tid = timerValue(); if ( tid ) timerId = startTimer( tid * 1000 ); } else if ( mode == QPEApplication::Enable ) { if ( timerId ) { killTimer(timerId); timerId = 0; } } #endif currentMode = mode; QCopEnvelope("QPE/System", "setScreenSaverMode(int)") << mode; } } void TempScreenSaverMonitor::applicationTerminated(int pid) { if ( removeOld(pid) ) updateAll(); } int TempScreenSaverMonitor::timerValue() { int tid = 0; #ifdef QTOPIA_MAX_SCREEN_DISABLE_TIME tid = QTOPIA_MAX_SCREEN_DISABLE_TIME; char *env = getenv("QTOPIA_DISABLED_APM_TIMEOUT"); if ( !env ) return tid; QString strEnv = env; bool ok = FALSE; int envTime = strEnv.toInt(&ok); if ( ok ) { if ( envTime < 0 ) return 0; else if ( envTime <= QTOPIA_MIN_SCREEN_DISABLE_TIME ) return tid; else return envTime; } #endif return tid; } void TempScreenSaverMonitor::timerEvent(QTimerEvent *t) { #ifdef QTOPIA_MAX_SCREEN_DISABLE_TIME if ( timerId && (t->timerId() == timerId) ) { /* Clean up */ killTimer(timerId); timerId = 0; currentMode = QPEApplication::Enable; QCopEnvelope("QPE/System", "setScreenSaverMode(int)") << currentMode; // signal starts on a merry-go-round, which ends up in Desktop::togglePower() emit forceSuspend(); // if we have apm we are asleep at this point, next line will be executed when we // awake from suspend. if ( QFile::exists( "/proc/apm" ) ) { QTime t; t = t.addSecs( timerValue() ); QString str = tr("<qt>The running applications disabled the screen saver for more than the allowed time (%1).<p>The system was forced to suspend</p></qt>").arg( t.toString() ); QMessageBox::information(0, tr("Forced suspend"), str); } // Reset all requests. for (int i = 0; i < 3; i++) sStatus[i].clear(); updateAll(); } #else Q_UNUSED(t); #endif } diff --git a/core/launcher/systray.cpp b/core/launcher/systray.cpp index 6cc1446..3c72d25 100644 --- a/core/launcher/systray.cpp +++ b/core/launcher/systray.cpp @@ -1,152 +1,150 @@ /********************************************************************** ** 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 "systray.h" + +/* OPIE */ +#include <opie2/odebug.h> #include <qtopia/qpeapplication.h> #include <qtopia/qlibrary.h> #include <qtopia/config.h> +using namespace Opie::Core; +/* QT */ #include <qlayout.h> #include <qdir.h> -#include "systray.h" - +/* STD */ #include <stdlib.h> -/* ### Single build floppies ### */ -#if 0 -#ifdef QT_NO_COMPONENTS -#include "../plugins/applets/clockapplet/clockappletimpl.h" -#endif -#endif - SysTray::SysTray( QWidget *parent ) : QFrame( parent ), layout(0) { //setFrameStyle( QFrame::Panel | QFrame::Sunken ); loadApplets(); } SysTray::~SysTray() { clearApplets(); } static int compareAppletPositions(const void *a, const void *b) { const TaskbarApplet* aa = *(const TaskbarApplet**)a; const TaskbarApplet* ab = *(const TaskbarApplet**)b; int d = ab->iface->position() - aa->iface->position(); if ( d ) return d; return QString::compare(ab->name,aa->name); } void SysTray::loadApplets() { hide(); clearApplets(); addApplets(); } void SysTray::clearApplets() { #ifndef QT_NO_COMPONENTS /* * Note on clearing. SOme applets delete their * applets themselves some don't do it * and on restart this can crash. If we delete it * here we might end up in a double deletion. We could * use QGuardedPtr but that would be one QOBject * for every applet more but only useful for restart */ QValueList<TaskbarApplet>::Iterator mit; for ( mit = appletList.begin(); mit != appletList.end(); ++mit ) { (*mit).iface->release(); (*mit).library->unload(); delete (*mit).library; } #endif appletList.clear(); if ( layout ) delete layout; layout = new QHBoxLayout( this, 0, 1 ); layout->setAutoAdd(TRUE); } void SysTray::addApplets() { hide(); #ifndef QT_NO_COMPONENTS Config cfg( "Taskbar" ); cfg.setGroup( "Applets" ); QStringList exclude = cfg.readListEntry( "ExcludeApplets", ',' ); QString lang = getenv( "LANG" ); QString path = QPEApplication::qpeDir() + "/plugins/applets"; #ifdef Q_OS_MACX QDir dir( path, "lib*.dylib" ); #else QDir dir( path, "lib*.so" ); #endif /* Q_OS_MACX */ QStringList list = dir.entryList(); QStringList::Iterator it; int napplets=0; TaskbarApplet* *applets = new TaskbarApplet*[list.count()]; for ( it = list.begin(); it != list.end(); ++it ) { if ( exclude.find( *it ) != exclude.end() ) continue; - qWarning( "Found Applet: %s", (*it).latin1() ); + owarn << "Found Applet: " << (*it) << "" << oendl; TaskbarAppletInterface *iface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if (( lib->queryInterface( IID_TaskbarApplet, (QUnknownInterface**)&iface ) == QS_OK ) && iface ) { TaskbarApplet *applet = new TaskbarApplet; applets[napplets++] = applet; applet->library = lib; applet->iface = iface; QTranslator *trans = new QTranslator(qApp); QString type = (*it).left( (*it).find(".") ); QString tfn = QPEApplication::qpeDir()+"/i18n/"+lang+"/"+type+".qm"; if ( trans->load( tfn )) qApp->installTranslator( trans ); else delete trans; } else { exclude += *it; delete lib; } } cfg.writeEntry( "ExcludeApplets", exclude, ',' ); qsort(applets,napplets,sizeof(applets[0]),compareAppletPositions); while (napplets--) { TaskbarApplet *applet = applets[napplets]; applet->applet = applet->iface->applet( this ); appletList.append(*applet); } delete [] applets; #else /* ## FIXME single app */ TaskbarApplet * const applet = new TaskbarApplet(); applet->iface = new ClockAppletImpl(); applet->applet = applet->iface->applet( this ); appletList.append( applet ); #endif show(); } diff --git a/core/launcher/taskbar.cpp b/core/launcher/taskbar.cpp index 91e2f20..86e0d0d 100644 --- a/core/launcher/taskbar.cpp +++ b/core/launcher/taskbar.cpp @@ -1,377 +1,380 @@ /********************************************************************** ** 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 "startmenu.h" #include "inputmethods.h" #include "runningappbar.h" #include "systray.h" #include "wait.h" #include "appicons.h" #include "taskbar.h" #include "server.h" +/* OPIE */ +#include <opie2/odebug.h> #include <qtopia/config.h> #include <qtopia/qpeapplication.h> #ifdef QWS #include <qtopia/qcopenvelope_qws.h> #endif #include <qtopia/global.h> -//#include <qtopia/custom.h> +using namespace Opie::Core; +/* QT */ #include <qlabel.h> #include <qlayout.h> #include <qtimer.h> #ifdef QWS #include <qwindowsystem_qws.h> #endif #include <qwidgetstack.h> #if defined( Q_WS_QWS ) #include <qwsdisplay_qws.h> #include <qgfx_qws.h> #endif static bool initNumLock() { #ifdef QPE_INITIAL_NUMLOCK_STATE QPE_INITIAL_NUMLOCK_STATE #endif return FALSE; } //--------------------------------------------------------------------------- class SafeMode : public QWidget { Q_OBJECT public: SafeMode( QWidget *parent ) : QWidget( parent ), menu(0) { message = tr("Safe Mode"); QFont f( font() ); f.setWeight( QFont::Bold ); setFont( f ); } void mousePressEvent( QMouseEvent *); QSize sizeHint() const; void paintEvent( QPaintEvent* ); private slots: void action(int i); private: QString message; QPopupMenu *menu; }; void SafeMode::mousePressEvent( QMouseEvent *) { if ( !menu ) { menu = new QPopupMenu(this); menu->insertItem( tr("Plugin Manager..."), 0 ); menu->insertItem( tr("Restart Qtopia"), 1 ); menu->insertItem( tr("Help..."), 2 ); connect(menu, SIGNAL(activated(int)), this, SLOT(action(int))); } QPoint curPos = mapToGlobal( QPoint(0,0) ); QSize sh = menu->sizeHint(); menu->popup( curPos-QPoint((sh.width()-width())/2,sh.height()) ); } void SafeMode::action(int i) { switch (i) { case 0: Global::execute( "pluginmanager" ); break; case 1: Global::restart(); break; case 2: Global::execute( "helpbrowser", "safemode.html" ); break; } } QSize SafeMode::sizeHint() const { QFontMetrics fm = fontMetrics(); return QSize( fm.width(message), fm.height() ); } void SafeMode::paintEvent( QPaintEvent* ) { QPainter p(this); p.drawText( rect(), AlignCenter, message ); } //--------------------------------------------------------------------------- class LockKeyState : public QWidget { public: LockKeyState( QWidget *parent ) : QWidget(parent), nl(initNumLock()), cl(FALSE) { nl_pm = Resource::loadPixmap("numlock"); cl_pm = Resource::loadPixmap("capslock"); } QSize sizeHint() const { return QSize(nl_pm.width()+2,nl_pm.width()+nl_pm.height()+1); } void toggleNumLockState() { nl = !nl; repaint(); } void toggleCapsLockState() { cl = !cl; repaint(); } void paintEvent( QPaintEvent * ) { int y = (height()-sizeHint().height())/2; QPainter p(this); if ( nl ) p.drawPixmap(1,y,nl_pm); if ( cl ) p.drawPixmap(1,y+nl_pm.height()+1,cl_pm); } private: QPixmap nl_pm, cl_pm; bool nl, cl; }; //--------------------------------------------------------------------------- TaskBar::~TaskBar() { } TaskBar::TaskBar() : QHBox(0, 0, WStyle_Customize | WStyle_Tool | WStyle_StaysOnTop | WGroupLeader) { Config cfg( "Launcher" ); cfg.setGroup( "InputMethods" ); resizeRunningApp = cfg.readBoolEntry( "Resize", true ); sm = new StartMenu( this ); connect( sm, SIGNAL(tabSelected(const QString&)), this, SIGNAL(tabSelected(const QString&)) ); inputMethods = new InputMethods( this ); connect( inputMethods, SIGNAL(inputToggled(bool)), this, SLOT(calcMaxWindowRect()) ); stack = new QWidgetStack( this ); stack->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ) ); label = new QLabel(stack); runningAppBar = new RunningAppBar(stack); stack->raiseWidget(runningAppBar); waitIcon = new Wait( this ); (void) new AppIcons( this ); sysTray = new SysTray( this ); /* ### FIXME plugin loader and safe mode */ #if 0 if (PluginLoader::inSafeMode()) (void)new SafeMode( this ); #endif // ## make customizable in some way? #ifdef QT_QWS_CUSTOM lockState = new LockKeyState( this ); #else lockState = 0; #endif #if defined(Q_WS_QWS) #if !defined(QT_NO_COP) QCopChannel *channel = new QCopChannel( "QPE/TaskBar", this ); connect( channel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(receive(const QCString&,const QByteArray&)) ); #endif #endif waitTimer = new QTimer( this ); connect( waitTimer, SIGNAL( timeout() ), this, SLOT( stopWait() ) ); clearer = new QTimer( this ); QObject::connect(clearer, SIGNAL(timeout()), SLOT(clearStatusBar())); connect( qApp, SIGNAL(symbol()), this, SLOT(toggleSymbolInput()) ); connect( qApp, SIGNAL(numLockStateToggle()), this, SLOT(toggleNumLockState()) ); connect( qApp, SIGNAL(capsLockStateToggle()), this, SLOT(toggleCapsLockState()) ); } void TaskBar::setStatusMessage( const QString &text ) { if ( !text.isEmpty() ) { label->setText( text ); stack->raiseWidget( label ); if ( sysTray && ( label->fontMetrics().width( text ) > label->width() ) ) sysTray->hide(); clearer->start( 3000, TRUE ); } else { clearStatusBar(); } } void TaskBar::clearStatusBar() { label->clear(); stack->raiseWidget(runningAppBar); if ( sysTray ) sysTray->show(); // stack->raiseWidget( mru ); } void TaskBar::startWait() { waitIcon->setWaiting( true ); // a catchall stop after 10 seconds... waitTimer->start( 10 * 1000, true ); } void TaskBar::stopWait(const QString&) { waitTimer->stop(); waitIcon->setWaiting( false ); } void TaskBar::stopWait() { waitTimer->stop(); waitIcon->setWaiting( false ); } /* * This resizeEvent will be captured by * the ServerInterface and it'll layout * and calc rect. Now if we go from bigger * to smaller screen the SysTray is out of * bounds and repaint() won't trigger an Event */ void TaskBar::resizeEvent( QResizeEvent *e ) { if ( sysTray ) sysTray->hide(); QHBox::resizeEvent( e ); if ( sysTray ) sysTray->show(); - qWarning("TaskBar::resize event"); + owarn << "TaskBar::resize event" << oendl; } void TaskBar::styleChange( QStyle &s ) { QHBox::styleChange( s ); calcMaxWindowRect(); } void TaskBar::calcMaxWindowRect() { if ( resizeRunningApp ) { #if defined(Q_WS_QWS) QRect wr; int displayWidth = qApp->desktop()->width(); QRect ir = inputMethods->inputRect(); if ( ir.isValid() ) { wr.setCoords( 0, 0, displayWidth-1, ir.top()-1 ); } else { wr.setCoords( 0, 0, displayWidth-1, y()-1 ); } #if QT_VERSION < 0x030000 QWSServer::setMaxWindowRect( qt_screen->mapToDevice(wr,QSize(qt_screen->width(),qt_screen->height())) ); #else QWSServer::setMaxWindowRect( wr ); #endif #endif } } void TaskBar::receive( const QCString &msg, const QByteArray &data ) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "message(QString)" ) { QString text; stream >> text; setStatusMessage( text ); } else if ( msg == "hideInputMethod()" ) { inputMethods->hideInputMethod(); } else if ( msg == "showInputMethod()" ) { inputMethods->showInputMethod(); } else if ( msg == "showInputMethod(QString)" ) { QString name; stream >> name; inputMethods->showInputMethod(name); } else if ( msg == "reloadInputMethods()" ) { inputMethods->loadInputMethods(); } else if ( msg == "reloadApplets()" ) { sysTray->clearApplets(); sm->createMenu(); sysTray->addApplets(); }else if ( msg == "toggleMenu()" ) { if ( sm-> launchMenu-> isVisible() ) sm-> launch(); else QCopEnvelope e( "QPE/System", "toggleApplicationMenu()" ); }else if ( msg == "toggleStartMenu()" ) sm->launch(); } void TaskBar::setApplicationState( const QString &name, ServerInterface::ApplicationState state ) { if ( state == ServerInterface::Launching ) runningAppBar->applicationLaunched( name ); else if ( state == ServerInterface::Terminated ) runningAppBar->applicationTerminated( name ); } void TaskBar::toggleNumLockState() { if ( lockState ) lockState->toggleNumLockState(); } void TaskBar::toggleCapsLockState() { if ( lockState ) lockState->toggleCapsLockState(); } void TaskBar::toggleSymbolInput() { QString unicodeInput = qApp->translate( "InputMethods", "Unicode" ); if ( inputMethods->currentShown() == unicodeInput ) { inputMethods->hideInputMethod(); } else { inputMethods->showInputMethod( unicodeInput ); } } #include "taskbar.moc" diff --git a/core/launcher/transferserver.cpp b/core/launcher/transferserver.cpp index e32cf41..4b764e3 100644 --- a/core/launcher/transferserver.cpp +++ b/core/launcher/transferserver.cpp @@ -1,1442 +1,1431 @@ /********************************************************************** ** 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 _XOPEN_SOURCE +#include "transferserver.h" +/* OPIE */ +#include <opie2/odebug.h> #include <opie2/oglobal.h> +#include <qtopia/qprocess.h> +#include <qtopia/process.h> +#include <qtopia/private/contact.h> +#include <qtopia/version.h> +#ifdef Q_WS_QWS +#include <qtopia/qcopenvelope_qws.h> +#endif +using namespace Opie::Core; -#ifndef Q_OS_WIN32 +/* QT */ +#include <qtextstream.h> +#include <qmessagebox.h> + +/* STD */ #include <pwd.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <time.h> #ifndef Q_OS_MACX #include <shadow.h> #include <crypt.h> #endif /* Q_OS_MACX */ -#else -#include <stdlib.h> -#include <time.h> -#endif - - -#if defined(_OS_LINUX_) -#include <shadow.h> -#endif - -#include <qtextstream.h> -#include <qmessagebox.h> -//#include <qtopia/qcopchannel_qws.h> -#include <qtopia/process.h> -#include <qtopia/private/contact.h> -#include <qtopia/version.h> -#ifdef Q_WS_QWS -#include <qtopia/qcopenvelope_qws.h> -#endif - - -#include "transferserver.h" -#include <qtopia/qprocess.h> - const int block_size = 51200; -using namespace Opie::Core; TransferServer::TransferServer( Q_UINT16 port, QObject *parent, const char* name) : QServerSocket( port, 1, parent, name ) { connections.setAutoDelete( TRUE ); if ( !ok() ) - qWarning( "Failed to bind to port %d", port ); + owarn << "Failed to bind to port " << port << "" << oendl; } void TransferServer::authorizeConnections() { QListIterator<ServerPI> it(connections); while ( it.current() ) { if ( !it.current()->verifyAuthorised() ) { disconnect( it.current(), SIGNAL(connectionClosed(ServerPI*)), this, SLOT( closed(ServerPI*)) ); connections.removeRef( it.current() ); } else ++it; } } void TransferServer::closed(ServerPI *item) { connections.removeRef(item); } TransferServer::~TransferServer() { } void TransferServer::newConnection( int socket ) { ServerPI *ptr = new ServerPI( socket, this ); connect( ptr, SIGNAL(connectionClosed(ServerPI*)), this, SLOT( closed(ServerPI*)) ); connections.append( ptr ); } QString SyncAuthentication::serverId() { Config cfg("Security"); cfg.setGroup("Sync"); QString r = cfg.readEntry("serverid"); if ( r.isEmpty() ) { r = OGlobal::generateUuid(); cfg.writeEntry("serverid", r ); } return r; } QString SyncAuthentication::ownerName() { QString vfilename = Global::applicationFileName("addressbook", "businesscard.vcf"); if (QFile::exists(vfilename)) { Contact c; c = Contact::readVCard( vfilename )[0]; return c.fullName(); } return QString::null; } QString SyncAuthentication::loginName() { struct passwd *pw = 0L; #ifndef Q_OS_WIN32 pw = getpwuid( geteuid() ); return QString::fromLocal8Bit( pw->pw_name ); #else //### revise return QString(); #endif } int SyncAuthentication::isAuthorized(QHostAddress peeraddress) { Config cfg("Security"); cfg.setGroup("Sync"); // QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0"); uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100); // QHostAddress allowed; // allowed.setAddress(allowedstr); // uint auth_peer = allowed.ip4Addr(); uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24); uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined ? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits)); return (peeraddress.ip4Addr() & mask) == auth_peer; } bool SyncAuthentication::checkUser( const QString& user ) { if ( user.isEmpty() ) return FALSE; QString euser = loginName(); return user == euser; } bool SyncAuthentication::checkPassword( const QString& password ) { #ifdef ALLOW_UNIX_USER_FTP // First, check system password... struct passwd *pw = 0; struct spwd *spw = 0; pw = getpwuid( geteuid() ); spw = getspnam( pw->pw_name ); QString cpwd = QString::fromLocal8Bit( pw->pw_passwd ); if ( cpwd == "x" && spw ) cpwd = QString::fromLocal8Bit( spw->sp_pwdp ); // Note: some systems use more than crypt for passwords. QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) ); if ( cpwd == cpassword ) return TRUE; #endif static int lastdenial=0; static int denials=0; int now = time(0); Config cfg("Security"); cfg.setGroup("SyncMode"); int mode = cfg.readNumEntry("Mode", 0x02 ); //No pass word needed if the user really needs it if (mode & 0x04) { QMessageBox unauth( tr("Sync Connection"), tr("<qt><p>An unauthorized system is requesting access to this device." "<p>You chose IntelliSync so you may I allow or deny this connection.</qt>" ), QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Cancel|QMessageBox::Default, QMessageBox::NoButton, 0, QString::null, TRUE, WStyle_StaysOnTop); unauth.setButtonText(QMessageBox::Ok, tr("Allow" ) ); unauth.setButtonText(QMessageBox::Cancel, tr("Deny")); switch( unauth.exec() ) { case QMessageBox::Ok: return TRUE; break; case QMessageBox::Cancel: default: denials++; lastdenial=now; return FALSE; } } // Detect old Qtopia Desktop (no password) and fail if ( password.isEmpty() ) { if ( denials < 3 || now > lastdenial+600 ) { QMessageBox unauth( tr("Sync Connection"), tr("<p>An unauthorized system is requesting access to this device." "<p>If you are using a version of Qtopia Desktop older than 1.5.1, " "please upgrade or change the security setting to use IntelliSync." ), QMessageBox::Warning, QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton, 0, QString::null, TRUE, WStyle_StaysOnTop); unauth.setButtonText(QMessageBox::Cancel, tr("Deny")); unauth.exec(); denials++; lastdenial=now; } return FALSE; } // Second, check sync password... static int lock=0; if ( lock ) return FALSE; ++lock; /* * we need to support old Sync software and QtopiaDesktop */ if ( password.left(6) == "Qtopia" || password.left(6) == "rootme" ) { Config cfg( "Security" ); cfg.setGroup("Sync"); QStringList pwds = cfg.readListEntry("Passwords",' '); for (QStringList::ConstIterator it=pwds.begin(); it!=pwds.end(); ++it) { #ifndef Q_OS_WIN32 QString cpassword = QString::fromLocal8Bit( crypt( password.mid(8).local8Bit(), (*it).left(2).latin1() ) ); #else // ### revise QString cpassword(""); #endif if ( *it == cpassword ) { lock--; return TRUE; } } // Unrecognized system. Be careful... QMessageBox unrecbox( tr("Sync Connection"), tr( "<p>An unrecognized system is requesting access to this device." "<p>If you have just initiated a Sync for the first time, this is normal."), QMessageBox::Warning, QMessageBox::Cancel, QMessageBox::Yes, QMessageBox::NoButton, 0, QString::null, TRUE, WStyle_StaysOnTop); unrecbox.setButtonText(QMessageBox::Cancel, tr("Deny")); unrecbox.setButtonText(QMessageBox::Yes, tr("Allow")); if ( (denials > 2 && now < lastdenial+600) || unrecbox.exec() != QMessageBox::Yes) { denials++; lastdenial=now; lock--; return FALSE; } else { const char salty[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/."; char salt[2]; salt[0]= salty[rand() % (sizeof(salty)-1)]; salt[1]= salty[rand() % (sizeof(salty)-1)]; #ifndef Q_OS_WIN32 QString cpassword = QString::fromLocal8Bit( crypt( password.mid(8).local8Bit(), salt ) ); #else //### revise QString cpassword(""); #endif denials=0; pwds.prepend(cpassword); cfg.writeEntry("Passwords",pwds,' '); lock--; return TRUE; } } lock--; return FALSE; } ServerPI::ServerPI( int socket, QObject *parent, const char* name ) : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ), storFileSize(-1) { state = Connected; setSocket( socket ); peerport = peerPort(); peeraddress = peerAddress(); #ifndef INSECURE if ( !SyncAuthentication::isAuthorized(peeraddress) ) { state = Forbidden; startTimer( 0 ); } else #endif { connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); passiv = FALSE; for( int i = 0; i < 4; i++ ) wait[i] = FALSE; send( "220 Qtopia " QPE_VERSION " FTP Server" ); // No tr state = Wait_USER; dtp = new ServerDTP( this ); connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) ); connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) ); connect( dtp, SIGNAL( error(int) ), SLOT( dtpError(int) ) ); directory = QDir::currentDirPath(); static int p = 1024; while ( !serversocket || !serversocket->ok() ) { delete serversocket; serversocket = new ServerSocket( ++p, this ); } connect( serversocket, SIGNAL( newIncomming(int) ), SLOT( newConnection(int) ) ); } } ServerPI::~ServerPI() { close(); if ( dtp ) dtp->close(); delete dtp; delete serversocket; } bool ServerPI::verifyAuthorised() { if ( !SyncAuthentication::isAuthorized(peerAddress()) ) { state = Forbidden; return FALSE; } return TRUE; } void ServerPI::connectionClosed() { - // qDebug( "Debug: Connection closed" ); + // odebug << "Debug: Connection closed" << oendl; emit connectionClosed(this); } void ServerPI::send( const QString& msg ) { QTextStream os( this ); os << msg << endl; - //qDebug( "Reply: %s", msg.latin1() ); + //odebug << "Reply: " << msg << "" << oendl; } void ServerPI::read() { while ( canReadLine() ) process( readLine().stripWhiteSpace() ); } bool ServerPI::checkReadFile( const QString& file ) { QString filename; if ( file[0] != "/" ) filename = directory.path() + "/" + file; else filename = file; QFileInfo fi( filename ); return ( fi.exists() && fi.isReadable() ); } bool ServerPI::checkWriteFile( const QString& file ) { QString filename; if ( file[0] != "/" ) filename = directory.path() + "/" + file; else filename = file; QFileInfo fi( filename ); if ( fi.exists() ) if ( !QFile( filename ).remove() ) return FALSE; return TRUE; } void ServerPI::process( const QString& message ) { - //qDebug( "Command: %s", message.latin1() ); + //odebug << "Command: " << message << "" << oendl; // split message using "," as separator QStringList msg = QStringList::split( " ", message ); if ( msg.isEmpty() ) return; // command token QString cmd = msg[0].upper(); // argument token QString arg; if ( msg.count() >= 2 ) arg = msg[1]; // full argument string QString args; if ( msg.count() >= 2 ) { QStringList copy( msg ); // FIXME: for Qt3 // copy.pop_front() copy.remove( copy.begin() ); args = copy.join( " " ); } - //qDebug( "args: %s", args.latin1() ); + //odebug << "args: " << args << "" << oendl; // we always respond to QUIT, regardless of state if ( cmd == "QUIT" ) { send( "211 Good bye!" ); // No tr close(); return; } // connected to client if ( Connected == state ) return; // waiting for user name if ( Wait_USER == state ) { if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) { send( "530 Please login with USER and PASS" ); // No tr return; } send( "331 User name ok, need password" ); // No tr state = Wait_PASS; return; } // waiting for password if ( Wait_PASS == state ) { if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) { send( "530 Please login with USER and PASS" ); // No tr return; } send( "230 User logged in, proceed" ); // No tr state = Ready; return; } // ACCESS CONTROL COMMANDS // Only an ALLO sent immediately before STOR is valid. if ( cmd != "STOR" ) storFileSize = -1; // account (ACCT) if ( cmd == "ACCT" ) { // even wu-ftp does not support it send( "502 Command not implemented" ); // No tr } // change working directory (CWD) else if ( cmd == "CWD" ) { if ( !args.isEmpty() ) { if ( directory.cd( args, TRUE ) ) send( "250 Requested file action okay, completed" ); // No tr else send( "550 Requested action not taken" ); // No tr } else send( "500 Syntax error, command unrecognized" ); // No tr } // change to parent directory (CDUP) else if ( cmd == "CDUP" ) { if ( directory.cdUp() ) send( "250 Requested file action okay, completed" ); // No tr else send( "550 Requested action not taken" ); // No tr } // structure mount (SMNT) else if ( cmd == "SMNT" ) { // even wu-ftp does not support it send( "502 Command not implemented" ); // No tr } // reinitialize (REIN) else if ( cmd == "REIN" ) { // even wu-ftp does not support it send( "502 Command not implemented" ); // No tr } // TRANSFER PARAMETER COMMANDS // data port (PORT) else if ( cmd == "PORT" ) { if ( parsePort( arg ) ) send( "200 Command okay" ); // No tr else send( "500 Syntax error, command unrecognized" ); // No tr } // passive (PASV) else if ( cmd == "PASV" ) { passiv = TRUE; send( "227 Entering Passive Mode (" // No tr + address().toString().replace( QRegExp( "\\." ), "," ) + "," + QString::number( ( serversocket->port() ) >> 8 ) + "," + QString::number( ( serversocket->port() ) & 0xFF ) +")" ); } // representation type (TYPE) else if ( cmd == "TYPE" ) { if ( arg.upper() == "A" || arg.upper() == "I" ) send( "200 Command okay" ); // No tr else send( "504 Command not implemented for that parameter" ); // No tr } // file structure (STRU) else if ( cmd == "STRU" ) { if ( arg.upper() == "F" ) send( "200 Command okay" ); // No tr else send( "504 Command not implemented for that parameter" ); // No tr } // transfer mode (MODE) else if ( cmd == "MODE" ) { if ( arg.upper() == "S" ) send( "200 Command okay" ); // No tr else send( "504 Command not implemented for that parameter" ); // No tr } // FTP SERVICE COMMANDS // retrieve (RETR) else if ( cmd == "RETR" ) if ( !args.isEmpty() && checkReadFile( absFilePath( args ) ) || backupRestoreGzip( absFilePath( args ) ) ) { send( "150 File status okay" ); // No tr sendFile( absFilePath( args ) ); } else { - qDebug("550 Requested action not taken"); + odebug << "550 Requested action not taken" << oendl; send( "550 Requested action not taken" ); // No tr } // store (STOR) else if ( cmd == "STOR" ) if ( !args.isEmpty() && checkWriteFile( absFilePath( args ) ) ) { send( "150 File status okay" ); // No tr retrieveFile( absFilePath( args ) ); } else send( "550 Requested action not taken" ); // No tr // store unique (STOU) else if ( cmd == "STOU" ) { send( "502 Command not implemented" ); // No tr } // append (APPE) else if ( cmd == "APPE" ) { send( "502 Command not implemented" ); // No tr } // allocate (ALLO) else if ( cmd == "ALLO" ) { storFileSize = args.toInt(); send( "200 Command okay" ); // No tr } // restart (REST) else if ( cmd == "REST" ) { send( "502 Command not implemented" ); // No tr } // rename from (RNFR) else if ( cmd == "RNFR" ) { renameFrom = QString::null; if ( args.isEmpty() ) send( "500 Syntax error, command unrecognized" ); // No tr else { QFile file( absFilePath( args ) ); if ( file.exists() ) { send( "350 File exists, ready for destination name" ); // No tr renameFrom = absFilePath( args ); } else send( "550 Requested action not taken" ); // No tr } } // rename to (RNTO) else if ( cmd == "RNTO" ) { if ( lastCommand != "RNFR" ) send( "503 Bad sequence of commands" ); // No tr else if ( args.isEmpty() ) send( "500 Syntax error, command unrecognized" ); // No tr else { QDir dir( absFilePath( args ) ); if ( dir.rename( renameFrom, absFilePath( args ), TRUE ) ) send( "250 Requested file action okay, completed." ); // No tr else send( "550 Requested action not taken" ); // No tr } } // abort (ABOR) else if ( cmd.contains( "ABOR" ) ) { dtp->close(); if ( dtp->dtpMode() != ServerDTP::Idle ) send( "426 Connection closed; transfer aborted" ); // No tr else send( "226 Closing data connection" ); // No tr } // delete (DELE) else if ( cmd == "DELE" ) { if ( args.isEmpty() ) send( "500 Syntax error, command unrecognized" ); // No tr else { QFile file( absFilePath( args ) ) ; if ( file.remove() ) { send( "250 Requested file action okay, completed" ); // No tr QCopEnvelope e("QPE/System", "linkChanged(QString)" ); e << file.name(); } else { send( "550 Requested action not taken" ); // No tr } } } // remove directory (RMD) else if ( cmd == "RMD" ) { if ( args.isEmpty() ) send( "500 Syntax error, command unrecognized" ); // No tr else { QDir dir; if ( dir.rmdir( absFilePath( args ), TRUE ) ) send( "250 Requested file action okay, completed" ); // No tr else send( "550 Requested action not taken" ); // No tr } } // make directory (MKD) else if ( cmd == "MKD" ) { if ( args.isEmpty() ) { - qDebug(" Error: no arg"); + odebug << " Error: no arg" << oendl; send( "500 Syntax error, command unrecognized" ); // No tr } else { QDir dir; if ( dir.mkdir( absFilePath( args ), TRUE ) ) send( "250 Requested file action okay, completed." ); // No tr else send( "550 Requested action not taken" ); // No tr } } // print working directory (PWD) else if ( cmd == "PWD" ) { send( "257 \"" + directory.path() +"\"" ); } // list (LIST) else if ( cmd == "LIST" ) { if ( sendList( absFilePath( args ) ) ) send( "150 File status okay" ); // No tr else send( "500 Syntax error, command unrecognized" ); // No tr } // size (SIZE) else if ( cmd == "SIZE" ) { QString filePath = absFilePath( args ); QFileInfo fi( filePath ); bool gzipfile = backupRestoreGzip( filePath ); if ( !fi.exists() && !gzipfile ) send( "500 Syntax error, command unrecognized" ); // No tr else { if ( !gzipfile ) send( "213 " + QString::number( fi.size() ) ); else { Process duproc( QString("du") ); duproc.addArgument("-s"); QString in, out; if ( !duproc.exec(in, out) ) { - qDebug("du process failed; just sending back 1K"); + odebug << "du process failed; just sending back 1K" << oendl; send( "213 1024"); } else { QString size = out.left( out.find("\t") ); int guess = size.toInt()/5; if ( filePath.contains("doc") ) // No tr guess *= 1000; - qDebug("sending back gzip guess of %d", guess); + odebug << "sending back gzip guess of " << guess << "" << oendl; send( "213 " + QString::number(guess) ); } } } } // name list (NLST) else if ( cmd == "NLST" ) { send( "502 Command not implemented" ); // No tr } // site parameters (SITE) else if ( cmd == "SITE" ) { send( "502 Command not implemented" ); // No tr } // system (SYST) else if ( cmd == "SYST" ) { send( "215 UNIX Type: L8" ); // No tr } // status (STAT) else if ( cmd == "STAT" ) { send( "502 Command not implemented" ); // No tr } // help (HELP ) else if ( cmd == "HELP" ) { send( "502 Command not implemented" ); // No tr } // noop (NOOP) else if ( cmd == "NOOP" ) { send( "200 Command okay" ); // No tr } // not implemented else send( "502 Command not implemented" ); // No tr lastCommand = cmd; } bool ServerPI::backupRestoreGzip( const QString &file ) { return (file.find( "backup" ) != -1 && // No tr file.findRev( ".tgz" ) == (int)file.length()-4 ); } bool ServerPI::backupRestoreGzip( const QString &file, QStringList &targets ) { if ( file.find( "backup" ) != -1 && // No tr file.findRev( ".tgz" ) == (int)file.length()-4 ) { QFileInfo info( file ); targets = info.dirPath( TRUE ); qDebug("ServerPI::backupRestoreGzip for %s = %s", file.latin1(), targets.join(" ").latin1() ); return true; } return false; } void ServerPI::sendFile( const QString& file ) { if ( passiv ) { wait[SendFile] = TRUE; waitfile = file; if ( waitsocket ) newConnection( waitsocket ); } else { QStringList targets; if ( backupRestoreGzip( file, targets ) ) dtp->sendGzipFile( file, targets, peeraddress, peerport ); else dtp->sendFile( file, peeraddress, peerport ); } } void ServerPI::retrieveFile( const QString& file ) { if ( passiv ) { wait[RetrieveFile] = TRUE; waitfile = file; if ( waitsocket ) newConnection( waitsocket ); } else { QStringList targets; if ( backupRestoreGzip( file, targets ) ) dtp->retrieveGzipFile( file, peeraddress, peerport ); else dtp->retrieveFile( file, peeraddress, peerport, storFileSize ); } } bool ServerPI::parsePort( const QString& pp ) { QStringList p = QStringList::split( ",", pp ); if ( p.count() != 6 ) return FALSE; // h1,h2,h3,h4,p1,p2 peeraddress = QHostAddress( ( p[0].toInt() << 24 ) + ( p[1].toInt() << 16 ) + ( p[2].toInt() << 8 ) + p[3].toInt() ); peerport = ( p[4].toInt() << 8 ) + p[5].toInt(); return TRUE; } void ServerPI::dtpCompleted() { send( "226 Closing data connection, file transfer successful" ); // No tr if ( dtp->dtpMode() == ServerDTP::RetrieveFile ) { QString fn = dtp->fileName(); if ( fn.right(8)==".desktop" && fn.find("/Documents/")>=0 ) { QCopEnvelope e("QPE/System", "linkChanged(QString)" ); e << fn; } } waitsocket = 0; dtp->close(); storFileSize = -1; } void ServerPI::dtpFailed() { dtp->close(); waitsocket = 0; send( "451 Requested action aborted: local error in processing" ); // No tr storFileSize = -1; } void ServerPI::dtpError( int ) { dtp->close(); waitsocket = 0; send( "451 Requested action aborted: local error in processing" ); // No tr storFileSize = -1; } bool ServerPI::sendList( const QString& arg ) { QByteArray listing; QBuffer buffer( listing ); if ( !buffer.open( IO_WriteOnly ) ) return FALSE; QTextStream ts( &buffer ); QString fn = arg; if ( fn.isEmpty() ) fn = directory.path(); QFileInfo fi( fn ); if ( !fi.exists() ) return FALSE; // return file listing if ( fi.isFile() ) { ts << fileListing( &fi ) << endl; } // return directory listing else if ( fi.isDir() ) { QDir dir( fn ); const QFileInfoList *list = dir.entryInfoList( QDir::All | QDir::Hidden ); QFileInfoListIterator it( *list ); QFileInfo *info; unsigned long total = 0; while ( ( info = it.current() ) ) { if ( info->fileName() != "." && info->fileName() != ".." ) total += info->size(); ++it; } ts << "total " << QString::number( total / 1024 ) << endl; // No tr it.toFirst(); while ( ( info = it.current() ) ) { if ( info->fileName() == "." || info->fileName() == ".." ) { ++it; continue; } ts << fileListing( info ) << endl; ++it; } } if ( passiv ) { waitarray = buffer.buffer(); wait[SendByteArray] = TRUE; if ( waitsocket ) newConnection( waitsocket ); } else dtp->sendByteArray( buffer.buffer(), peeraddress, peerport ); return TRUE; } QString ServerPI::fileListing( QFileInfo *info ) { if ( !info ) return QString::null; QString s; // type char if ( info->isDir() ) s += "d"; else if ( info->isSymLink() ) s += "l"; else s += "-"; // permisson string s += permissionString( info ) + " "; // number of hardlinks int subdirs = 1; if ( info->isDir() ) subdirs = 2; // FIXME : this is to slow //if ( info->isDir() ) //subdirs = QDir( info->absFilePath() ).entryList( QDir::Dirs ).count(); s += QString::number( subdirs ).rightJustify( 3, ' ', TRUE ) + " "; // owner QString o = info->owner(); if ( o.isEmpty() ) o = QString::number(info->ownerId()); s += o.leftJustify( 8, ' ', TRUE ) + " "; // group QString g = info->group(); if ( g.isEmpty() ) g = QString::number(info->groupId()); s += g.leftJustify( 8, ' ', TRUE ) + " "; // file size in bytes s += QString::number( info->size() ).rightJustify( 9, ' ', TRUE ) + " "; // last modified date QDate date = info->lastModified().date(); QTime time = info->lastModified().time(); s += date.monthName( date.month() ) + " " + QString::number( date.day() ).rightJustify( 2, ' ', TRUE ) + " " + QString::number( time.hour() ).rightJustify( 2, '0', TRUE ) + ":" + QString::number( time.minute() ).rightJustify( 2,'0', TRUE ) + " "; // file name s += info->fileName(); return s; } QString ServerPI::permissionString( QFileInfo *info ) { if ( !info ) return QString( "---------" ); QString s; // user if ( info->permission( QFileInfo::ReadUser ) ) s += "r"; else s += "-"; if ( info->permission( QFileInfo::WriteUser ) ) s += "w"; else s += "-"; if ( info->permission( QFileInfo::ExeUser ) ) s += "x"; else s += "-"; // group if ( info->permission( QFileInfo::ReadGroup ) ) s += "r"; else s += "-"; if ( info->permission( QFileInfo::WriteGroup ) )s += "w"; else s += "-"; if ( info->permission( QFileInfo::ExeGroup ) ) s += "x"; else s += "-"; // exec if ( info->permission( QFileInfo::ReadOther ) ) s += "r"; else s += "-"; if ( info->permission( QFileInfo::WriteOther ) ) s += "w"; else s += "-"; if ( info->permission( QFileInfo::ExeOther ) ) s += "x"; else s += "-"; return s; } void ServerPI::newConnection( int socket ) { - //qDebug( "New incomming connection" ); + //odebug << "New incomming connection" << oendl; if ( !passiv ) return; if ( wait[SendFile] ) { QStringList targets; if ( backupRestoreGzip( waitfile, targets ) ) dtp->sendGzipFile( waitfile, targets ); else dtp->sendFile( waitfile ); dtp->setSocket( socket ); } else if ( wait[RetrieveFile] ) { - qDebug("check retrieve file"); + odebug << "check retrieve file" << oendl; if ( backupRestoreGzip( waitfile ) ) dtp->retrieveGzipFile( waitfile ); else dtp->retrieveFile( waitfile, storFileSize ); dtp->setSocket( socket ); } else if ( wait[SendByteArray] ) { dtp->sendByteArray( waitarray ); dtp->setSocket( socket ); } else if ( wait[RetrieveByteArray] ) { - qDebug("retrieve byte array"); + odebug << "retrieve byte array" << oendl; dtp->retrieveByteArray(); dtp->setSocket( socket ); } else waitsocket = socket; for( int i = 0; i < 4; i++ ) wait[i] = FALSE; } QString ServerPI::absFilePath( const QString& file ) { if ( file.isEmpty() ) return file; QString filepath( file ); if ( file[0] != "/" ) filepath = directory.path() + "/" + file; return filepath; } void ServerPI::timerEvent( QTimerEvent * ) { connectionClosed(); } ServerDTP::ServerDTP( QObject *parent, const char* name) : QSocket( parent, name ), mode( Idle ), createTargzProc( 0 ), retrieveTargzProc( 0 ) { connect( this, SIGNAL( connected() ), SLOT( connected() ) ); connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); connect( this, SIGNAL( bytesWritten(int) ), SLOT( bytesWritten(int) ) ); connect( this, SIGNAL( readyRead() ), SLOT( readyRead() ) ); createTargzProc = new QProcess( QString("tar"), this, "createTargzProc"); // No tr createTargzProc->setCommunication( QProcess::Stdout ); createTargzProc->setWorkingDirectory( QDir::rootDirPath() ); connect( createTargzProc, SIGNAL( processExited() ), SLOT( targzDone() ) ); retrieveTargzProc = new QProcess( this, "retrieveTargzProc" ); retrieveTargzProc->setCommunication( QProcess::Stdin ); retrieveTargzProc->setWorkingDirectory( QDir::rootDirPath() ); connect( retrieveTargzProc, SIGNAL( processExited() ), SIGNAL( completed() ) ); connect( retrieveTargzProc, SIGNAL( processExited() ), SLOT( extractTarDone() ) ); } ServerDTP::~ServerDTP() { buf.close(); if ( RetrieveFile == mode && file.isOpen() ) { // We're being shutdown before the client closed. file.close(); if ( recvFileSize >= 0 && (int)file.size() != recvFileSize ) { - qDebug( "STOR incomplete" ); + odebug << "STOR incomplete" << oendl; file.remove(); } } else { file.close(); } createTargzProc->kill(); } void ServerDTP::extractTarDone() { - qDebug("extract done"); + odebug << "extract done" << oendl; #ifndef QT_NO_COP QCopEnvelope e( "QPE/System", "restoreDone(QString)" ); e << file.name(); #endif } void ServerDTP::connected() { // send file mode switch ( mode ) { case SendFile : if ( !file.exists() || !file.open( IO_ReadOnly) ) { emit failed(); mode = Idle; return; } - //qDebug( "Debug: Sending file '%s'", file.name().latin1() ); + //odebug << "Debug: Sending file '" << file.name() << "'" << oendl; bytes_written = 0; if ( file.size() == 0 ) { //make sure it doesn't hang on empty files file.close(); emit completed(); mode = Idle; } else { // Don't write more if there is plenty buffered already. if ( bytesToWrite() <= block_size && !file.atEnd() ) { QCString s; s.resize( block_size ); int bytes = file.readBlock( s.data(), block_size ); writeBlock( s.data(), bytes ); } } break; case SendGzipFile: if ( createTargzProc->isRunning() ) { // SHOULDN'T GET HERE, BUT DOING A SAFETY CHECK ANYWAY - qWarning("Previous tar --gzip process is still running; killing it..."); + owarn << "Previous tar --gzip process is still running; killing it..." << oendl; createTargzProc->kill(); } bytes_written = 0; - qDebug("==>start send tar process"); + odebug << "==>start send tar process" << oendl; if ( !createTargzProc->start() ) qWarning("Error starting %s", createTargzProc->arguments().join(" ").latin1()); break; case SendBuffer: if ( !buf.open( IO_ReadOnly) ) { emit failed(); mode = Idle; return; } - // qDebug( "Debug: Sending byte array" ); + // odebug << "Debug: Sending byte array" << oendl; bytes_written = 0; while( !buf.atEnd() ) putch( buf.getch() ); buf.close(); break; case RetrieveFile: // retrieve file mode if ( file.exists() && !file.remove() ) { emit failed(); mode = Idle; return; } if ( !file.open( IO_WriteOnly) ) { emit failed(); mode = Idle; return; } - // qDebug( "Debug: Retrieving file %s", file.name().latin1() ); + // odebug << "Debug: Retrieving file " << file.name() << "" << oendl; break; case RetrieveGzipFile: - qDebug("=-> starting tar process to receive .tgz file"); + odebug << "=-> starting tar process to receive .tgz file" << oendl; break; case RetrieveBuffer: // retrieve buffer mode if ( !buf.open( IO_WriteOnly) ) { emit failed(); mode = Idle; return; } - // qDebug( "Debug: Retrieving byte array" ); + // odebug << "Debug: Retrieving byte array" << oendl; break; case Idle: - qDebug("connection established but mode set to Idle; BUG!"); + odebug << "connection established but mode set to Idle; BUG!" << oendl; break; } } void ServerDTP::connectionClosed() { - //qDebug( "Debug: Data connection closed %ld bytes written", bytes_written ); + //odebug << "Debug: Data connection closed " << bytes_written << " bytes written" << oendl; // send file mode if ( SendFile == mode ) { if ( bytes_written == file.size() ) emit completed(); else emit failed(); } // send buffer mode else if ( SendBuffer == mode ) { if ( bytes_written == buf.size() ) emit completed(); else emit failed(); } // retrieve file mode else if ( RetrieveFile == mode ) { file.close(); if ( recvFileSize >= 0 && (int)file.size() != recvFileSize ) { - qDebug( "STOR incomplete" ); + odebug << "STOR incomplete" << oendl; file.remove(); emit failed(); } else { emit completed(); } } else if ( RetrieveGzipFile == mode ) { - qDebug("Done writing ungzip file; closing input"); + odebug << "Done writing ungzip file; closing input" << oendl; retrieveTargzProc->flushStdin(); retrieveTargzProc->closeStdin(); } // retrieve buffer mode else if ( RetrieveBuffer == mode ) { buf.close(); emit completed(); } mode = Idle; } void ServerDTP::bytesWritten( int bytes ) { bytes_written += bytes; // send file mode if ( SendFile == mode ) { if ( bytes_written == file.size() ) { - // qDebug( "Debug: Sending complete: %d bytes", file.size() ); + // odebug << "Debug: Sending complete: " << file.size() << " bytes" << oendl; file.close(); emit completed(); mode = Idle; } else if( !file.atEnd() ) { QCString s; s.resize( block_size ); int bytes = file.readBlock( s.data(), block_size ); writeBlock( s.data(), bytes ); } } // send buffer mode if ( SendBuffer == mode ) { if ( bytes_written == buf.size() ) { - // qDebug( "Debug: Sending complete: %d bytes", buf.size() ); + // odebug << "Debug: Sending complete: " << buf.size() << " bytes" << oendl; emit completed(); mode = Idle; } } } void ServerDTP::readyRead() { // retrieve file mode if ( RetrieveFile == mode ) { QCString s; s.resize( bytesAvailable() ); readBlock( s.data(), bytesAvailable() ); file.writeBlock( s.data(), s.size() ); } else if ( RetrieveGzipFile == mode ) { if ( !retrieveTargzProc->isRunning() ) retrieveTargzProc->start(); QByteArray s; s.resize( bytesAvailable() ); readBlock( s.data(), bytesAvailable() ); retrieveTargzProc->writeToStdin( s ); - qDebug("wrote %d bytes to ungzip ", s.size() ); + odebug << "wrote " << s.size() << " bytes to ungzip " << oendl; } // retrieve buffer mode else if ( RetrieveBuffer == mode ) { QCString s; s.resize( bytesAvailable() ); readBlock( s.data(), bytesAvailable() ); buf.writeBlock( s.data(), s.size() ); } } void ServerDTP::writeTargzBlock() { QByteArray block = createTargzProc->readStdout(); writeBlock( block.data(), block.size() ); - qDebug("writeTargzBlock %d", block.size()); + odebug << "writeTargzBlock " << block.size() << "" << oendl; } void ServerDTP::targzDone() { - qDebug("tar and gzip done"); + odebug << "tar and gzip done" << oendl; emit completed(); mode = Idle; disconnect( createTargzProc, SIGNAL( readyReadStdout() ), this, SLOT( writeTargzBlock() ) ); } void ServerDTP::sendFile( const QString fn, const QHostAddress& host, Q_UINT16 port ) { file.setName( fn ); mode = SendFile; connectToHost( host.toString(), port ); } void ServerDTP::sendFile( const QString fn ) { file.setName( fn ); mode = SendFile; } void ServerDTP::sendGzipFile( const QString &fn, const QStringList &archiveTargets, const QHostAddress& host, Q_UINT16 port ) { sendGzipFile( fn, archiveTargets ); connectToHost( host.toString(), port ); } void ServerDTP::sendGzipFile( const QString &fn, const QStringList &archiveTargets ) { mode = SendGzipFile; file.setName( fn ); QStringList args = "targzip"; //args += "-cv"; args += archiveTargets; - qDebug("sendGzipFile %s", args.join(" ").latin1() ); + odebug << "sendGzipFile " << args.join(" ") << "" << oendl; createTargzProc->setArguments( args ); connect( createTargzProc, SIGNAL( readyReadStdout() ), SLOT( writeTargzBlock() ) ); } void ServerDTP::retrieveFile( const QString fn, const QHostAddress& host, Q_UINT16 port, int fileSize ) { recvFileSize = fileSize; file.setName( fn ); mode = RetrieveFile; connectToHost( host.toString(), port ); } void ServerDTP::retrieveFile( const QString fn, int fileSize ) { recvFileSize = fileSize; file.setName( fn ); mode = RetrieveFile; } void ServerDTP::retrieveGzipFile( const QString &fn ) { - qDebug("retrieveGzipFile %s", fn.latin1()); + odebug << "retrieveGzipFile " << fn << "" << oendl; file.setName( fn ); mode = RetrieveGzipFile; retrieveTargzProc->setArguments( "targunzip" ); connect( retrieveTargzProc, SIGNAL( processExited() ), SLOT( extractTarDone() ) ); } void ServerDTP::retrieveGzipFile( const QString &fn, const QHostAddress& host, Q_UINT16 port ) { retrieveGzipFile( fn ); connectToHost( host.toString(), port ); } void ServerDTP::sendByteArray( const QByteArray& array, const QHostAddress& host, Q_UINT16 port ) { buf.setBuffer( array ); mode = SendBuffer; connectToHost( host.toString(), port ); } void ServerDTP::sendByteArray( const QByteArray& array ) { buf.setBuffer( array ); mode = SendBuffer; } void ServerDTP::retrieveByteArray( const QHostAddress& host, Q_UINT16 port ) { buf.setBuffer( QByteArray() ); mode = RetrieveBuffer; connectToHost( host.toString(), port ); } void ServerDTP::retrieveByteArray() { buf.setBuffer( QByteArray() ); mode = RetrieveBuffer; } void ServerDTP::setSocket( int socket ) { QSocket::setSocket( socket ); connected(); } |