-rw-r--r-- | core/launcher/desktop.cpp | 6 | ||||
-rw-r--r-- | core/launcher/launcher.cpp | 6 | ||||
-rw-r--r-- | core/launcher/launcher.pro | 2 | ||||
-rw-r--r-- | core/launcher/runningappbar.cpp | 287 | ||||
-rw-r--r-- | core/launcher/runningappbar.h | 88 | ||||
-rw-r--r-- | core/launcher/startmenu.cpp | 4 | ||||
-rw-r--r-- | core/launcher/taskbar.cpp | 21 | ||||
-rw-r--r-- | core/launcher/taskbar.h | 10 |
8 files changed, 405 insertions, 19 deletions
diff --git a/core/launcher/desktop.cpp b/core/launcher/desktop.cpp index a19e4c6..bca95b2 100644 --- a/core/launcher/desktop.cpp +++ b/core/launcher/desktop.cpp @@ -21,7 +21,7 @@ #include "desktop.h" #include "info.h" #include "launcher.h" -#include "mrulist.h" +//#include "mrulist.h" #include "qcopbridge.h" #include "shutdownimpl.h" #include "startmenu.h" @@ -318,7 +318,7 @@ void DesktopApplication::switchLCD ( bool on ) { if ( qApp ) { DesktopApplication *dapp = (DesktopApplication *) qApp; - + if ( dapp-> m_screensaver ) dapp-> m_screensaver-> setBacklight ( on ? -3 : -1 ); } @@ -727,7 +727,7 @@ void Desktop::executeOrModify( const QString& appLnkFile ) QCString app = lnk.exec().utf8(); Global::terminateBuiltin( "calibrate" ); if ( QCopChannel::isRegistered( "QPE/Application/" + app ) ) { - MRUList::addTask( &lnk ); + // MRUList::addTask( &lnk ); if ( hasVisibleWindow( app ) ) QCopChannel::send( "QPE/Application/" + app, "nextView()" ); else diff --git a/core/launcher/launcher.cpp b/core/launcher/launcher.cpp index effcd24..fd89410 100644 --- a/core/launcher/launcher.cpp +++ b/core/launcher/launcher.cpp @@ -58,7 +58,7 @@ #include "syncdialog.h" #include "desktop.h" #include <qpe/lnkproperties.h> -#include "mrulist.h" +//#include "mrulist.h" #include "qrsync.h" #include <stdlib.h> #include <unistd.h> @@ -730,8 +730,8 @@ void Launcher::systemMessage( const QCString &msg, const QByteArray &data) if ( msg == "closing(QString)" ){ QString app; stream >> app; - qWarning("app closed %s", app.latin1() ); - MRUList::removeTask( app ); + //qWarning("app closed %s", app.latin1() ); + // MRUList::removeTask( app ); }else if ( msg == "linkChanged(QString)" ) { QString link; stream >> link; diff --git a/core/launcher/launcher.pro b/core/launcher/launcher.pro index 5b32bc3..0e557aa 100644 --- a/core/launcher/launcher.pro +++ b/core/launcher/launcher.pro @@ -10,6 +10,7 @@ HEADERS = background.h \ taskbar.h \ sidething.h \ mrulist.h \ + runningappbar.h \ stabmon.h \ inputmethods.h \ systray.h \ @@ -51,6 +52,7 @@ SOURCES = background.cpp \ taskbar.cpp \ sidething.cpp \ mrulist.cpp \ + runningappbar.cpp \ stabmon.cpp \ inputmethods.cpp \ systray.cpp \ diff --git a/core/launcher/runningappbar.cpp b/core/launcher/runningappbar.cpp new file mode 100644 index 0000000..298f671 --- a/dev/null +++ b/core/launcher/runningappbar.cpp @@ -0,0 +1,287 @@ +/********************************************************************** +** 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 + +// For "kill" +#include <sys/types.h> +#include <signal.h> + +#include <qtimer.h> +#include <qpopupmenu.h> +#include <qmessagebox.h> +#include <qpainter.h> +#include "qprocess.h" +#include <qpe/qpeapplication.h> +#include <qpe/applnk.h> +#include <qpe/qcopenvelope_qws.h> +#include <qpe/global.h> +#include <qwindowsystem_qws.h> +#include "runningappbar.h" + +RunningAppBar::RunningAppBar(QWidget* parent) + : QFrame(parent), m_AppLnkSet(0L), m_SelectedAppIndex(-1) +{ + m_AppLnkSet = new AppLnkSet( QPEApplication::qpeDir() + "apps" ); + + 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&)) ); + + spacing = AppLnk::smallIconSize()+3; +} + +RunningAppBar::~RunningAppBar() { +} + +void RunningAppBar::newQcopChannel(const QString& channelName) { + QString prefix("QPE/Application/"); + if (channelName.startsWith(prefix)) { + QString appName = channelName.mid(prefix.length()); +// qDebug("App %s just connected!", appName.latin1()); + const AppLnk* newGuy = m_AppLnkSet->findExec(appName); + if (newGuy && !newGuy->isPreloaded()) { + addTask(*newGuy); + } + } +} + +void RunningAppBar::removedQcopChannel(const QString& channelName) { + QString prefix("QPE/Application/"); + if (channelName.startsWith(prefix)) { + QString appName = channelName.mid(prefix.length()); + qDebug("App %s just disconnected!", appName.latin1()); + const AppLnk* newGuy = m_AppLnkSet->findExec(appName); + if (newGuy) { + removeTask(*newGuy); + } + } +} + +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; + addTask(*m_AppLnkSet->findExec(appName)); + } else if ( msg == "fastAppHiding(QString)") { + QString appName; + stream >> appName; + removeTask(*m_AppLnkSet->findExec(appName)); + } +} + +void RunningAppBar::addTask(const AppLnk& appLnk) { +// qDebug("Added %s to app list.", appLnk.name().latin1()); + AppLnk* newApp = new AppLnk(appLnk); + newApp->setExec(appLnk.exec()); + m_AppList.prepend(newApp); + update(); +} + +void RunningAppBar::removeTask(const AppLnk& appLnk) { + unsigned int i = 0; + for (; i < m_AppList.count() ; i++) { + AppLnk* target = m_AppList.at(i); + if (target->exec() == appLnk.exec()) { + qDebug("Removing %s from app list.", appLnk.name().latin1()); + m_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. + m_SelectedAppIndex = 0; + int x=0; + QListIterator<AppLnk> it( m_AppList ); + for ( ; it.current(); ++it,++m_SelectedAppIndex,x+=spacing ) { + if ( x + spacing <= width() ) { + if ( e->x() >= x && e->x() < x+spacing ) { + if ( m_SelectedAppIndex < (int)m_AppList.count() ) { + repaint(FALSE); + return; + } + } + } else { + break; + } + } + m_SelectedAppIndex = -1; + repaint( FALSE ); +} + +void RunningAppBar::mouseReleaseEvent(QMouseEvent *e) +{ + if (e->button() == QMouseEvent::RightButton) { + return; + } + if ( m_SelectedAppIndex >= 0 ) { + QString channel = QString("QPE/Application/") + m_AppList.at(m_SelectedAppIndex)->exec(); + if (QCopChannel::isRegistered(channel.latin1())) { +// qDebug("%s is running!", m_AppList.at(m_SelectedAppIndex)->exec().latin1()); + QCopEnvelope e(channel.latin1(), "raise()"); + // This class will delete itself after hearing from the app or the timer expiring + (void)new AppMonitor(*m_AppList.at(m_SelectedAppIndex), *this); + } + else { + removeTask(*m_AppList.at(m_SelectedAppIndex)); + } + + m_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(m_AppList); + + for (; it.current(); i++, ++it ) { + if ( x + spacing <= width() ) { + curApp = it.current(); + if ( (int)i == m_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 ); +} + +const int AppMonitor::RAISE_TIMEOUT_MS = 500; + +AppMonitor::AppMonitor(const AppLnk& app, RunningAppBar& owner) + : QObject(0L), m_Owner(owner), m_App(app), m_PsProc(0L), m_AppKillerBox(0L) { + QCopChannel* channel = new QCopChannel( "QPE/System", this ); + connect( channel, SIGNAL(received(const QCString&, const QByteArray&)), + this, SLOT(received(const QCString&, const QByteArray&)) ); + connect(&m_Timer, SIGNAL(timeout()), this, SLOT(timerExpired())); + m_Timer.start(RAISE_TIMEOUT_MS, TRUE); +} + +AppMonitor::~AppMonitor() { + if (m_AppKillerBox) { + delete m_AppKillerBox; + m_AppKillerBox = 0L; + } +} + +void AppMonitor::received(const QCString& msg, const QByteArray& data) { + QDataStream stream( data, IO_ReadOnly ); + + if (msg == "appRaised(QString)") { + QString appName; + stream >> appName; + if (appName == m_App.exec()) { + // qDebug("Got a heartbeat from %s", appName.latin1()); + m_Timer.stop(); + // Check to make sure we're not waiting on user input... + if (m_AppKillerBox) { + // 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 m_AppKillerBox; + m_AppKillerBox = 0L; + } + else { + // Ok, we're not waiting on user input, so clean us up now. + // WE DELETE OURSELVES HERE! Don't do anything else!! + delete this; + } + } + } +} + +void AppMonitor::timerExpired() { + // qDebug("Checking in on %s", m_App.name().latin1()); + // We store this incase the application responds while we're + // waiting for user input so we know not to delete ourselves. This + // will be cleaned up in the destructor. + m_AppKillerBox = new QMessageBox(tr("Application Problem"), + tr("<p>%1 is not responding.</p>").arg(m_App.name()) + + tr("<p>Would you like to force the application to exit?</p>"), + QMessageBox::Warning, QMessageBox::Yes, + QMessageBox::No | QMessageBox::Default, + QMessageBox::NoButton); + if (m_AppKillerBox->exec() == QMessageBox::Yes) { + // qDebug("Killing the app!!! Bwuhahahaha!"); + m_PsProc = new QProcess(QString("ps")); + m_PsProc->addArgument("h"); + m_PsProc->addArgument("-C"); + m_PsProc->addArgument(m_App.exec()); + m_PsProc->addArgument("-o"); + m_PsProc->addArgument("pid"); + connect(m_PsProc, SIGNAL(processExited()), this, SLOT(psProcFinished())); + m_PsProc->start(); + } + else { + // qDebug("Wuss.."); + // WE DELETE OURSELVES HERE! Don't do anything else!! + delete this; + } +} + +void AppMonitor::psProcFinished() { + QString pid = m_PsProc->readLineStdout(); + delete m_PsProc; + m_PsProc = 0L; + + // qDebug("Killing app %s", pid.latin1()); + if (pid.isEmpty()) { + // Hmm.. did the application bail before we got there? + qDebug("AppMonitor: Tried to kill application %s but ps couldn't find it.", m_App.exec().latin1()); + } + else { + int success = kill(pid.toUInt(), SIGKILL); + if (success == 0) { + m_Owner.removeTask(m_App); + } + else { + qWarning("Could not kill task %s", m_App.exec().latin1()); + } + } + + // WE DELETE OURSELVES HERE! Don't do anything else!! + delete this; +} diff --git a/core/launcher/runningappbar.h b/core/launcher/runningappbar.h new file mode 100644 index 0000000..880bb69 --- a/dev/null +++ b/core/launcher/runningappbar.h @@ -0,0 +1,88 @@ +/********************************************************************** +** 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 RUNNING_APP_BAR_H +#define RUNNING_APP_BAR_H + +#include <qframe.h> +#include <qlist.h> +#include <qtimer.h> + +class AppLnk; +class AppLnkSet; +class QCString; +class QProcess; +class QMessageBox; + +class RunningAppBar : public QFrame { + Q_OBJECT + + public: + RunningAppBar(QWidget* parent); + ~RunningAppBar(); + + void addTask(const AppLnk& appLnk); + void removeTask(const AppLnk& appLnk); + void paintEvent(QPaintEvent* event); + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + QSize sizeHint() const; + + private slots: + void newQcopChannel(const QString& channel); + void removedQcopChannel(const QString& channel); + void received(const QCString& msg, const QByteArray& data); + + private: + AppLnkSet* m_AppLnkSet; + QList<AppLnk> m_AppList; + int m_SelectedAppIndex; + int spacing; +}; + +/** + * Internal class that checks back in on the process when timerExpired is called + * to make sure the process is on top. If it's not it displays a dialog + * box asking permission to kill it. + */ +class AppMonitor : public QObject { + Q_OBJECT + + public: + static const int RAISE_TIMEOUT_MS; + + AppMonitor(const AppLnk& app, RunningAppBar& owner); + ~AppMonitor(); + + private slots: + void timerExpired(); + void received(const QCString& msg, const QByteArray& data); + void psProcFinished(); + + private: + RunningAppBar& m_Owner; + const AppLnk& m_App; + QTimer m_Timer; + QProcess* m_PsProc; + QMessageBox* m_AppKillerBox; +}; + +#endif + diff --git a/core/launcher/startmenu.cpp b/core/launcher/startmenu.cpp index 5bac874..5506c55 100644 --- a/core/launcher/startmenu.cpp +++ b/core/launcher/startmenu.cpp @@ -20,7 +20,7 @@ #include "startmenu.h" #include "sidething.h" -#include "mrulist.h" +//#include "mrulist.h" #include "info.h" #include <qpe/qpeapplication.h> @@ -75,7 +75,7 @@ void StartMenu::loadOptions() useWidePopupMenu = ( tmpBoolString1 == "TRUE" ) ? TRUE : FALSE; QString tmpBoolString2 = config.readEntry( "StartButtonIsFlat", "TRUE" ); startButtonIsFlat = ( tmpBoolString2 == "TRUE" ) ? TRUE : FALSE; - QString tmpBoolString3 = config.readEntry( "UseMRUList", "TRUE" ); +// QString tmpBoolString3 = config.readEntry( "UseMRUList", "TRUE" ); popupMenuSidePixmap = config.readEntry( "PopupMenuSidePixmap", "launcher/sidebar" ); startButtonPixmap = config.readEntry( "StartButtonPixmap", "go" ); #else diff --git a/core/launcher/taskbar.cpp b/core/launcher/taskbar.cpp index e38b9fe..9f397eb 100644 --- a/core/launcher/taskbar.cpp +++ b/core/launcher/taskbar.cpp @@ -21,6 +21,7 @@ #include "startmenu.h" #include "inputmethods.h" #include "mrulist.h" +#include "runningappbar.h" #include "systray.h" #include "calibrate.h" #include "wait.h" @@ -155,8 +156,11 @@ TaskBar::TaskBar() : QHBox(0, 0, WStyle_Customize | WStyle_Tool | WStyle_StaysOn stack->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ) ); label = new QLabel(stack); - mru = new MRUList( stack ); - stack->raiseWidget( mru ); + //mru = new MRUList( stack ); + //stack->raiseWidget( mru ); + + runningAppBar = new RunningAppBar(stack); + stack->raiseWidget(runningAppBar); waitIcon = new Wait( this ); (void) new AppIcons( this ); @@ -166,7 +170,7 @@ TaskBar::TaskBar() : QHBox(0, 0, WStyle_Customize | WStyle_Tool | WStyle_StaysOn // ## make customizable in some way? #ifdef QT_QWS_CUSTOM lockState = new LockKeyState( this ); -#else +y#else lockState = 0; #endif @@ -196,7 +200,8 @@ void TaskBar::setStatusMessage( const QString &text ) void TaskBar::clearStatusBar() { label->clear(); - stack->raiseWidget( mru ); + stack->raiseWidget(runningAppBar); + // stack->raiseWidget( mru ); } void TaskBar::startWait() @@ -209,13 +214,14 @@ void TaskBar::startWait() void TaskBar::stopWait(const QString& app) { waitTimer->stop(); - mru->addTask(sm->execToLink(app)); + //mru->addTask(sm->execToLink(app)); waitIcon->setWaiting( false ); } void TaskBar::stopWait() { waitTimer->stop(); + waitIcon->setWaiting( false ); } @@ -274,7 +280,7 @@ void TaskBar::receive( const QCString &msg, const QByteArray &data ) else if ( msg == "setLed(int,bool)" ) { int led, status; stream >> led >> status; - + ODevice::inst ( )-> setLed ( led, status ? OLED_BlinkSlow : OLED_Off ); } } @@ -311,6 +317,7 @@ void TaskBar::toggleSymbolInput() bool TaskBar::recoverMemory() { - return mru->quitOldApps(); + //eturn mru->quitOldApps(); + return true; } diff --git a/core/launcher/taskbar.h b/core/launcher/taskbar.h index 40983af..cd631ef 100644 --- a/core/launcher/taskbar.h +++ b/core/launcher/taskbar.h @@ -28,7 +28,8 @@ class QTimer; class InputMethods; class Wait; class SysTray; -class MRUList; +//class MRUList; +class RunningAppBar; class QWidgetStack; class QTimer; class QLabel; @@ -59,18 +60,19 @@ protected: void resizeEvent( QResizeEvent * ); void styleChange( QStyle & ); void setStatusMessage( const QString &text ); - + private slots: void calcMaxWindowRect(); void receive( const QCString &msg, const QByteArray &data ); private: - + QTimer *waitTimer; Wait *waitIcon; InputMethods *inputMethods; SysTray *sysTray; - MRUList *mru; + // MRUList *mru; + RunningAppBar* runningAppBar; QWidgetStack *stack; QTimer *clearer; QLabel *label; |