author | llornkcor <llornkcor> | 2004-04-25 07:56:02 (UTC) |
---|---|---|
committer | llornkcor <llornkcor> | 2004-04-25 07:56:02 (UTC) |
commit | 73f0c227fc94bc4dea12e4eb2384bdff2e9561eb (patch) (side-by-side diff) | |
tree | c33525271239fbf69e5daf9223beaa5dd28e0bb6 /library/qpeapplication.cpp | |
parent | cf9cab31dc8a46d3a2d74931b2a428ca87eed0a9 (diff) | |
download | opie-73f0c227fc94bc4dea12e4eb2384bdff2e9561eb.zip opie-73f0c227fc94bc4dea12e4eb2384bdff2e9561eb.tar.gz opie-73f0c227fc94bc4dea12e4eb2384bdff2e9561eb.tar.bz2 |
fix nonmaximized apps, and make the state and position persistent. ported from Qtopia 1.7 :)
-rw-r--r-- | library/qpeapplication.cpp | 259 |
1 files changed, 234 insertions, 25 deletions
diff --git a/library/qpeapplication.cpp b/library/qpeapplication.cpp index 755fb19..90cd5f1 100644 --- a/library/qpeapplication.cpp +++ b/library/qpeapplication.cpp @@ -87,24 +87,33 @@ #include "qpemenubar.h" #include "textcodecinterface.h" #include "imagecodecinterface.h" #include <unistd.h> #include <sys/file.h> #include <sys/ioctl.h> #ifndef QT_NO_SOUND #include <sys/soundcard.h> #endif #include "qt_override_p.h" +class HackWidget : public QWidget +{ +public: + bool needsOk() + { return (getWState() & WState_Reserved1 ); } + + QRect normalGeometry() + { return topData()->normalGeometry; }; +}; class QPEApplicationData { public: QPEApplicationData ( ) : presstimer( 0 ), presswidget( 0 ), rightpressed( false ), kbgrabbed( false ), notbusysent( false ), preloaded( false ), forceshow( false ), nomaximize( false ), keep_running( true ), qcopQok( false ), qpe_main_widget( 0 ) {} int presstimer; @@ -154,50 +163,246 @@ public: while((r=qcopq.dequeue())) { // remove from queue before sending... // event loop can come around again before getting // back from sendLocally #ifndef QT_NO_COP QCopChannel::sendLocally( r->channel, r->message, r->data ); #endif delete r; } } - static void show_mx(QWidget* mw, bool nomaximize, const QString & = QString::null ) - { - // 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 -#if defined(OPIE_HIGH_RES_SMALL_PHY) - if ( QPEApplication::desktop() ->width() >= 600 && ( mw->inherits("QMainWindow") || mw->isA("QMainWindow") ) ) { - ( ( QMainWindow* ) mw )->setUsesBigPixmaps( true ); - } -#endif + static void show_mx(QWidget* mw, bool nomaximize, QString &strName/* = QString::null */) + { + if ( mw->isVisible() ) { + mw->raise(); + } else { + QPoint p; + QSize s; if ( mw->layout() && mw->inherits("QDialog") ) { - QPEApplication::showDialog((QDialog*)mw, nomaximize); - } - else { + bool max; + if ( read_widget_rect(strName, max, p, s) && validate_widget_size(mw, p, s) ) { + mw->resize(s); + mw->move(p); + + if ( max && !nomaximize ) + mw->showMaximized(); + else + mw->show(); + } else { + qpe_show_dialog((QDialog*)mw,nomaximize); + } + } else { + bool max; + if ( read_widget_rect(strName, max, p, s) && validate_widget_size(mw, p, s) ) { + mw->resize(s); + mw->move(p); + } else { //no stored rectangle, make an estimation + int x = (qApp->desktop()->width()-mw->frameGeometry().width())/2; + int y = (qApp->desktop()->height()-mw->frameGeometry().height())/2; + mw->move( QMAX(x,0), QMAX(y,0) ); #ifdef Q_WS_QWS if ( !nomaximize ) mw->showMaximized(); +#endif + } + if ( max && !nomaximize ) + mw->showMaximized(); else + mw->show(); + } + } + } +// // 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 +// #if defined(OPIE_HIGH_RES_SMALL_PHY) +// 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); +// } +// else { +// #ifdef Q_WS_QWS +// if ( !nomaximize ) { +// qDebug("QDialog special case XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); +// mw->showMaximized(); +// // QPEApplication::showWidget( mw, !nomaximize ); +// } else +// #endif +// mw->show(); +// } +// } + + +static void qpe_show_dialog( QDialog* d, bool nomax ) +{ + QSize sh = d->sizeHint(); + int w = QMAX(sh.width(),d->width()); + int h = QMAX(sh.height(),d->height()); + + if ( d->parentWidget() && !d->parentWidget()->topLevelWidget()->isMaximized() ) + nomax = TRUE; + +#ifndef Q_WS_QWS + QSize s(qApp->desktop()->width(), qApp->desktop()->height() ); +#else + QSize s(qt_maxWindowRect.width(), qt_maxWindowRect.height() ); #endif - mw->show(); + int maxX = s.width() - (d->frameGeometry().width() - d->geometry().width()); + int maxY = s.height() - (d->frameGeometry().height() - d->geometry().height()); + + if ( (w >= maxX && h >= maxY) || ( (!nomax) && ( w > s.width()*3/4 || h > s.height()*3/4 ) ) ) { + d->showMaximized(); + } else { + // try centering the dialog around its parent + QPoint p(0,0); + if ( d->parentWidget() ) { + QPoint pp = d->parentWidget()->mapToGlobal( QPoint(0,0) ); + p = QPoint( pp.x() + d->parentWidget()->width()/2, + pp.y() + d->parentWidget()->height()/ 2 ); + } else { + p = QPoint( maxX/2, maxY/2 ); } + + p = QPoint( p.x() - w/2, p.y() - h/2 ); +// qDebug("p(x,y) is %d %d", p.x(), p.y() ); + + if ( w >= maxX ) { + if ( p.y() < 0 ) + p.setY(0); + if ( p.y() + h > maxY ) + p.setY( maxY - h); + + d->resize(maxX, h); + d->move(0, p.y() ); + } else if ( h >= maxY ) { + if ( p.x() < 0 ) + p.setX(0); + if ( p.x() + w > maxX ) + p.setX( maxX - w); + + d->resize(w, maxY); + d->move(p.x(),0); + } else { + d->resize(w, h); + } + + d->show(); } +} + + static bool read_widget_rect(const QString &app, bool &maximized, QPoint &p, QSize &s) + { + maximized = TRUE; + + // 350 is the trigger in qwsdefaultdecoration for providing a resize button + if ( qApp->desktop()->width() <= 350 ) + return FALSE; + + Config cfg( "qpe" ); + cfg.setGroup("ApplicationPositions"); + QString str = cfg.readEntry( app, QString::null ); + QStringList l = QStringList::split(",", str); + + if ( l.count() == 5) { + p.setX( l[0].toInt() ); + p.setY( l[1].toInt() ); + + s.setWidth( l[2].toInt() ); + s.setHeight( l[3].toInt() ); + + maximized = l[4].toInt(); + + return TRUE; + } + + return FALSE; + } + + + static bool validate_widget_size(const QWidget *w, QPoint &p, QSize &s) + { +#ifndef Q_WS_QWS + QRect qt_maxWindowRect = qApp->desktop()->geometry(); +#endif + int maxX = qt_maxWindowRect.width(); + int maxY = qt_maxWindowRect.height(); + int wWidth = s.width() + ( w->frameGeometry().width() - w->geometry().width() ); + int wHeight = s.height() + ( w->frameGeometry().height() - w->geometry().height() ); + + // total window size is not allowed to be larger than desktop window size + if ( ( wWidth >= maxX ) && ( wHeight >= maxY ) ) + return FALSE; + + if ( wWidth > maxX ) { + s.setWidth( maxX - (w->frameGeometry().width() - w->geometry().width() ) ); + wWidth = maxX; + } + + if ( wHeight > maxY ) { + s.setHeight( maxY - (w->frameGeometry().height() - w->geometry().height() ) ); + wHeight = maxY; + } + + // any smaller than this and the maximize/close/help buttons will be overlapping + if ( wWidth < 80 || wHeight < 60 ) + return FALSE; + + if ( p.x() < 0 ) + p.setX(0); + if ( p.y() < 0 ) + p.setY(0); + + if ( p.x() + wWidth > maxX ) + p.setX( maxX - wWidth ); + if ( p.y() + wHeight > maxY ) + p.setY( maxY - wHeight ); + + return TRUE; + } + + static void store_widget_rect(QWidget *w, QString &app) + { + // 350 is the trigger in qwsdefaultdecoration for providing a resize button + if ( qApp->desktop()->width() <= 350 ) + return; + + // we use these to map the offset of geometry and pos. ( we can only use normalGeometry to + // get the non-maximized version, so we have to do it the hard way ) + int offsetX = w->x() - w->geometry().left(); + int offsetY = w->y() - w->geometry().top(); + + QRect r; + if ( w->isMaximized() ) + r = ( (HackWidget *) w)->normalGeometry(); + else + r = w->geometry(); + + // Stores the window placement as pos(), size() (due to the offset mapping) + Config cfg( "qpe" ); + cfg.setGroup("ApplicationPositions"); + QString s; + s.sprintf("%d,%d,%d,%d,%d", r.left() + offsetX, r.top() + offsetY, r.width(), r.height(), w->isMaximized() ); + cfg.writeEntry( app, s ); + } + static bool setWidgetCaptionFromAppName( QWidget* /*mw*/, const QString& /*appName*/, const QString& /*appsPath*/ ) { /* // This works but disable it for now until it is safe to apply // What is does is scan the .desktop files of all the apps for // the applnk that has the corresponding argv[0] as this program // then it uses the name stored in the .desktop file as the caption // for the main widget. This saves duplicating translations for // the app name in the program and in the .desktop files. AppLnkSet apps( appsPath ); @@ -217,28 +422,28 @@ public: { setWidgetCaptionFromAppName( mw, appName, QPEApplication::qpeDir() + "apps" ); nomaximize = nomax; qpe_main_widget = mw; qcopQok = TRUE; #ifndef QT_NO_COP sendQCopQ(); #endif if ( preloaded ) { if (forceshow) - show_mx(mw, nomax); + show_mx(mw, nomax, appName); } else if ( keep_running ) { - show_mx(mw, nomax); + show_mx(mw, nomax, appName); } } void loadTextCodecs() { QString path = QPEApplication::qpeDir() + "/plugins/textcodecs"; #ifdef Q_OS_MACX QDir dir( path, "lib*.dylib" ); #else QDir dir( path, "lib*.so" ); #endif QStringList list; @@ -854,32 +1059,32 @@ void QPEApplication::mapToDefaultAction( QWSKeyEvent * ke, int key ) && activePopupWidget() ->parentWidget() ->inherits( "QComboBox" ) ) key = Qt::Key_Return; if ( activePopupWidget() && activePopupWidget() ->inherits( "QPopupMenu" ) ) key = Qt::Key_Return; #ifdef QWS ke->simpleData.keycode = key; #endif } -class HackWidget : public QWidget -{ -public: - bool needsOk() - { - return ( getWState() & WState_Reserved1 ); - } -}; +// class HackWidget : public QWidget +// { +// public: +// bool needsOk() +// { +// return ( getWState() & WState_Reserved1 ); +// } +// }; /*! \internal */ #ifdef QWS bool QPEApplication::qwsEventFilter( QWSEvent * e ) { if ( !d->notbusysent && e->type == QWSEvent::Focus ) { if ( qApp->type() != QApplication::GuiServer ) { QCopEnvelope e( "QPE/System", "notBusy(QString)" ); e << d->appName; @@ -1969,24 +2174,26 @@ int QPEApplication::exec() */ void QPEApplication::tryQuit() { if ( activeModalWidget() || strcmp( argv() [ 0 ], "embeddedkonsole" ) == 0 ) return ; // Inside modal loop or konsole. Too hard to save state. #ifndef QT_NO_COP { QCopEnvelope e( "QPE/System", "closing(QString)" ); e << d->appName; } #endif + if ( d->keep_running ) + d->store_widget_rect(d->qpe_main_widget, d->appName); processEvents(); quit(); } /*! \internal */ void QPEApplication::installTranslation( const QString& baseName ) { QTranslator* trans = new QTranslator(this); QString tfn = qpeDir() + "/i18n/"+baseName; if ( trans->load( tfn ) ) @@ -1994,24 +2201,26 @@ void QPEApplication::installTranslation( const QString& baseName ) { else delete trans; } /*! \internal User initiated quit. Makes the window 'Go Away'. If preloaded this means hiding the window. If not it means quitting the application. As this is user initiated we don't need to check state. */ void QPEApplication::hideOrQuit() { + if ( d->keep_running ) + d->store_widget_rect(d->qpe_main_widget, d->appName); processEvents(); // If we are a preloaded application we don't actually quit, so emit // a System message indicating we're quasi-closing. if ( d->preloaded && d->qpe_main_widget ) #ifndef QT_NO_COP { QCopEnvelope e("QPE/System", "fastAppHiding(QString)" ); e << d->appName; d->qpe_main_widget->hide(); } |