-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 @@ -16,17 +16,17 @@ ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #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" #include "transferserver.h" #include "irserver.h" #include "packageslave.h" @@ -313,17 +313,17 @@ private: bool m_backlight_forcedoff; }; void DesktopApplication::switchLCD ( bool on ) { if ( qApp ) { DesktopApplication *dapp = (DesktopApplication *) qApp; - + if ( dapp-> m_screensaver ) dapp-> m_screensaver-> setBacklight ( on ? -3 : -1 ); } } DesktopApplication::DesktopApplication( int& argc, char **argv, Type appType ) : QPEApplication( argc, argv, appType ) @@ -722,17 +722,17 @@ void Desktop::raiseLauncher() void Desktop::executeOrModify( const QString& appLnkFile ) { AppLnk lnk( MimeType::appsFolderName() + "/" + 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()" ); } else { lnk.execute(); } 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 @@ -53,17 +53,17 @@ #include <qlabel.h> #include <qtextstream.h> #include "launcherview.h" #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> #if defined(_OS_LINUX_) || defined(Q_OS_LINUX) #include <stdio.h> #include <sys/vfs.h> #include <mntent.h> @@ -725,18 +725,18 @@ void Launcher::updateLink(const QString& link) } 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 ) { got_lnk_change = TRUE; lnk_change = link; } else { updateLink(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 @@ -5,16 +5,17 @@ HEADERS = background.h \ desktop.h \ qprocess.h \ mediummountgui.h \ info.h \ appicons.h \ taskbar.h \ sidething.h \ mrulist.h \ + runningappbar.h \ stabmon.h \ inputmethods.h \ systray.h \ wait.h \ shutdownimpl.h \ launcher.h \ launcherview.h \ ../../core/apps/calibrate/calibrate.h \ @@ -46,16 +47,17 @@ SOURCES = background.cpp \ desktop.cpp \ mediummountgui.cpp \ qprocess.cpp qprocess_unix.cpp \ info.cpp \ appicons.cpp \ taskbar.cpp \ sidething.cpp \ mrulist.cpp \ + runningappbar.cpp \ stabmon.cpp \ inputmethods.cpp \ systray.cpp \ wait.cpp \ shutdownimpl.cpp \ launcher.cpp \ launcherview.cpp \ ../../core/apps/calibrate/calibrate.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 @@ -15,17 +15,17 @@ ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "startmenu.h" #include "sidething.h" -#include "mrulist.h" +//#include "mrulist.h" #include "info.h" #include <qpe/qpeapplication.h> #include <qpe/config.h> #include <qpe/applnk.h> #include <qpe/global.h> #include <qpe/resource.h> @@ -70,17 +70,17 @@ void StartMenu::loadOptions() #ifdef USE_CONFIG_FILE // Read configuration file Config config("StartMenu"); config.setGroup( "StartMenu" ); 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 useWidePopupMenu = FALSE; popupMenuSidePixmap = "lauchner/sidebar"; startButtonIsFlat = TRUE; startButtonPixmap = "launcher/start_button"; 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 @@ -16,16 +16,17 @@ ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** *********************************************************************/ #include "startmenu.h" #include "inputmethods.h" #include "mrulist.h" +#include "runningappbar.h" #include "systray.h" #include "calibrate.h" #include "wait.h" #include "appicons.h" #include "taskbar.h" #include "desktop.h" @@ -150,28 +151,31 @@ TaskBar::TaskBar() : QHBox(0, 0, WStyle_Customize | WStyle_Tool | WStyle_StaysOn connect( inputMethods, SIGNAL(inputToggled(bool)), this, SLOT(calcMaxWindowRect()) ); //new QuickLauncher( this ); 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 ); sysTray = new SysTray( this ); // ## make customizable in some way? #ifdef QT_QWS_CUSTOM lockState = new LockKeyState( this ); -#else +y#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&)) ); @@ -191,36 +195,38 @@ void TaskBar::setStatusMessage( const QString &text ) if ( sysTray && ( label->fontMetrics().width( text ) > label->width() ) ) sysTray->hide(); clearer->start( 3000 ); } void TaskBar::clearStatusBar() { label->clear(); - stack->raiseWidget( mru ); + stack->raiseWidget(runningAppBar); + // 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& 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 ) { QHBox::resizeEvent( e ); calcMaxWindowRect(); } @@ -269,17 +275,17 @@ void TaskBar::receive( const QCString &msg, const QByteArray &data ) } else if ( msg == "reloadApplets()" ) { sysTray->loadApplets(); } else if ( msg == "soundAlarm()" ) { Desktop::soundAlarm(); } else if ( msg == "setLed(int,bool)" ) { int led, status; stream >> led >> status; - + ODevice::inst ( )-> setLed ( led, status ? OLED_BlinkSlow : OLED_Off ); } } QWidget *TaskBar::calibrate(bool) { #ifdef Q_WS_QWS Calibrate *c = new Calibrate; @@ -306,11 +312,12 @@ void TaskBar::toggleSymbolInput() inputMethods->hideInputMethod(); } else { inputMethods->showInputMethod("Unicode"); } } 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 @@ -23,17 +23,18 @@ #include <qhbox.h> class QLabel; class QTimer; class InputMethods; class Wait; class SysTray; -class MRUList; +//class MRUList; +class RunningAppBar; class QWidgetStack; class QTimer; class QLabel; class StartMenu; class LockKeyState; class TaskBar : public QHBox { Q_OBJECT @@ -54,28 +55,29 @@ public slots: void toggleNumLockState(); void toggleCapsLockState(); void toggleSymbolInput(); 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; LockKeyState* lockState; StartMenu *sm; }; |