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 @@ -20,9 +20,9 @@ #include "desktop.h" #include "info.h" #include "launcher.h" -#include "mrulist.h" +//#include "mrulist.h" #include "qcopbridge.h" #include "shutdownimpl.h" #include "startmenu.h" #include "taskbar.h" @@ -726,9 +726,9 @@ void Desktop::executeOrModify( const QString& appLnkFile ) if ( lnk.isValid() ) { 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 QCopChannel::send( "QPE/Application/" + app, "raise()" ); 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 @@ -57,9 +57,9 @@ #include "launcher.h" #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> @@ -729,10 +729,10 @@ void Launcher::systemMessage( const QCString &msg, const QByteArray &data) QDataStream stream( data, IO_ReadOnly ); 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; if ( in_lnk_props ) { 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 @@ -9,8 +9,9 @@ HEADERS = background.h \ appicons.h \ taskbar.h \ sidething.h \ mrulist.h \ + runningappbar.h \ stabmon.h \ inputmethods.h \ systray.h \ wait.h \ @@ -50,8 +51,9 @@ SOURCES = background.cpp \ appicons.cpp \ taskbar.cpp \ sidething.cpp \ mrulist.cpp \ + runningappbar.cpp \ stabmon.cpp \ inputmethods.cpp \ systray.cpp \ wait.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 @@ -19,9 +19,9 @@ **********************************************************************/ #include "startmenu.h" #include "sidething.h" -#include "mrulist.h" +//#include "mrulist.h" #include "info.h" #include <qpe/qpeapplication.h> #include <qpe/config.h> @@ -74,9 +74,9 @@ void StartMenu::loadOptions() QString tmpBoolString1 = config.readEntry( "UseWidePopupMenu", "FALSE" ); 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 // Basically just #include the .qpe_menu.conf file settings 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 @@ -20,8 +20,9 @@ #include "startmenu.h" #include "inputmethods.h" #include "mrulist.h" +#include "runningappbar.h" #include "systray.h" #include "calibrate.h" #include "wait.h" #include "appicons.h" @@ -154,10 +155,13 @@ TaskBar::TaskBar() : QHBox(0, 0, WStyle_Customize | WStyle_Tool | WStyle_StaysOn stack = new QWidgetStack( this ); 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 ); @@ -165,9 +169,9 @@ 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 #if defined(Q_WS_QWS) @@ -195,9 +199,10 @@ void TaskBar::setStatusMessage( const QString &text ) void TaskBar::clearStatusBar() { label->clear(); - stack->raiseWidget( mru ); + stack->raiseWidget(runningAppBar); + // stack->raiseWidget( mru ); } void TaskBar::startWait() { @@ -208,15 +213,16 @@ 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 ); } void TaskBar::resizeEvent( QResizeEvent *e ) @@ -310,7 +316,8 @@ 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 @@ -27,9 +27,10 @@ class QLabel; class QTimer; class InputMethods; class Wait; class SysTray; -class MRUList; +//class MRUList; +class RunningAppBar; class QWidgetStack; class QTimer; class QLabel; class StartMenu; @@ -69,9 +70,10 @@ private: QTimer *waitTimer; Wait *waitIcon; InputMethods *inputMethods; SysTray *sysTray; - MRUList *mru; + // MRUList *mru; + RunningAppBar* runningAppBar; QWidgetStack *stack; QTimer *clearer; QLabel *label; LockKeyState* lockState; |