summaryrefslogtreecommitdiff
path: root/library
Side-by-side diff
Diffstat (limited to 'library') (more/less context) (ignore whitespace changes)
-rw-r--r--library/qpeapplication.cpp271
1 files changed, 240 insertions, 31 deletions
diff --git a/library/qpeapplication.cpp b/library/qpeapplication.cpp
index 755fb19..90cd5f1 100644
--- a/library/qpeapplication.cpp
+++ b/library/qpeapplication.cpp
@@ -87,50 +87,59 @@
#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;
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;
- bool qcopQok : 1;
+ bool qcopQok : 1;
- QStringList langs;
+ 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;
};
@@ -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 )
+
+ 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") ) {
+ 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());
- // 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 );
- }
+ 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
- if ( mw->layout() && mw->inherits("QDialog") ) {
- QPEApplication::showDialog((QDialog*)mw, nomaximize);
- }
- else {
-#ifdef Q_WS_QWS
- if ( !nomaximize )
- mw->showMaximized();
- else
+ 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() );
- mw->show();
- }
+ // 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();
}