-rw-r--r-- | library/qpeapplication.cpp | 124 | ||||
-rw-r--r-- | library/qpeapplication.h | 5 |
2 files changed, 98 insertions, 31 deletions
diff --git a/library/qpeapplication.cpp b/library/qpeapplication.cpp index 9286f9f..149e6bb 100644 --- a/library/qpeapplication.cpp +++ b/library/qpeapplication.cpp @@ -1,85 +1,84 @@ /********************************************************************** ** 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. ** -** $Id$ -** -**********************************************************************/ +*/ #define QTOPIA_INTERNAL_LANGLIST #include <stdlib.h> #include <unistd.h> #include <linux/limits.h> // needed for some toolchains (PATH_MAX) #include <qfile.h> #ifdef Q_WS_QWS #ifndef QT_NO_COP #if QT_VERSION <= 231 #define private public #define sendLocally processEvent #include "qcopenvelope_qws.h" #undef private #else #include "qcopenvelope_qws.h" #endif #endif #include <qwindowsystem_qws.h> #endif #include <qtextstream.h> #include <qpalette.h> #include <qbuffer.h> #include <qptrdict.h> #include <qregexp.h> #include <qdir.h> #include <qlabel.h> #include <qdialog.h> #include <qdragobject.h> #include <qtextcodec.h> #include <qevent.h> #include <qtooltip.h> #include <qsignal.h> #include <qmainwindow.h> +#include <qwidgetlist.h> #if defined(Q_WS_QWS) && !defined(QT_NO_COP) #define QTOPIA_INTERNAL_INITAPP #include "qpeapplication.h" #include "qpestyle.h" #include "styleinterface.h" #if QT_VERSION >= 300 #include <qstylefactory.h> #else #include <qplatinumstyle.h> #include <qwindowsstyle.h> #include <qmotifstyle.h> #include <qmotifplusstyle.h> #include "lightstyle.h" #include <qpe/qlibrary.h> #endif #include "global.h" #include "resource.h" #if QT_VERSION <= 230 && defined(QT_NO_CODECS) #include "qutfcodec.h" #endif #include "config.h" #include "network.h" #ifdef QWS #include "fontmanager.h" #endif #include "alarmserver.h" #include "applnk.h" #include "qpemenubar.h" #include "textcodecinterface.h" @@ -88,78 +87,82 @@ #include <unistd.h> #include <sys/file.h> #include <sys/ioctl.h> #include <sys/soundcard.h> #include "qt_override_p.h" class QPEApplicationData { public: QPEApplicationData ( ) : presstimer( 0 ), presswidget( 0 ), rightpressed( false ), kbgrabbed( false ), notbusysent( false ), preloaded( false ), forceshow( false ), nomaximize( false ), keep_running( true ), qpe_main_widget( 0 ) { qcopq.setAutoDelete( TRUE ); } int presstimer; QWidget* presswidget; QPoint presspos; bool rightpressed : 1; bool kbgrabbed : 1; bool notbusysent : 1; bool preloaded : 1; bool forceshow : 1; bool nomaximize : 1; bool keep_running : 1; + QStringList langs; QString appName; struct QCopRec { QCopRec( const QCString &ch, const QCString &msg, const QByteArray &d ) : channel( ch ), message( msg ), data( d ) { } QCString channel; QCString message; QByteArray data; }; QWidget* qpe_main_widget; + QGuardedPtr<QWidget> lastWidget; QList<QCopRec> qcopq; + QString styleName; + QString decorationName; void enqueueQCop( const QCString &ch, const QCString &msg, const QByteArray &data ) { qcopq.append( new QCopRec( ch, msg, data ) ); } void sendQCopQ() { QCopRec * r; #ifndef QT_NO_COP for ( QListIterator<QCopRec> it( qcopq ); ( r = it.current() ); ++it ) QCopChannel::sendLocally( r->channel, r->message, r->data ); #endif qcopq.clear(); } static void show_mx(QWidget* mw, bool nomaximize) { // ugly hack, remove that later after finding a sane solution // Addendum: Only Sharp currently has models with high resolution but (physically) small displays, // so this is only useful if QT_QWS_SIMPAD is NOT defined. E.g. SIMpad has 800x600 but has // a (physically) large enough display to use the small icons #ifndef QT_QWS_SIMPAD if ( QPEApplication::desktop() ->width() >= 600 && ( mw->inherits("QMainWindow") || mw->isA("QMainWindow") ) ) { ( ( QMainWindow* ) mw )->setUsesBigPixmaps( true ); } #endif if ( mw->layout() && mw->inherits("QDialog") ) { QPEApplication::showDialog((QDialog*)mw, nomaximize); @@ -237,66 +240,64 @@ public: } else { lib->unload(); delete lib; } } } void loadImageCodecs() { QString path = QPEApplication::qpeDir() + "/plugins/imagecodecs"; QDir dir( path, "lib*.so" ); QStringList list; if ( dir. exists ( )) list = dir.entryList(); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { ImageCodecInterface *iface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if ( lib->queryInterface( IID_QtopiaImageCodec, (QUnknownInterface**)&iface ) == QS_OK && iface ) { QStringList formats = iface->keys(); for (QStringList::ConstIterator i = formats.begin(); i != formats.end(); ++i) { (void)iface->installIOHandler(*i); // ### it exists now; need to remember if we can delete it } } else { lib->unload(); delete lib; } } } - QString styleName; - QString decorationName; }; class ResourceMimeFactory : public QMimeSourceFactory { public: ResourceMimeFactory() : resImage( 0 ) { setFilePath( Global::helpPath() ); setExtensionType( "html", "text/html;charset=UTF-8" ); } ~ResourceMimeFactory() { delete resImage; } const QMimeSource* data( const QString& abs_name ) const { const QMimeSource * r = QMimeSourceFactory::data( abs_name ); if ( !r ) { int sl = abs_name.length(); do { sl = abs_name.findRev( '/', sl - 1 ); QString name = sl >= 0 ? abs_name.mid( sl + 1 ) : abs_name; int dot = name.findRev( '.' ); if ( dot >= 0 ) name = name.left( dot ); QImage img = Resource::loadImage( name ); if ( !img.isNull() ) { delete resImage; resImage = new QImageDrag( img ); r = resImage; } } @@ -634,66 +635,66 @@ QPEApplication::QPEApplication( int & argc, char **argv, Type t ) flock( f.handle(), LOCK_UN ); f.close(); f.remove(); } for ( int a = 0; a < argc; a++ ) { if ( qstrcmp( argv[ a ], "-preload" ) == 0 ) { argv[ a ] = argv[ a + 1 ]; a++; d->preloaded = TRUE; argc -= 1; } else if ( qstrcmp( argv[ a ], "-preload-show" ) == 0 ) { argv[ a ] = argv[ a + 1 ]; a++; d->preloaded = TRUE; d->forceshow = TRUE; argc -= 1; } } /* overide stored arguments */ setArgs( argc, argv ); #endif #else initApp( argc, argv ); #endif // qwsSetDecoration( new QPEDecoration() ); #ifndef QT_NO_TRANSLATION - QStringList langs = Global::languageList(); - for ( QStringList::ConstIterator it = langs.begin(); it != langs.end(); ++it ) { + d->langs = Global::languageList(); + for ( QStringList::ConstIterator it = d->langs.begin(); it != d->langs.end(); ++it ) { QString lang = *it; installTranslation( lang + "/libopie.qm"); installTranslation( lang + "/libqpe.qm" ); installTranslation( lang + "/" + d->appName + ".qm" ); //###language/font hack; should look it up somewhere #ifdef QWS if ( lang == "ja" || lang == "zh_CN" || lang == "zh_TW" || lang == "ko" ) { QFont fn = FontManager::unicodeFont( FontManager::Proportional ); setFont( fn ); } #endif } #endif applyStyle(); if ( type() == GuiServer ) { setVolume(); } installEventFilter( this ); QPEMenuToolFocusManager::initialize(); #ifdef QT_NO_QWS_CURSOR // if we have no cursor, probably don't want tooltips QToolTip::setEnabled( FALSE ); #endif @@ -713,64 +714,68 @@ void QPEApplication::initApp( int argc, char **argv ) channel.replace(QRegExp(".*/"),""); d->appName = channel; #if QT_VERSION > 235 qt_fbdpy->setIdentity( channel ); // In Qt/E 2.3.6 #endif channel = "QPE/Application/" + channel; pidChannel = new QCopChannel( channel, this); connect( pidChannel, SIGNAL(received(const QCString &, const QByteArray &)), this, SLOT(pidMessage(const QCString &, const QByteArray &))); processQCopFile(); d->keep_running = d->qcopq.isEmpty(); for (int a=0; a<argc; a++) { if ( qstrcmp(argv[a],"-preload")==0 ) { argv[a] = argv[a+1]; a++; d->preloaded = TRUE; argc-=1; } else if ( qstrcmp(argv[a],"-preload-show")==0 ) { argv[a] = argv[a+1]; a++; d->preloaded = TRUE; d->forceshow = TRUE; argc-=1; } } /* overide stored arguments */ setArgs(argc, argv); + + /* install translation here */ + for ( QStringList::ConstIterator it = d->langs.begin(); it != d->langs.end(); ++it ) + installTranslation( (*it) + "/" + d->appName + ".qm" ); } #endif static QPtrDict<void>* inputMethodDict = 0; static void createInputMethodDict() { if ( !inputMethodDict ) inputMethodDict = new QPtrDict<void>; } /*! Returns the currently set hint to the system as to whether widget \a w has any use for text input methods. \sa setInputMethodHint() InputMethodHint */ QPEApplication::InputMethodHint QPEApplication::inputMethodHint( QWidget * w ) { if ( inputMethodDict && w ) return ( InputMethodHint ) ( int ) inputMethodDict->find( w ); return Normal; } /*! \enum QPEApplication::InputMethodHint \value Normal the application sometimes needs text input (the default). \value AlwaysOff the application never needs text input. \value AlwaysOn the application always needs text input. */ @@ -1282,159 +1287,218 @@ void QPEApplication::systemMessage( const QCString& msg, const QByteArray& data } else if ( msg == "bassChange(bool)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> setBass(); } else if ( msg == "setTreble(int,int)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> int t, v; stream >> t >> v; setTreble( t, v ); } else if ( msg == "trebleChange(bool)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> setTreble(); } else if ( msg == "getMarkedText()" ) { if ( type() == GuiServer ) { const ushort unicode = 'C'-'@'; const int scan = Key_C; qwsServer->processKeyEvent( unicode, scan, ControlButton, TRUE, FALSE ); qwsServer->processKeyEvent( unicode, scan, ControlButton, FALSE, FALSE ); } } else if ( msg == "newChannel(QString)") { QString myChannel = "QPE/Application/" + d->appName; QString channel; stream >> channel; if (channel == myChannel) { processQCopFile(); d->sendQCopQ(); } } #endif } +#include <qmetaobject.h> + +QWidget *QPEApplication::nextWidget(QWidgetList* list, QWidget* _wid) { + QWidget *next = 0; + if ( list->isEmpty() || list->count() == 1 ) + next = _wid; + else{ + QWidget* wid; + uint idx = list->findRef( _wid ); + uint count = list->count(); + + /* one time through the list hacky we may not start with idx but end with it*/ + for (uint i = (idx + 1)%count; true; i=(i+1)%count ) { + wid = list->at(i); + if ( wid == _wid ) { + next = _wid; + break; + }else if ((( wid->inherits("QMainWindow") || + wid->inherits("QDialog") ) && + wid != qApp->desktop() && !wid->isHidden() ) || + ( wid == mainWidget() || wid == d->qpe_main_widget ) ){ + next = wid; + break; + } + } + } + + delete list; + return next; +} /*! \internal */ +// ########## raise()ing main window should raise and set active +// ########## it and then all childen. This belongs in Qt/Embedded +/* + * slightly change in behaviour to kill the need of modality in Opie + * If any of the topLevelWidgets !isFullyObscured we highlight the next + * top level window + * 1)If visible and not modal we iterate over the list of top level widgets + * 2)If modal we we make the modal and its parent toplevel widget visible if available + * 3)else make topLevel visible + * + * send qcop if necessary and save current visible widget if not modal + */ bool QPEApplication::raiseAppropriateWindow() { bool r = FALSE; - // ########## raise()ing main window should raise and set active - // ########## it and then all childen. This belongs in Qt/Embedded - QWidget *top = d->qpe_main_widget; - if ( !top ) - top = mainWidget(); - if ( top && d->keep_running ) { - if ( top->isVisible() ) - r = TRUE; - else if (d->preloaded) { - // We are preloaded and not visible.. pretend we just started.. - QCopEnvelope e("QPE/System", "fastAppShowing(QString)"); - e << d->appName; - } + QWidget *top = d->qpe_main_widget ? d->qpe_main_widget : mainWidget(); + /* 1. */ + if ( ( top && (top->isVisible() ) || ( d->lastWidget && d->lastWidget->isVisible() ) ) && + !activeModalWidget() ) { + r = TRUE; + /*wid will be valid and topLevelWidgets will be deleted properly.. */ + QWidget *wid = nextWidget( topLevelWidgets(), + d->lastWidget ? (QWidget*)d->lastWidget : top ); + /* keep the size window got but not for root*/ + if ( top == wid ) + d->show_mx(top, d->nomaximize ); + else + wid->show(); + + wid->raise(); + wid->setActiveWindow(); + d->lastWidget = wid; + }else if ( activeModalWidget() ) { + QWidget* mod = activeModalWidget(); + /* get the parent of the modal and its topLevelWidget as background widget */ + QWidget* par = activeModalWidget()->parentWidget() ? activeModalWidget()->parentWidget()->topLevelWidget() : 0; + if (par ) { + if (par == top ) + d->show_mx(par, d->nomaximize ); + else + par->show(); + par->raise(); + par->setActiveWindow(); + } + mod->show(); + mod->raise(); + mod->setActiveWindow(); + }else if (top){ d->show_mx(top, d->nomaximize); top->raise(); top->setActiveWindow(); + d->lastWidget = top; } - QWidget *topm = activeModalWidget(); - if ( topm && topm != top ) { - topm->show(); - topm->raise(); - topm->setActiveWindow(); - // If we haven't already handled the fastAppShowing message - if (!top && d->preloaded) { + + if (!r && d->preloaded ) { QCopEnvelope e("QPE/System", "fastAppShowing(QString)"); e << d->appName; } - r = FALSE; - } + return r; } + void QPEApplication::pidMessage( const QCString& msg, const QByteArray& data) { #ifdef Q_WS_QWS if ( msg == "quit()" ) { tryQuit(); } else if ( msg == "quitIfInvisible()" ) { if ( d->qpe_main_widget && !d->qpe_main_widget->isVisible() ) quit(); } else if ( msg == "close()" ) { hideOrQuit(); } else if ( msg == "disablePreload()" ) { d->preloaded = FALSE; d->keep_running = TRUE; /* so that quit will quit */ } else if ( msg == "enablePreload()" ) { if (d->qpe_main_widget) d->preloaded = TRUE; d->keep_running = TRUE; /* so next quit won't quit */ } else if ( msg == "raise()" ) { d->keep_running = TRUE; d->notbusysent = FALSE; raiseAppropriateWindow(); // Tell the system we're still chugging along... QCopEnvelope e("QPE/System", "appRaised(QString)"); e << d->appName; } else if ( msg == "flush()" ) { emit flush(); // we need to tell the desktop QCopEnvelope e( "QPE/Desktop", "flushDone(QString)" ); e << d->appName; } else if ( msg == "reload()" ) { emit reload(); } else if ( msg == "setDocument(QString)" ) { d->keep_running = TRUE; QDataStream stream( data, IO_ReadOnly ); QString doc; stream >> doc; QWidget *mw = mainWidget(); if ( !mw ) mw = d->qpe_main_widget; if ( mw ) Global::setDocument( mw, doc ); + } else if ( msg == "QPEProcessQCop()" ) { processQCopFile(); d->sendQCopQ(); - } + }else { bool p = d->keep_running; d->keep_running = FALSE; emit appMessage( msg, data); if ( d->keep_running ) { d->notbusysent = FALSE; raiseAppropriateWindow(); if ( !p ) { // Tell the system we're still chugging along... #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "appRaised(QString)"); e << d->appName; #endif } } if ( p ) d->keep_running = p; } #endif } /*! Sets widget \a mw as the mainWidget() and shows it. For small windows, consider passing TRUE for \a nomaximize rather than the default FALSE. \sa showMainDocumentWidget() */ void QPEApplication::showMainWidget( QWidget* mw, bool nomaximize ) { d->show(mw, nomaximize ); } diff --git a/library/qpeapplication.h b/library/qpeapplication.h index 770ea23..343e0b9 100644 --- a/library/qpeapplication.h +++ b/library/qpeapplication.h @@ -84,64 +84,67 @@ public: static int execDialog( QDialog*, bool nomax=FALSE ); /* Merge setTempScreenSaverMode */ #ifdef QTOPIA_INTERNAL_INITAPP void initApp( int argv, char **argv ); #endif static void setKeepRunning(); bool keepRunning() const; bool keyboardGrabbed() const; int exec(); signals: void clientMoused(); void timeChanged(); void clockChanged( bool pm ); void micChanged( bool muted ); void volumeChanged( bool muted ); void appMessage( const QCString& msg, const QByteArray& data); void weekChanged( bool startOnMonday ); void dateFormatChanged( DateFormat ); void flush(); void reload(); /* linkChanged signal */ private slots: void systemMessage( const QCString &msg, const QByteArray &data ); void pidMessage( const QCString &msg, const QByteArray &data ); void removeSenderFromStylusDict(); void hideOrQuit(); +private: + inline QWidget *nextWidget( QWidgetList*, QWidget* ); + protected: bool qwsEventFilter( QWSEvent * ); void internalSetStyle( const QString &style ); void prepareForTermination(bool willrestart); virtual void restart(); virtual void shutdown(); bool eventFilter( QObject *, QEvent * ); void timerEvent( QTimerEvent * ); bool raiseAppropriateWindow(); virtual void tryQuit(); #if QT_VERSION > 233 virtual void polish ( QWidget * ); // this is actually implemented in qt_override.cpp (!) #endif private: #ifndef QT_NO_TRANSLATION void installTranslation( const QString& baseName ); #endif void mapToDefaultAction( QWSKeyEvent *ke, int defKey ); void processQCopFile(); #if defined(Q_WS_QWS) && !defined(QT_NO_COP) QCopChannel *sysChannel; QCopChannel *pidChannel; #endif QPEApplicationData *d; bool reserved_sh; }; @@ -164,41 +167,41 @@ inline void QPEApplication::showDialog( QDialog* d, bool nomax ) inline int QPEApplication::execDialog( QDialog* d, bool nomax ) { showDialog(d,nomax); return d->exec(); } enum Transformation { Rot0, Rot90, Rot180, Rot270 }; /* from qgfxtransformed_qws.cpp */ inline int TransToDeg ( Transformation t ) { int d = static_cast<int>( t ); return d * 90; } inline Transformation DegToTrans ( int d ) { Transformation t = static_cast<Transformation>( d / 90 ); return t; } /* * Set current rotation of Opie, and rotation for newly started apps. * Differs from setDefaultRotation in that 1) it rotates currently running apps, * and 2) does not set deforient or save orientation to qpe.conf. */ inline void QPEApplication::setCurrentRotation( int r ) { // setTransformation has been introduced in Qt/Embedded 2.3.4 snapshots // for compatibility with the SharpROM use fallback to setDefaultTransformation() #if QT_VERSION > 233 Transformation e = DegToTrans( r ); - setenv( "QWS_DISPLAY", QString( "Transformed:Rot%1:0" ).arg( r ).latin1(), 1 ); + ::setenv( "QWS_DISPLAY", QString( "Transformed:Rot%1:0" ).arg( r ).latin1(), 1 ); qApp->desktop()->qwsDisplay()->setTransformation( e ); #else setDefaultRotation( r ); #endif } #endif |