author | harlekin <harlekin> | 2002-09-09 18:21:06 (UTC) |
---|---|---|
committer | harlekin <harlekin> | 2002-09-09 18:21:06 (UTC) |
commit | c9442bf567252553da8ce216de1e64cbf70db3bd (patch) (side-by-side diff) | |
tree | 8eedf088cc2ad2608287a5e6c94ad05587fa9dc0 | |
parent | 3044db24e632adbcf5dbbf1874944d54cee7c8e3 (diff) | |
download | opie-c9442bf567252553da8ce216de1e64cbf70db3bd.zip opie-c9442bf567252553da8ce216de1e64cbf70db3bd.tar.gz opie-c9442bf567252553da8ce216de1e64cbf70db3bd.tar.bz2 |
mrulist is dead, long live runningappbar, hopefully
-rw-r--r-- | core/launcher/desktop.cpp | 4 | ||||
-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 | 19 | ||||
-rw-r--r-- | core/launcher/taskbar.h | 6 |
8 files changed, 401 insertions, 15 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 @@ -22,5 +22,5 @@ #include "info.h" #include "launcher.h" -#include "mrulist.h" +//#include "mrulist.h" #include "qcopbridge.h" #include "shutdownimpl.h" @@ -728,5 +728,5 @@ void Desktop::executeOrModify( const QString& appLnkFile ) Global::terminateBuiltin( "calibrate" ); if ( QCopChannel::isRegistered( "QPE/Application/" + app ) ) { - MRUList::addTask( &lnk ); + // MRUList::addTask( &lnk ); if ( hasVisibleWindow( app ) ) QCopChannel::send( "QPE/Application/" + app, "nextView()" ); 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 @@ -59,5 +59,5 @@ #include "desktop.h" #include <qpe/lnkproperties.h> -#include "mrulist.h" +//#include "mrulist.h" #include "qrsync.h" #include <stdlib.h> @@ -731,6 +731,6 @@ void Launcher::systemMessage( const QCString &msg, const QByteArray &data) 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; 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 @@ -11,4 +11,5 @@ HEADERS = background.h \ sidething.h \ mrulist.h \ + runningappbar.h \ stabmon.h \ inputmethods.h \ @@ -52,4 +53,5 @@ SOURCES = background.cpp \ sidething.cpp \ mrulist.cpp \ + runningappbar.cpp \ stabmon.cpp \ inputmethods.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 @@ -21,5 +21,5 @@ #include "startmenu.h" #include "sidething.h" -#include "mrulist.h" +//#include "mrulist.h" #include "info.h" @@ -76,5 +76,5 @@ void StartMenu::loadOptions() 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" ); 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 @@ -22,4 +22,5 @@ #include "inputmethods.h" #include "mrulist.h" +#include "runningappbar.h" #include "systray.h" #include "calibrate.h" @@ -156,6 +157,9 @@ TaskBar::TaskBar() : QHBox(0, 0, WStyle_Customize | WStyle_Tool | WStyle_StaysOn 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 ); @@ -167,5 +171,5 @@ TaskBar::TaskBar() : QHBox(0, 0, WStyle_Customize | WStyle_Tool | WStyle_StaysOn #ifdef QT_QWS_CUSTOM lockState = new LockKeyState( this ); -#else +y#else lockState = 0; #endif @@ -197,5 +201,6 @@ void TaskBar::clearStatusBar() { label->clear(); - stack->raiseWidget( mru ); + stack->raiseWidget(runningAppBar); + // stack->raiseWidget( mru ); } @@ -210,5 +215,5 @@ void TaskBar::stopWait(const QString& app) { waitTimer->stop(); - mru->addTask(sm->execToLink(app)); + //mru->addTask(sm->execToLink(app)); waitIcon->setWaiting( false ); } @@ -217,4 +222,5 @@ void TaskBar::stopWait() { waitTimer->stop(); + waitIcon->setWaiting( false ); } @@ -312,5 +318,6 @@ 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 @@ -29,5 +29,6 @@ class InputMethods; class Wait; class SysTray; -class MRUList; +//class MRUList; +class RunningAppBar; class QWidgetStack; class QTimer; @@ -71,5 +72,6 @@ private: InputMethods *inputMethods; SysTray *sysTray; - MRUList *mru; + // MRUList *mru; + RunningAppBar* runningAppBar; QWidgetStack *stack; QTimer *clearer; |