From eaf6da2bd05eac392c118c11fd5be1bab8586b6a Mon Sep 17 00:00:00 2001 From: zecke Date: Fri, 05 Sep 2003 21:09:43 +0000 Subject: OWidgetStack and Example showing it and QSignalMapper Added. The only problem with BigScreen Mode is window sizing and placing but this is a task of the WM we do not have... --- (limited to 'libopie/big-screen') diff --git a/libopie/big-screen/example/owidgetstack_example.cpp b/libopie/big-screen/example/owidgetstack_example.cpp new file mode 100644 index 0000000..a6b8201 --- a/dev/null +++ b/libopie/big-screen/example/owidgetstack_example.cpp @@ -0,0 +1,131 @@ +/* + * You may use, modify and distribute this example without any limitation + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../owidgetstack.h" + +#include "owidgetstack_example.h" + +#include +#include + +OPIE_EXPORT_APP( OApplicationFactory ) + +StackExample::StackExample( QWidget* parent, const char* name, WFlags fl ) + : QMainWindow( parent, name, fl ) +{ + m_stack = new OWidgetStack( this ); + setCentralWidget( m_stack ); + + /* nice Signal Mapper ;) */ + QSignalMapper *sm = new QSignalMapper(this); + connect(sm, SIGNAL(mapped(int) ), m_stack, SLOT(raiseWidget(int)) ); + + /* toolbar first but this should be known from the other examples */ + setToolBarsMovable( false ); + + /* only a menubar here */ + QToolBar* holder = new QToolBar( this ); + holder->setHorizontalStretchable( true ); + + QMenuBar *bar = new QMenuBar( holder ); + QPopupMenu *menu = new QPopupMenu( this ); + + QAction* a = new QAction( tr("Show MainWidget"), Resource::loadPixmap("zoom"), + QString::null, 0, this, 0 ); + sm->setMapping(a, 1 ); + connect(a, SIGNAL(activated() ), + sm, SLOT(map() ) ); + a->addTo( menu ); + + a = new QAction( tr("Show Details Small"), Resource::loadPixmap("zoom"), + QString::null, 0, this, 0 ); + sm->setMapping(a, 2 ); + connect(a, SIGNAL(activated() ), + sm, SLOT(map() ) ); + a->addTo( menu ); + + a = new QAction( tr("Show Details More"), Resource::loadPixmap("zoom"), + QString::null, 0, this, 0 ); + sm->setMapping(a, 3 ); + connect(a, SIGNAL(activated() ), + sm, SLOT(map() ) ); + a->addTo( menu ); + + a = new QAction( tr("Show Details All"), Resource::loadPixmap("zoom"), + QString::null, 0, this, 0 ); + sm->setMapping(a, 4 ); + connect(a, SIGNAL(activated() ), + sm, SLOT(map() ) ); + + bar->insertItem( tr("Actions"), menu ); + + /* now the gui */ + + /* first widget, main widget */ + QWidget * wid = new QWidget( m_stack ); + QGridLayout *grid = new QGridLayout(wid, 2, 2 ); + + QPushButton *btn = new QPushButton( tr("Show Details Small"), wid, "details1" ); + sm->setMapping(btn, 2 ); + connect(btn, SIGNAL(clicked()), sm, SLOT(map() ) ); + grid->addWidget( btn, 0, 0 ); + + btn = new QPushButton( tr("Show Details Medium"), wid, "details2"); + sm->setMapping(btn, 3 ); + connect(btn, SIGNAL(clicked()), sm, SLOT(map() ) ); + grid->addWidget( btn, 0, 1 ); + + btn = new QPushButton( tr("Show Details All"), wid, "details3"); + sm->setMapping(btn, 4 ); + connect(btn, SIGNAL(clicked()), sm, SLOT(map() ) ); + grid->addWidget( btn, 1, 1 ); + + m_stack->addWidget( wid, 1 ); + m_main = wid; + + QLabel *lbl = new QLabel(m_stack ); + lbl->setText(tr("Only small Details are shown here. Määh") ); + m_stack->addWidget( lbl, 2 ); + + lbl = new QLabel( m_stack ); + lbl->setText( tr("Some more details....Wo ist das Schaf?") ); + m_stack->addWidget( lbl, 3 ); + + lbl = new QLabel( m_stack ); + lbl->setText( tr("Ne nicht in Bayerisch Gmain sondern in Berlin
Vermiss und meine Augen werden nicht eckig, da mein Bildschirm abgerundet ist
Es lebe Hamburg Süd,weiss du, verstehst du? ;)
Susi ist dOOf, es lebe die Ofenecke...", "hard to translate that") ); + m_stack->addWidget( lbl, 4 ); + + + /* THE signal mapper does all the magic */ + m_stack->raiseWidget( m_main ); +} + + +StackExample::~StackExample() { + +} + + + +void StackExample::closeEvent( QCloseEvent* ev) { + /* if the close even came when we displayed a details */ + if (m_stack->visibleWidget() != m_main ) { + m_stack->raiseWidget( m_main ); + ev->ignore(); + return; + } + + ev->accept(); +} diff --git a/libopie/big-screen/example/owidgetstack_example.h b/libopie/big-screen/example/owidgetstack_example.h new file mode 100644 index 0000000..7977b48 --- a/dev/null +++ b/libopie/big-screen/example/owidgetstack_example.h @@ -0,0 +1,27 @@ +/* + * You may use, modify and distribute this example without any limitation + */ + +#ifndef O_STACK_EXAMPLE_SIMPLE_H +#define O_STACK_EXAMPLE_SIMPLE_H + +#include + + +class OWidgetStack; +class StackExample : public QMainWindow { + Q_OBJECT +public: + StackExample( QWidget* paren, const char* name, WFlags fl ); + ~StackExample(); + static QString appName() { return QString::fromLatin1("owidgetstack-example"); } + +protected: + void closeEvent( QCloseEvent* e ); +private: + OWidgetStack* m_stack; + QWidget* m_main; + +}; + +#endif diff --git a/libopie/big-screen/example/owidgetstack_example.pro b/libopie/big-screen/example/owidgetstack_example.pro new file mode 100644 index 0000000..ad1dc09 --- a/dev/null +++ b/libopie/big-screen/example/owidgetstack_example.pro @@ -0,0 +1,13 @@ +CONFIG += qt warn_on +TEMPLATE = app +TARGET = owidgetstack-example + +SOURCES = ../owidgetstack.cpp owidgetstack_example.cpp +HEADERS = ../owidgetstack.h owidgetstack_example.h + +INCLUDEPATH += $(OPIEDIR)/include +DEPENDSPATH += $(OPIEDIR)/include + +LIBS += -lqpe + +include ( $(OPIEDIR)/include.pro ) diff --git a/libopie/big-screen/owidgetstack.cpp b/libopie/big-screen/owidgetstack.cpp new file mode 100644 index 0000000..967c54b --- a/dev/null +++ b/libopie/big-screen/owidgetstack.cpp @@ -0,0 +1,404 @@ +#include +#include + +#include "owidgetstack.h" + +namespace { + const int mode_size = 330; +} + +/** + * This is the standard widget. For simple usage see the example. Normally this widget + * is the central widget of a QMainWindow. + * Use removeWidget before you delete a widget yourself. OWidgetStack does not + * yet recognize removal of children. + * + * @param parent The parent widget. It maybe 0 but then you need to take care of deletion. + * Or you use QPEApplication::showMainWidget(). + * @param name Name will be passed on to QObject + * @param fl Additional window flags passed to QFrame. see @Qt::WFlags + */ +OWidgetStack::OWidgetStack( QWidget* parent, const char* name, WFlags fl) + : QFrame( parent, name, fl ) +{ + m_last = m_mWidget = 0; + m_forced = false; + + QApplication::desktop()->installEventFilter( this ); + setFontPropagation ( AllChildren ); + setPalettePropagation( AllChildren ); + + /* sets m_mode and initializes more */ + /* if you change this call change switchTop as well */ + m_stack = 0; + switchStack(); +} + +/** + * The destructor. It deletes also all added widgets. + * + */ +OWidgetStack::~OWidgetStack() { + if (m_mode == BigScreen && !m_list.isEmpty() ) { + QMap::Iterator it = m_list.begin(); + for ( ; it != m_list.end(); ++it ) + delete it.data(); + } + m_list.clear(); + +} + +/** + * return the mode of the desktop. There are currently two modes. SmallScreen + * with a normal PDA resolution and BigScreen with resolutions greater than + * 330 for width and height. + * You can also force the mode this widget is in with forceMode() + * Note that NoForce will be never returned from here + */ +enum OWidgetStack::Mode OWidgetStack::mode()const { + return m_mode; +} + +/** + * You can also force one of the modes and then + * this widget stops on listening to size changes. You + * can revert to the scanning behaviour by setting mode + * to NoForce + */ +void OWidgetStack::forceMode( enum Mode mode) { + m_forced = mode != NoForce; + + /* we need to see which mode we're in */ + if (!m_forced ) { + if ( QApplication::desktop()->width() >= + mode_size ) + mode = BigScreen; + else + mode = SmallScreen; + } + switch( mode ) { + case NoForce: + case SmallScreen: + switchStack(); + break; + case BigScreen: + switchTop(); + break; + + } + + m_mode = mode; +} + +/** + * Adds a widget to the stack. The first widget added is considered + * to be the mainwindow. This is important because if Opie is in + * BigScreen mode the sizeHint of the MainWindow will be returned. + * In Small Screen the sizeHint of the QWidgetStack is returned. + * See QWidgetStack::sizeHint. + * This widget takes ownership of the widget and may even reparent. + * All windows will be hidden + * + * @param wid The QWidget to be added + * @param id An ID for the Widget. If the ID is duplicated the + last set widget will be related to the id + * + */ +void OWidgetStack::addWidget( QWidget* wid, int id) { + if (!wid) + return; + + /* set our main widget */ + if (!m_mWidget) + m_mWidget = wid; + + m_list.insert( id, wid ); + + /** + * adding does not raise any widget + * But for our mainwidget we prepare + * the right position with the right parent + */ + if (m_mode == SmallScreen ) + m_stack->addWidget( wid,id ); + else if ( m_mWidget == wid ) { + wid->reparent(this, 0, contentsRect().topLeft() ); + wid->hide(); + }else { + wid->reparent(0, WType_TopLevel, QPoint(10, 10) ); + wid->hide(); + } +} + + +/** + * Remove the widget from the stack it'll be reparented to 0 + * and ownership is dropped. You need to delete it. + * If the removed widget was the mainwindow consider + * to call setMainWindow. + * + * @param wid The QWidget to be removed + */ +void OWidgetStack::removeWidget( QWidget* wid) { + if (!wid) + return; + + if (m_mode == SmallScreen ) + m_stack->removeWidget( wid ); + + + wid->reparent(0, 0, QPoint(0, 0) ); + m_list.remove( id(wid) ); + + if ( wid == m_mWidget ) + m_mWidget = 0; +} + +#if 0 +/** + * @internal_resons + */ +QSizeHint OWidgetStack::sizeHint()const { + +} + +/** + * @internal_reasons + */ +QSizeHint OWidgetStack::minimumSizeHint()const { + +} +#endif + +/** + * This function tries to find the widget with the id. + * You supplied a possible id in addWIdget. Note that not + * QWidget::winId() is used. + * + * @param id The id to search for + * + * @return The widget or null + * @see addWidget + */ +QWidget* OWidgetStack::widget( int id) const { + return m_list[id]; +} + +/** + * Tries to find the assigned id for the widget + * or returns -1 if no widget could be found + * @param wid The widget to look for + */ +int OWidgetStack::id( QWidget* wid)const{ + if (m_list.isEmpty() ) + return -1; + + QMap::ConstIterator it = m_list.begin(); + for ( ; it != m_list.end(); ++it ) + if ( it.data() == wid ) + break; + + /* if not at the end return the key */ + return it == m_list.end() ? -1 : it.key(); +} + + +/** + * This function returns the currently visible + * widget. In BigScreen mode the mainwindow + * is returned + */ +QWidget* OWidgetStack::visibleWidget()const { + if (m_mode == SmallScreen ) + return m_stack->visibleWidget(); + else + return m_mWidget; + +} + +/** + * This method raises the widget wit the specefic id. + * Note that in BigScreen mode the widget is made visible + * but the other ( previous) visible widget(s) will not + * be made invisible. If you need this use hideWidget(). + * + * @param id Raise the widget with id + */ +void OWidgetStack::raiseWidget( int id) { + return raiseWidget( widget( id ) ); +} + +/** + * This is an overloaded function and only differs in its parameters. + * @see raiseWidget( int ) + */ +void OWidgetStack::raiseWidget( QWidget* wid) { + m_last = wid; + if (m_mode == SmallScreen ) + m_stack->raiseWidget( wid ); + else { + int ide; + emit aboutToShow( wid ); + /* if someone is connected and the widget is actually available */ + if ( receivers( SIGNAL(aboutToShow(int) ) ) && + ( (ide = id( wid ) ) != -1 ) ) + emit aboutToShow( ide ); + + /* ### FIXME PLACE THE WIDGET right */ + wid->show(); + } +} + +/** + * This will hide the currently visible widget + * and raise the widget specified by the parameter. + * Note that this method does not use visibleWIdget but remembers + * the last raisedWidget + */ +void OWidgetStack::hideWidget( int id) { + /* hiding our main widget wouldn't be smart */ + if ( m_mode == BigScreen && m_last != m_mWidget ) + m_last->hide(); + raiseWidget( id ); +} + +/** + * This is overloaded and only differs in the parameters + * it takes. + */ +void OWidgetStack::hideWidget( QWidget* wid) { + /* still not smart */ + if ( m_mode == BigScreen && m_last != m_mWidget ) + m_last->hide(); + + raiseWidget( wid ); +} + + +bool OWidgetStack::eventFilter( QObject* obj, QEvent* e) { + qWarning(" %s %s", obj->name(), obj->className() ); + if ( e->type() == QEvent::Resize ) { + QResizeEvent *res = static_cast( e ); + QSize size = res->size(); + if ( size.width() >= mode_size ) + switchTop(); + else + switchStack(); + } + return false; +} + + +/** + * @internal_resons + */ +void OWidgetStack::resizeEvent( QResizeEvent* ev ) { + QFrame::resizeEvent( ev ); + if (m_mode == SmallScreen ) + m_stack->setGeometry( frameRect() ); + else + if (m_mWidget ) + m_mWidget->setGeometry( frameRect() ); + +} + +/** + * setMainWindow gives the OWidgetStack a hint which + * window should always stay inside the stack. + * Normally the first added widget is considered to be + * the mainwindow but you can change this with this + * function. + * If in BigScreen mode the current mainwindow will be reparented + * and hidden. The position will be taken by the new one. + * If the old MainWindow was hidden the new window will + * also be hidden. If the window was visible the new mainwindow + * will be made visible too and the old one hidden. If there + * was no mainwindow it will be hidden as well. + * + * @param wid The new mainwindow + */ +void OWidgetStack::setMainWindow( QWidget* wid ) { + if (m_mode == BigScreen ) { + bool wasVisible = false; + if (m_mWidget ) { + wasVisible = !m_mWidget->isHidden(); + /* hidden by default */ + m_mWidget->reparent(0, WType_TopLevel, QPoint(10, 10) ); + } + wid->reparent(this, 0, frameRect().topLeft() ); + + if (wasVisible) + wid->show(); + } + + m_mWidget = wid; +} + +/** + * this is an overloaded member and only differs + * in the type of arguments. + * @see setMainWindow(QWidget*) + */ +void OWidgetStack::setMainWindow( int id) { + setMainWindow( widget( id ) ); +} + + +/* + * this function switches to a stack ;) + */ +void OWidgetStack::switchStack() { + if (m_stack ) { + m_stack->setGeometry( frameRect() ); + return; + } + + m_mode = SmallScreen; + m_stack = new QWidgetStack(this); + + connect(m_stack, SIGNAL(aboutToShow(QWidget*) ), + this, SIGNAL(aboutToShow(QWidget*) ) ); + connect(m_stack, SIGNAL(aboutToShow(int) ), + this, SIGNAL(aboutToShow(int) ) ); + + /* now reparent the widgets... luckily QWidgetSatck does most of the work */ + if (m_list.isEmpty() ) + return; + + QMap::Iterator it = m_list.begin(); + for ( ; it != m_list.end(); ++it ) + m_stack->addWidget( it.data(), it.key() ); + + +} + +/* + * we will switch to top level mode + * reparent the list of widgets and then delete the stack + */ +void OWidgetStack::switchTop() { + m_mode = BigScreen; + /* this works because it is guaranteed that switchStack was called at least once*/ + if (!m_stack && m_mWidget) { + m_mWidget->setGeometry( frameRect() ); + return; + }else if (!m_stack) + return; + + if (!m_list.isEmpty() ) { + QMap::Iterator it = m_list.begin(); + for ( ; it != m_list.end(); ++it ) { + /* better than reparenting twice */ + if ( it.data() == m_mWidget ) { + m_mWidget->reparent(this, 0, frameRect().topLeft() ); + m_mWidget->setGeometry( frameRect() ); + m_mWidget->show(); + }else + /* ### FIXME we need to place the widget better */ + it.data()->reparent(0, WType_TopLevel, QPoint(10, 10) ); + } + } + + delete m_stack; + m_stack = 0; +} diff --git a/libopie/big-screen/owidgetstack.h b/libopie/big-screen/owidgetstack.h new file mode 100644 index 0000000..5179213 --- a/dev/null +++ b/libopie/big-screen/owidgetstack.h @@ -0,0 +1,127 @@ +/* +               =. This file is part of the OPIE Project +             .=l. Copyright (c) 2003 hOlgAr +           .>+-= + _;:,     .>    :=|. This library is free software; you can +.> <`_,   >  .   <= redistribute it and/or modify it under +:`=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; either version 2 of the License, +     ._= =}       : or (at your option) any later version. +    .%`+i>       _;_. +    .i_,=:_.      -`: PARTICULAR PURPOSE. See the GNU +..}^=.=       =       ; Library General Public License for more +++=   -.     .`     .: details. + :     =  ...= . :.=- + -.   .:....=;==+<; You should have received a copy of the GNU +  -_. . .   )=.  = Library General Public License along with +    --        :-=` this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#ifndef OPIE_BIG_WIDGET_STACK_H +#define OPIE_BIG_WIDGET_STACK_H + +#include +#include + +class QWidgetStack; +/** + * + * OWidgetStack is the answer to the problem of using Opie at different screen + * sizes and to have a different behaviour. Most applications use a QWidgetStack + * to supply a view on click. And by clicking the (X) you go back but this + * behaviour feels strange on bigger screens. It's ok on smaller one because + * one can't determine the difference. + * This stack reads the default out of the size of the desktop widget but + * can be forced to have either the one or the other behaviour. + * The first widget added is considered the 'main' widget and its + * sizeHint will be taking if in BigScreen mode. + * In small screen mode this widget behaves exactly like a QWidgetStack and in BigScreen + * mode it'll use the MainWindow as child of this widget and arranges the others as + * hidden top level widgets. + * + * @version 0.1 + * @author hOlgAr F. + * @short Either a true stack or a list of top Level widgets + */ +class OWidgetStack : public QFrame { + Q_OBJECT +public: + enum Mode { SmallScreen, BigScreen, NoForce }; + OWidgetStack( QWidget* parent, const char* name = 0, WFlags fl = 0 ); + ~OWidgetStack(); + + enum Mode mode()const; + void forceMode( enum Mode ); + + void addWidget( QWidget* , int ); + void removeWidget( QWidget* ); + +// QSizeHint sizeHint()const; +// QSizeHint minimumSizeHint()const; + + QWidget *widget( int )const; + int id( QWidget* )const; + + + + QWidget* visibleWidget() const; + + bool eventFilter( QObject*, QEvent* ); +signals: + /** + * OWidgetStack monitors the Desktop Widget for + * size changes if it recignizes a change size it'll + * send a signal and adjust its mode. After the signal + * was emitted. During the signal a call to mode() the + * old mode will be returned. Note that if a size change happens + * but no modeChange no signal will be emitted + * + * + * @param mode The new mode of the desktop + */ + void modeChanged( enum Mode mode); + + /** + * These two signals are emitted whenever we're about to + * show one of the widgets + */ + void aboutToShow( QWidget* ); + void aboutToShow( int ); + +public slots: + void raiseWidget( int ); + void raiseWidget( QWidget* ); + void hideWidget( int ); + void hideWidget( QWidget* ); + void setMainWindow( QWidget* ); + void setMainWindow( int ); + +protected: + void resizeEvent( QResizeEvent* ); + +private: + void switchStack(); + void switchTop(); + QMap m_list; + QWidgetStack *m_stack; + QWidget *m_mWidget; + QWidget *m_last; + + enum Mode m_mode; + bool m_forced : 1; + + struct Private; + Private *d; +}; + + +#endif -- cgit v0.9.0.2