-rw-r--r-- | libopie2/opieui/big-screen/.cvsignore | 8 | ||||
-rw-r--r-- | libopie2/opieui/big-screen/IDEAS | 81 | ||||
-rw-r--r-- | libopie2/opieui/big-screen/big-screen.pro | 2 | ||||
-rw-r--r-- | libopie2/opieui/big-screen/obarcollection.h | 116 | ||||
-rw-r--r-- | libopie2/opieui/big-screen/obigscreen_p.h | 28 | ||||
-rw-r--r-- | libopie2/opieui/big-screen/omodalhelper.cpp | 179 | ||||
-rw-r--r-- | libopie2/opieui/big-screen/omodalhelper.h | 774 | ||||
-rw-r--r-- | libopie2/opieui/big-screen/osplitter.cpp | 638 | ||||
-rw-r--r-- | libopie2/opieui/big-screen/osplitter.h | 150 | ||||
-rw-r--r-- | libopie2/opieui/big-screen/owidgetstack.cpp | 435 | ||||
-rw-r--r-- | libopie2/opieui/big-screen/owidgetstack.h | 132 | ||||
-rw-r--r-- | libopie2/opieui/opieui.pro | 2 |
12 files changed, 2545 insertions, 0 deletions
diff --git a/libopie2/opieui/big-screen/.cvsignore b/libopie2/opieui/big-screen/.cvsignore new file mode 100644 index 0000000..1244207 --- a/dev/null +++ b/libopie2/opieui/big-screen/.cvsignore | |||
@@ -0,0 +1,8 @@ | |||
1 | Makefile* | ||
2 | obj | ||
3 | moc* | ||
4 | *moc | ||
5 | *.o | ||
6 | ~* | ||
7 | *base.cpp | ||
8 | *base.h | ||
diff --git a/libopie2/opieui/big-screen/IDEAS b/libopie2/opieui/big-screen/IDEAS new file mode 100644 index 0000000..27a4d6e --- a/dev/null +++ b/libopie2/opieui/big-screen/IDEAS | |||
@@ -0,0 +1,81 @@ | |||
1 | Now that PDAs get a VGA resolution and Opie runs on Webpads | ||
2 | and could be used as a Kiosk secure environment the design | ||
3 | decision that were right for a 320x240/240x320 doesn't necessary | ||
4 | to be right for bigger screens. | ||
5 | |||
6 | Remember most desktops a few years ago had only a resolution | ||
7 | of 800x600. | ||
8 | Then also to remember is that a webpad with 640x480 is different to | ||
9 | a PDA with the same resolution. The PDA has a much smaller | ||
10 | physical display. | ||
11 | |||
12 | With higher resolution the feeling of a desktop comes. | ||
13 | |||
14 | Problems with current Opie: | ||
15 | -InputMethod use full width but most of the times are not high enough | ||
16 | This actually makes it harder to input and looks stupid. | ||
17 | -ToolBars only feels strange on bigger screens. Maybe do it like WinCE3 does | ||
18 | share the ToolBar with MenuBar if they're too big for the screen allow handles | ||
19 | to either show the left or right side. Note that the handle from Qt looks | ||
20 | bad and should be patched away | ||
21 | -The Escape/Close back to View does not make sense on bigger screens and desktop | ||
22 | on a desktop you might even want to show multiple views and detach from the 'system' | ||
23 | view | ||
24 | -Modality. Dunnow how you get back to the enter dialog without modality in Qt/E fix it? | ||
25 | On bigger screen this is not the problem you can move windows. But you should try | ||
26 | to be less modal in the future. | ||
27 | I've added a small to qpeapplication to iterate over the toplevel widgets 99% | ||
28 | ( click on the taskbar to iterate over the widgets first time nothing is changed ) | ||
29 | , BUT it should be avoided to use modality showMaximized(), exec() | ||
30 | INSTEAD we will use a modal helper where one can register to show a dialog for uid | ||
31 | type and will get a signal once the settings need to be applied, rejected or discarded. | ||
32 | This way you can almost work like with exec(), do not need to care for freeing. | ||
33 | Problems sometimes to have more than one dialog in memory is expensive. Allow queueing | ||
34 | and reusing this widget ( only set the Record new? ) | ||
35 | -Viewing on bigger screens you may want to have a seperate viewer widget ( topLevel ) which | ||
36 | might also get spon off from the normal operation. The (X) close go back does not make | ||
37 | sense on bigger screens and feels strange | ||
38 | -Sizing and Auto sizing of widgets | ||
39 | |||
40 | Widgets and Classes | ||
41 | |||
42 | Toolbar/Action and Popups: | ||
43 | While KParts with XMLGUI provide a fantastic technology to change the GUI | ||
44 | on the fly. Parsing these GUI descriptions is not an option for PDAs | ||
45 | specially not on start up. | ||
46 | Instead we will need to use normal object in this case QAction and QPopupMenuss. We | ||
47 | will then group these Actions into groups. Each group can have children and one | ||
48 | parent. Each group has two attributes one for the menubar and one for the toolbar. | ||
49 | Attributes for each might be | together. Always, Never, Auto are the attributes I | ||
50 | can think of tonite. Always will place this group always there, Never yeah never, | ||
51 | Automatic lets the later described Manager decide. Also one could or MightSpinOff | ||
52 | to a group. This way a child group might get spon off if enough place is there. | ||
53 | You cann add QAction and QPopupMenus to the group the Group will not take owner ship | ||
54 | and you might use your QAction in other places as well. | ||
55 | Toplevel groups need to be registered to the manager and this manager will depending | ||
56 | on global settings place and control MenuBar and ToolBar/ToolBar. | ||
57 | This allows to dynamically create toolbar on the fly | ||
58 | |||
59 | Modality class: | ||
60 | It'll be a template with a QSignal to tell about changes and a method to get to know | ||
61 | which action to be applied. It has three template parameters one for the WIdget used | ||
62 | and one for the type of uid and the last for the editor widget which | ||
63 | at least needs to provide some methods as well. | ||
64 | If you need to edit an widget you simply tell the helper about it. If present it'll | ||
65 | raise the widget or either queue it or create a new editor depending on a policy | ||
66 | one can set manually or get from the system. | ||
67 | |||
68 | Viewing: | ||
69 | We will provide a special OWidgetStack which either is a real QWidgetStack or a QList | ||
70 | of toplevel widgets to be raised. One has to see how one can use it with todolist | ||
71 | and datebook. specially the switching back and forth need to be handled but with possible | ||
72 | no code reordering ( least intrusive ) | ||
73 | Viewing II: | ||
74 | Example Advanced FM has a tabwidget but on a SIMpad it would make perfect sense to use a | ||
75 | QSplitter or QVBox. We will provide an OSplitter which either provides the one | ||
76 | or the other widget depending on the size | ||
77 | |||
78 | |||
79 | These small changes ( replacing Q with O + bit more) should make Opie a better environment for | ||
80 | bigger screens. The additional library memory is a fair trade off and memory can be recovered | ||
81 | by other technics \ No newline at end of file | ||
diff --git a/libopie2/opieui/big-screen/big-screen.pro b/libopie2/opieui/big-screen/big-screen.pro new file mode 100644 index 0000000..f324d3c --- a/dev/null +++ b/libopie2/opieui/big-screen/big-screen.pro | |||
@@ -0,0 +1,2 @@ | |||
1 | HEADERS += big-screen/obigscreen_p.h big-screen/osplitter.h big-screen/owidgetstack.h #big-screen/omodalhelper.h | ||
2 | SOURCES += big-screen/osplitter.cpp big-screen/owidgetstack.cpp #big-screen/omodalhelper.cpp | ||
diff --git a/libopie2/opieui/big-screen/obarcollection.h b/libopie2/opieui/big-screen/obarcollection.h new file mode 100644 index 0000000..e3a2935 --- a/dev/null +++ b/libopie2/opieui/big-screen/obarcollection.h | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | =. This file is part of the OPIE Project | ||
3 | .=l. Copyright (c) 2003 hOlgAr <zecke@handhelds.org> | ||
4 | .>+-= | ||
5 | _;:, .> :=|. This library is free software; you can | ||
6 | .> <`_, > . <= redistribute it and/or modify it under | ||
7 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public | ||
8 | .="- .-=="i, .._ License as published by the Free Software | ||
9 | - . .-<_> .<> Foundation; either version 2 of the License, | ||
10 | ._= =} : or (at your option) any later version. | ||
11 | .%`+i> _;_. | ||
12 | .i_,=:_. -<s. This library is distributed in the hope that | ||
13 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; | ||
14 | : .. .:, . . . without even the implied warranty of | ||
15 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A | ||
16 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU | ||
17 | ..}^=.= = ; Library General Public License for more | ||
18 | ++= -. .` .: details. | ||
19 | : = ...= . :.=- | ||
20 | -. .:....=;==+<; You should have received a copy of the GNU | ||
21 | -_. . . )=. = Library General Public License along with | ||
22 | -- :-=` this library; see the file COPYING.LIB. | ||
23 | If not, write to the Free Software Foundation, | ||
24 | Inc., 59 Temple Place - Suite 330, | ||
25 | Boston, MA 02111-1307, USA. | ||
26 | |||
27 | */ | ||
28 | |||
29 | #ifndef OBARCOLLECTION_H | ||
30 | #define OBARCOLLECTION_H | ||
31 | |||
32 | /* QT */ | ||
33 | |||
34 | #include <qstring.h> | ||
35 | #include <qwidget.h> | ||
36 | |||
37 | class QAction; | ||
38 | class QPopupMenu; | ||
39 | |||
40 | namespace Opie | ||
41 | { | ||
42 | |||
43 | /* | ||
44 | * ### TODO | ||
45 | * -Consider Life Updates | ||
46 | * -Make ValueBased like Opie-featurelist | ||
47 | */ | ||
48 | |||
49 | /** | ||
50 | * The different screen sizes have different look and feel. On bigger | ||
51 | * screens only a QToolBar feels strange. One is at least known to have | ||
52 | * a Help-Menu, a File Menu with Quit/Exit but instead of providing two | ||
53 | * different ways / two action sets we will group actions to gether and give | ||
54 | * them attributes when and where we might want them to be visible. | ||
55 | * We can also group actions. For example you could Group All Actions | ||
56 | * into the File Group. This means with many actions you would only have more toolbar | ||
57 | * actions but many sub menus in File. On bigger screen this would automatically | ||
58 | * expand to a full blown MenuBar and ToolButtons. | ||
59 | * | ||
60 | * @short Grouping of actions for dynamic Bar Generation | ||
61 | * @version 0.01 | ||
62 | * @author hOlgAr | ||
63 | */ | ||
64 | class OBarGroup | ||
65 | { | ||
66 | public: | ||
67 | enum Preference { Allways, Never, IfPlace }; | ||
68 | OBarGroup( const QString& name, enum Preference groupPreference ); | ||
69 | ~OBarGroup(); | ||
70 | |||
71 | void add( QAction* action, enum Preference menuPreference, | ||
72 | enum Preference toolpreference ); | ||
73 | void add( const QString&, QPopupMenu* ); | ||
74 | |||
75 | void add( OBarGroup* ); | ||
76 | |||
77 | void remove( QAction* action ); | ||
78 | void remove( QMap* ); | ||
79 | |||
80 | protected: | ||
81 | OBarGroup* parent()const; | ||
82 | |||
83 | private: | ||
84 | }; | ||
85 | |||
86 | |||
87 | /** | ||
88 | * Add your groups in order to the bar manager | ||
89 | * and either call createGUI() on it, or tell it | ||
90 | * it the mainwindow and it is listening to the show event | ||
91 | * and then creates the toolbar | ||
92 | */ | ||
93 | class OBarManager : public QObject | ||
94 | { | ||
95 | public: | ||
96 | OBarManager( QWindow* parent ); | ||
97 | ~OBarManager(); | ||
98 | |||
99 | void add( OBarGroup*, int pos = -1 ); | ||
100 | void remove( OBarGroup* ); | ||
101 | |||
102 | bool eventFilter( QObject* , QEvent* ); | ||
103 | |||
104 | public slots: | ||
105 | void createGUI(); | ||
106 | }; | ||
107 | |||
108 | /* | ||
109 | * ### TODO GUI merging | ||
110 | */ | ||
111 | |||
112 | }; | ||
113 | |||
114 | #endif | ||
115 | |||
116 | |||
diff --git a/libopie2/opieui/big-screen/obigscreen_p.h b/libopie2/opieui/big-screen/obigscreen_p.h new file mode 100644 index 0000000..db8fc83 --- a/dev/null +++ b/libopie2/opieui/big-screen/obigscreen_p.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef OPIE_BIG_SCREEN_PRIVATE | ||
2 | #define OPIE_BIG_SCREEN_PRIVATE | ||
3 | |||
4 | /* QT */ | ||
5 | #include <qstring.h> | ||
6 | |||
7 | class QWidget; | ||
8 | |||
9 | namespace Opie | ||
10 | { | ||
11 | |||
12 | struct OSplitterContainer | ||
13 | { | ||
14 | bool operator==( const OSplitterContainer& o) const | ||
15 | { | ||
16 | if (widget != o.widget ) return false; | ||
17 | if (icon != o.icon ) return false; | ||
18 | if (name != o.name ) return false; | ||
19 | return true; | ||
20 | } | ||
21 | QWidget* widget; | ||
22 | QString icon; | ||
23 | QString name; | ||
24 | }; | ||
25 | |||
26 | }; | ||
27 | |||
28 | #endif | ||
diff --git a/libopie2/opieui/big-screen/omodalhelper.cpp b/libopie2/opieui/big-screen/omodalhelper.cpp new file mode 100644 index 0000000..19aa64f --- a/dev/null +++ b/libopie2/opieui/big-screen/omodalhelper.cpp | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | =. This file is part of the OPIE Project | ||
3 | .=l. Copyright (c) 2003 hOlgAr <zecke@handhelds.org> | ||
4 | .>+-= | ||
5 | _;:, .> :=|. This library is free software; you can | ||
6 | .> <`_, > . <= redistribute it and/or modify it under | ||
7 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public | ||
8 | .="- .-=="i, .._ License as published by the Free Software | ||
9 | - . .-<_> .<> Foundation; either version 2 of the License, | ||
10 | ._= =} : or (at your option) any later version. | ||
11 | .%`+i> _;_. | ||
12 | .i_,=:_. -<s. This library is distributed in the hope that | ||
13 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; | ||
14 | : .. .:, . . . without even the implied warranty of | ||
15 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A | ||
16 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU | ||
17 | ..}^=.= = ; Library General Public License for more | ||
18 | ++= -. .` .: details. | ||
19 | : = ...= . :.=- | ||
20 | -. .:....=;==+<; You should have received a copy of the GNU | ||
21 | -_. . . )=. = Library General Public License along with | ||
22 | -- :-=` this library; see the file COPYING.LIB. | ||
23 | If not, write to the Free Software Foundation, | ||
24 | Inc., 59 Temple Place - Suite 330, | ||
25 | Boston, MA 02111-1307, USA. | ||
26 | |||
27 | */ | ||
28 | |||
29 | #include "omodalhelper.h" | ||
30 | |||
31 | /* QT */ | ||
32 | #include <qpushbutton.h> | ||
33 | #include <qvbox.h> | ||
34 | #include <qlayout.h> | ||
35 | #include <qlabel.h> | ||
36 | |||
37 | /* Signal handling */ | ||
38 | OModalHelperSignal::OModalHelperSignal( OModalHelperBase* base, QObject* parent ) | ||
39 | : QObject( parent, "OModal Helper Signal" ), m_base( base ) | ||
40 | {} | ||
41 | |||
42 | OModalHelperSignal::~OModalHelperSignal() | ||
43 | { | ||
44 | /* special the ancestor deletes its creator */ | ||
45 | delete m_base; | ||
46 | } | ||
47 | |||
48 | |||
49 | /* Helper Controler */ | ||
50 | /* | ||
51 | * the dialogs signal will be slotted here | ||
52 | * and we will call into m_base | ||
53 | */ | ||
54 | OModalHelperControler::OModalHelperControler( OModalHelperBase* base, QObject* parent ) | ||
55 | : QObject(parent, "OModal Helper Controler" ), m_base( base ), m_dia( 0 ), m_id( -1 ) | ||
56 | {} | ||
57 | |||
58 | TransactionID OModalHelperControler::transactionID()const | ||
59 | { | ||
60 | return m_id; | ||
61 | } | ||
62 | |||
63 | void OModalHelperControler::setTransactionID( TransactionID id ) | ||
64 | { | ||
65 | m_dia = 0; | ||
66 | m_id = id; | ||
67 | } | ||
68 | |||
69 | QDialog* OModalHelperControler::dialog()const | ||
70 | { | ||
71 | return m_dia; | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * If we're in the New mode we will map the QDialog | ||
76 | * to the TransactionID | ||
77 | */ | ||
78 | void OModalHelperControler::done( int result ) | ||
79 | { | ||
80 | if ( sender() && !sender()->isA("OModalQueuedDialog") ) | ||
81 | m_dia = static_cast<QDialog*>( sender() ); | ||
82 | |||
83 | m_base->done( result, m_id ); | ||
84 | } | ||
85 | |||
86 | void OModalHelperControler::next() | ||
87 | { | ||
88 | m_base->next( m_id ); | ||
89 | } | ||
90 | |||
91 | void OModalHelperControler::prev() | ||
92 | { | ||
93 | m_base->prev( m_id ); | ||
94 | } | ||
95 | |||
96 | /* The Queued Dialog inclusive QueuedBar */ | ||
97 | struct OModalQueueBar : public QHBox | ||
98 | { | ||
99 | QPushButton* next; | ||
100 | QPushButton* prev; | ||
101 | QLabel * label; | ||
102 | |||
103 | OModalQueueBar( QWidget* parent ); | ||
104 | void setText( const QString& str ); | ||
105 | }; | ||
106 | |||
107 | OModalQueueBar::OModalQueueBar( QWidget* parent ) | ||
108 | : QWidget( parent, "OModal Queue Bar" ) | ||
109 | { | ||
110 | prev = new QPushButton( this ); | ||
111 | prev->setText( OModalQueuedDialog::tr("Prev") ); | ||
112 | |||
113 | label = new QLabel(this); | ||
114 | |||
115 | next = new QPushButton( this ); | ||
116 | next->setText( OModalQueuedDialog::tr("Next") ); | ||
117 | } | ||
118 | |||
119 | void OModalQueueBar::setText( const QString& str ) | ||
120 | { | ||
121 | label->setText( str ); | ||
122 | } | ||
123 | |||
124 | |||
125 | OModalQueuedDialog::OModalQueuedDialog( QDialog* mainWidget ) | ||
126 | : QDialog(0, "OModal Queued Dialog" ) | ||
127 | { | ||
128 | QVBoxLayout *lay = new QVBoxLayout( this ); | ||
129 | |||
130 | m_bar = new OModalQueueBar( this ); | ||
131 | lay->addWidget( m_bar ); | ||
132 | |||
133 | m_center = mainWidget; | ||
134 | m_center->reparent(this, 0, QPoint(0, 0) ); | ||
135 | lay->addWidget( m_center ); | ||
136 | |||
137 | |||
138 | connect(m_bar->next, SIGNAL(clicked() ), this, | ||
139 | SIGNAL(next() ) ); | ||
140 | connect(m_bar->prev, SIGNAL(clicked() ), this, | ||
141 | SIGNAL(prev() ) ); | ||
142 | |||
143 | } | ||
144 | |||
145 | OModalQueuedDialog::~OModalQueuedDialog() | ||
146 | {} | ||
147 | |||
148 | QDialog* OModalQueuedDialog::centerDialog()const | ||
149 | { | ||
150 | return m_center; | ||
151 | } | ||
152 | |||
153 | void OModalQueuedDialog::setQueueBarEnabled( bool b) | ||
154 | { | ||
155 | /* in Qt3 use setEnabled( bool ) */ | ||
156 | if (b) | ||
157 | m_bar->show(); | ||
158 | else | ||
159 | m_bar->hide(); | ||
160 | } | ||
161 | |||
162 | void OModalQueuedDialog::setRecord( int record, int count ) | ||
163 | { | ||
164 | if (!record && !count ) | ||
165 | { | ||
166 | hide(); | ||
167 | return; | ||
168 | } | ||
169 | else | ||
170 | show(); | ||
171 | |||
172 | if ( count > 1 ) | ||
173 | m_bar->show(); | ||
174 | else | ||
175 | m_bar->hide(); | ||
176 | |||
177 | m_bar->setText( tr("Editing record %1 out of %2", | ||
178 | "Shows the current edited record out of an array of records").arg( record ). arg( count ) ); | ||
179 | } | ||
diff --git a/libopie2/opieui/big-screen/omodalhelper.h b/libopie2/opieui/big-screen/omodalhelper.h new file mode 100644 index 0000000..096cec4 --- a/dev/null +++ b/libopie2/opieui/big-screen/omodalhelper.h | |||
@@ -0,0 +1,774 @@ | |||
1 | /* | ||
2 | =. This file is part of the OPIE Project | ||
3 | .=l. Copyright (c) 2003 hOlgAr <zecke@handhelds.org> | ||
4 | .>+-= | ||
5 | _;:, .> :=|. This library is free software; you can | ||
6 | .> <`_, > . <= redistribute it and/or modify it under | ||
7 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public | ||
8 | .="- .-=="i, .._ License as published by the Free Software | ||
9 | - . .-<_> .<> Foundation; either version 2 of the License, | ||
10 | ._= =} : or (at your option) any later version. | ||
11 | .%`+i> _;_. | ||
12 | .i_,=:_. -<s. This library is distributed in the hope that | ||
13 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; | ||
14 | : .. .:, . . . without even the implied warranty of | ||
15 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A | ||
16 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU | ||
17 | ..}^=.= = ; Library General Public License for more | ||
18 | ++= -. .` .: details. | ||
19 | : = ...= . :.=- | ||
20 | -. .:....=;==+<; You should have received a copy of the GNU | ||
21 | -_. . . )=. = Library General Public License along with | ||
22 | -- :-=` this library; see the file COPYING.LIB. | ||
23 | If not, write to the Free Software Foundation, | ||
24 | Inc., 59 Temple Place - Suite 330, | ||
25 | Boston, MA 02111-1307, USA. | ||
26 | |||
27 | */ | ||
28 | |||
29 | #ifndef OMODALHELPER_H | ||
30 | #define OMODALHELPER_H | ||
31 | |||
32 | /* QT*/ | ||
33 | #include <qdialog.h> | ||
34 | #include <qwidget.h> | ||
35 | #include <qvaluelist.h> | ||
36 | #include <qmap.h> | ||
37 | #include <qvariant.h> | ||
38 | |||
39 | typedef int TransactionID; | ||
40 | |||
41 | class QDialog; | ||
42 | |||
43 | namespace Opie | ||
44 | { | ||
45 | |||
46 | class OModalHelperControler; | ||
47 | class OModalHelperSignal; | ||
48 | |||
49 | struct OModalHelperBase | ||
50 | { | ||
51 | virtual void done( int status, TransactionID ) = 0; | ||
52 | virtual void next( TransactionID ) = 0; | ||
53 | virtual void prev( TransactionID ) = 0; | ||
54 | }; | ||
55 | |||
56 | /** | ||
57 | * Modality sucks! ;) But it is easy to work with | ||
58 | * do exec() on a dialog and you know everything is funky. | ||
59 | * You only need to have one Dialog loaded and so on. | ||
60 | * This class helps you to work like with modality and help | ||
61 | * you to keep things in sync | ||
62 | * It's a template class but it sends signals once one Item is ready | ||
63 | * the signals contains the status and id of the item and then you | ||
64 | * need fetch it. | ||
65 | * Handled Records will stay available until the first call to retrieve | ||
66 | * either the record via the TransactionID or via the QValueList<Record>. Note | ||
67 | * that most functions do not take handled records into account. | ||
68 | * Also if you edit an record external you can tell this class and it'll | ||
69 | * call the merge() function of your widget to maybe merge in these changes. | ||
70 | * It also supports multiple modes. Either it can create new dialogs | ||
71 | * for each item or it can queue them depending on your usage. But it is | ||
72 | * so smart that if only one item is shown that the queue bar is not shown | ||
73 | * See the example for simple usage. | ||
74 | * | ||
75 | * @short helps to life without modaility | ||
76 | * @author hOlgAr | ||
77 | * @version 0.01 | ||
78 | */ | ||
79 | template<class Dialog, class Record, typename Id = int> | ||
80 | class OModalHelper : private OModalHelperBase | ||
81 | { | ||
82 | friend class OModalHelperSignal; | ||
83 | friend class OModalHelperControler; | ||
84 | public: | ||
85 | typedef QValueList<Record> RecordList; | ||
86 | typedef QMap<Id, Record> IdMap; | ||
87 | typedef QMap<TransactionID, Id> TransactionMap; | ||
88 | typedef QMap<QDialog*, TransactionID> DialogMap | ||
89 | enum Mode { Queue, New }; | ||
90 | OModalHelper(enum Mode mode, QObject* parnet ); | ||
91 | |||
92 | bool handles( Id id)const; | ||
93 | TransactionID transactionID( Id id)const; | ||
94 | |||
95 | void suspend( bool = true ); | ||
96 | |||
97 | void cancel(); | ||
98 | void cancel( TransactionID ); | ||
99 | |||
100 | void connectDone( QObject* rec, const char* slot ); | ||
101 | void connectAccepted( QObject* rec, const char* slot ); | ||
102 | void connectRejected( QObject* rec, const char* slot ); | ||
103 | |||
104 | TransactionID handle( Id id, const Record& rec = Record() ); | ||
105 | |||
106 | void edited( Id, int what, const QVariant& data ); | ||
107 | |||
108 | Record record( TransactionID )const; | ||
109 | RecordList recordsDone()const; | ||
110 | private: | ||
111 | virtual void done( int, TransactionID ); | ||
112 | virtual void next( TransactionID ); | ||
113 | virtual void prev( TransactionID ); | ||
114 | |||
115 | Record nextRecord( TransactionID &, int & )const; | ||
116 | Record prevRecord( TransactionID &, int & )const; | ||
117 | int pos( TransactionID )const; | ||
118 | Dialog* newDialogRecord( const Record& ); | ||
119 | |||
120 | private: | ||
121 | OModalHelperDialog *queuedDialog()const; // generate or recycle | ||
122 | OModalHelperDialog *m_dialog; | ||
123 | OModalHelperSignal *m_signal; // our signal | ||
124 | OModalHelperControler *m_controler; | ||
125 | IdMap m_ids; // maps ids (uids) to a record | ||
126 | IdMap m_doneIds; | ||
127 | TransactionMap m_transactions; // activate transactions | ||
128 | TransactionMap m_done; // done and waiting for getting picked | ||
129 | DialogMap m_editing; // only used for New Mode | ||
130 | enum Mode m_mode; // the mode we're in | ||
131 | bool m_disabled :1; | ||
132 | }; | ||
133 | |||
134 | |||
135 | |||
136 | /* ### FIXME use namespace with Qt3 */ | ||
137 | |||
138 | /* | ||
139 | * A note on flow. The Signal is used for QT Signals when | ||
140 | * a record is done. | ||
141 | * There is either one controler and this controler slot will | ||
142 | * be connected to a dialog signal. | ||
143 | * In Queue we get the next and prev signals and call the Helper. | ||
144 | * this then changes the Record of the dialog and sets the transactionId | ||
145 | * of the controler. | ||
146 | * For the new mode | ||
147 | * | ||
148 | */ | ||
149 | |||
150 | class OModalHelperSignal : public QObject | ||
151 | { | ||
152 | Q_OBJECT | ||
153 | public: | ||
154 | OModalHelperSignal(OModalHelperBase* base, QObject* parent); | ||
155 | ~OModalHelperSignal(); | ||
156 | |||
157 | signals: | ||
158 | done( int status, TransactionID transaction ); | ||
159 | accepted( TransactionID transaction ); | ||
160 | rejected( TransactionID transaction ); | ||
161 | |||
162 | private: | ||
163 | OModalHelperBase* m_base; | ||
164 | }; | ||
165 | |||
166 | |||
167 | class OModalHelperControler : public QObject | ||
168 | { | ||
169 | Q_OBJECT | ||
170 | public: | ||
171 | OModalHelperControler( OModalHelperBase* , QObject* parent); | ||
172 | virtual TransactionID transactionID()const; | ||
173 | void setTransactionID( TransactionID id ); | ||
174 | QDialog* dialog()const; | ||
175 | |||
176 | public slots: | ||
177 | virtual void done(int result ); | ||
178 | virtual void next(); | ||
179 | virtual void prev(); | ||
180 | private: | ||
181 | QDialog *m_dia; | ||
182 | TransactionID m_id; | ||
183 | OModalHelperBase *m_base; | ||
184 | } | ||
185 | |||
186 | struct OModalQueueBar; | ||
187 | class OModalQueuedDialog : public QDialog | ||
188 | { | ||
189 | Q_OBJECT | ||
190 | public: | ||
191 | OModalQueuedDialog(QDialog *mainWidget); | ||
192 | ~OModalQueuedDialog(); | ||
193 | |||
194 | QDialog* centerDialog()const; | ||
195 | |||
196 | void setQueueBarEnabled( bool = true ); | ||
197 | void setRecord( int record, int count ); | ||
198 | |||
199 | signals: | ||
200 | void next(); | ||
201 | void prev(); | ||
202 | |||
203 | private: | ||
204 | OModalQueueBar *m_bar; | ||
205 | QDialog *m_center; | ||
206 | }; | ||
207 | |||
208 | |||
209 | /* | ||
210 | * Tcpp Template Implementation | ||
211 | */ | ||
212 | |||
213 | /** | ||
214 | * This is the simple Template c'tor. It takes the mode | ||
215 | * this helper should operate in and the parent object. | ||
216 | * This helper will be deleted when the parent gets deleted | ||
217 | * or you delete it yourself. | ||
218 | * | ||
219 | * @param mode The mode this dialog should be in | ||
220 | * @param parent The parent QObject of this helper. | ||
221 | */ | ||
222 | template<class Dialog, class Record, typename Id> | ||
223 | OModalHelper<Dialog, Record, Id>::OModalHelper( enum Mode mode, QObject* parent ) | ||
224 | { | ||
225 | m_disabled = false; | ||
226 | m_mode = mode; | ||
227 | m_signal = new OModalHelperSignal( this, parent ); | ||
228 | m_controler = new OModalHelperControler( this, m_signal ); | ||
229 | } | ||
230 | |||
231 | |||
232 | /** | ||
233 | * This functions looks for your record and sees if it is | ||
234 | * handled with this helper. Note that done records | ||
235 | * will not be returned. | ||
236 | * | ||
237 | * @return true if the record is currenlty edited otherwise false | ||
238 | * | ||
239 | * @param Id The id which might be handled | ||
240 | */ | ||
241 | template<class Dialog, class Record, typename Id> | ||
242 | bool OModalHelper<Dialog, Record, Id>::handles( Id id )const | ||
243 | { | ||
244 | if ( m_transactions.isEmpty() ) | ||
245 | return false; | ||
246 | |||
247 | TransactionMap::ConstIterator it = m_transactions.begin(); | ||
248 | for ( ; it != m_transactions.end(); ++it ) | ||
249 | if ( it.data() == id ) | ||
250 | return true; | ||
251 | |||
252 | return false; | ||
253 | } | ||
254 | |||
255 | |||
256 | /** | ||
257 | * just like handles( Id ) but returns the TransactionId | ||
258 | */ | ||
259 | template<class Dialog, class Record, typename Id> | ||
260 | TransactionID OModalHelper<Dialog, Record, Id>::transactionID( Id id)const | ||
261 | { | ||
262 | if ( m_transactions.isEmpty() || !m_ids.contains( id ) ) | ||
263 | return 0; | ||
264 | |||
265 | TransactionMap::ConstIterator it = m_transactions.begin(); | ||
266 | for ( ; it != m_transactions.end(); ++it ) | ||
267 | if ( it.data() == id ) | ||
268 | return it.key(); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * If you're requested to flush your data and you do not want | ||
275 | * to call cancel with this method you can disable and enabled | ||
276 | * all dialogs. | ||
277 | * The state gets saved so if you want to handle a new record the dialog | ||
278 | * will be disabled as well. | ||
279 | * | ||
280 | * @param sus If true setDisabled(TRUE) will be called otherwise FALSE | ||
281 | */ | ||
282 | template<class Dialog, class Record, typename Id> | ||
283 | void OModalHelper<Dialog, Record, Id>::suspend(bool sus) | ||
284 | { | ||
285 | m_disabled = sus; | ||
286 | if (m_mode == New ) | ||
287 | for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it ) | ||
288 | it.key()->setDisabled( sus ); | ||
289 | else if (m_dialog ) | ||
290 | queuedDialog()->setDisabled( sus ); | ||
291 | } | ||
292 | |||
293 | /** | ||
294 | * Cancel will cancel all current operations and clear the list | ||
295 | * of done operations as well. | ||
296 | * This also clears all done operations you did not popped | ||
297 | */ | ||
298 | template<class Dialog, class Record, typename Id> | ||
299 | void OModalHelper<Dialog, Record, Id>::cancel() | ||
300 | { | ||
301 | m_ids.clear(); | ||
302 | m_doneIds.clear(); | ||
303 | m_done.clear(); | ||
304 | m_transactions.clear(); | ||
305 | |||
306 | /* we also need to remove the QDialogs */ | ||
307 | /* and hide the queue dialog if present */ | ||
308 | if (m_mode == New && !m_editing.isEmpty() ) | ||
309 | { | ||
310 | for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it ) | ||
311 | delete it.key(); | ||
312 | |||
313 | m_editing.clear(); | ||
314 | } | ||
315 | else if (m_dialog ) | ||
316 | queuedDialog()->setRecord( 0, 0 ); | ||
317 | |||
318 | m_controler->setTransactionID( 0 ); | ||
319 | } | ||
320 | |||
321 | |||
322 | /** | ||
323 | * This cancels editing of the record behind the Transaction Number | ||
324 | * Note that if editing is already done it will also be removed from this list | ||
325 | */ | ||
326 | template<class Dialog, class Record, typename Id> | ||
327 | void OModalHelper::cancel( TransactionID tid ) | ||
328 | { | ||
329 | /* wrong tid */ | ||
330 | if (!m_transactions.contains( tid ) && !m_done.contains( tid) ) | ||
331 | return; | ||
332 | |||
333 | if (m_mode == New ) | ||
334 | /* reverse map eek */ | ||
335 | for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it ) | ||
336 | if ( it.data() == tid ) | ||
337 | { | ||
338 | it.key()->hide(); | ||
339 | delete it.key(); | ||
340 | it = m_editing.remove( it ); | ||
341 | break; | ||
342 | } | ||
343 | |||
344 | /* now remove from the various maps done and currently editing map*/ | ||
345 | if (m_transactions.contains( tid ) ) | ||
346 | m_ids.remove( m_transactions[tid] ); | ||
347 | if (m_done.contains( tid ) ) | ||
348 | m_doneIds.remove( m_done[tid ] ); | ||
349 | m_done.remove( tid ); | ||
350 | m_transactions.remove( tid ); | ||
351 | |||
352 | next( 0 ); | ||
353 | } | ||
354 | |||
355 | /** | ||
356 | * Connect to the done Signal. SIGNAL( done(int, TransactionID ) ) | ||
357 | * This signal gets emitted whenever a Record was accepted or rejected | ||
358 | * | ||
359 | * @param rec The object where the slot belongs to | ||
360 | * @param slot The slot which should be called. See the needed parameter above | ||
361 | */ | ||
362 | template<class Dialog, class Record, typename Id> | ||
363 | void OModalHelper<Dialog, Record, Id>::connectDone( QObject* rec, const char* slot ) | ||
364 | { | ||
365 | QObject::connect(m_signal, SIGNAL(done(int, TransactionID) ), | ||
366 | rec, slot ); | ||
367 | } | ||
368 | |||
369 | /** | ||
370 | * Connect to the accepted Signal. SIGNAL( accepted(TransactionID ) ) | ||
371 | * This signal gets emitted whenever a Record was accepted | ||
372 | * | ||
373 | * @param rec The object where the slot belongs to | ||
374 | * @param slot The slot which should be called. See the needed parameter above | ||
375 | */ | ||
376 | template<class Dialog, class Record, typename Id> | ||
377 | void OModalHelper<Dialog, Record, Id>::connectAccepted( QObject* rec, const char* slot ) | ||
378 | { | ||
379 | QObject::connect(m_signal, SIGNAL(accepted(TransactionID) ), | ||
380 | rec, slot ); | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * Same as the accepted method but this one gets emitted if the dialog | ||
385 | * got rejected. | ||
386 | * SIGNAL( rejected(TransactionID) ) | ||
387 | * | ||
388 | * @param rec The QObject of the slot | ||
389 | * @param slot The slot make sure the signature is correct | ||
390 | */ | ||
391 | template<class Dialog, class Record, typename Id> | ||
392 | void OModalHelper<Dialog, Record, Id>::connectRejected( QObject* rec, const char* slot ) | ||
393 | { | ||
394 | QObject::connect(m_signal, SIGNAL(rejected(TransactionID) ), | ||
395 | rec, slot ); | ||
396 | } | ||
397 | |||
398 | /** | ||
399 | * Tell the helper to handle a record. If the record is currently handled | ||
400 | * it will be made active. | ||
401 | * Already handled record which are waiting getting popped are not taken into account | ||
402 | * Otherwise this helpers make the record editable. | ||
403 | * The record supplied needs to have a valid copy operator and constructor. | ||
404 | * In the case where the record is already present the parameter gets discarded. | ||
405 | * If you want the new record to be taken you need to cancel the Transaction first | ||
406 | * | ||
407 | * @param id The Identification of the Record. For PIM it would uid() | ||
408 | * @param rec The record we want to be edited | ||
409 | * | ||
410 | * @returns This functions returns the TransactionId assigned to the record | ||
411 | * | ||
412 | */ | ||
413 | template<class Dialog, class Record, typename Id> | ||
414 | TransactionID OModalHelper<Dialog, Record, Id>::handle( Id id, const Record& rec ) | ||
415 | { | ||
416 | static TransactionID t_id = 0; | ||
417 | /* | ||
418 | *this method consists out of two parts divided each into New and Queued Mode. | ||
419 | * Either we have the dialog already, in this case we need to highlight the widget | ||
420 | * Or we need to add it. | ||
421 | */ | ||
422 | TransactionID tid = 0; | ||
423 | /* we already have the record lets see if it was done or not */ | ||
424 | if ( !(tid = transactionID( id ) ) ) | ||
425 | { | ||
426 | if (m_mode == New ) | ||
427 | { | ||
428 | /* lets find the dialog and show it need to reverse map*/ | ||
429 | for (DialogMap::Iterator it = m_editing.begin(); it != m_editing.end(); ++it ) | ||
430 | if ( it.data() == tid ) | ||
431 | it.key()->show(); | ||
432 | } | ||
433 | else if (m_controler->transactionID() != tid ) | ||
434 | { | ||
435 | int po = pos( tid ); | ||
436 | m_controler->setTransactionID( tid ); | ||
437 | static_cast<Dialog*>( queuedDialog()->centerDialog() )->setRecord( m_ids[ m_transactions[tid] ] ); | ||
438 | queuedDialog()->setRecord( po, m_transactions.count() ); | ||
439 | } | ||
440 | } | ||
441 | else | ||
442 | { | ||
443 | tid = ++t_id; | ||
444 | m_transactions.insert( tid, id ); | ||
445 | m_ids.insert( id, rec ); | ||
446 | |||
447 | if (m_mode == New ) | ||
448 | m_editing.insert( newDialogRecord( rec ), tid ); | ||
449 | else | ||
450 | { | ||
451 | m_controler->setTransactionID( tid ); | ||
452 | static_cast<Dialog*>( queuedDialog()->centerDialog() )->setRecord( rec ); | ||
453 | queuedDialog()->setRecord( m_transactions.count(), m_transactions.count() ); | ||
454 | } | ||
455 | } | ||
456 | return tid; | ||
457 | } | ||
458 | |||
459 | /** | ||
460 | * The goal of this helper is to help you to create non blocking | ||
461 | * GUIs. In the example of the todolist you can have the edit dialog | ||
462 | * but still change the priority or completion inline even if you currently | ||
463 | * edit the record. | ||
464 | * Your Dialog needs to have a Method setData(int,const QVariant& ) which will be called | ||
465 | * in these cases. | ||
466 | * If you edit anything while a record is edited call this function to merge the | ||
467 | * change in. Note if the record is not handled here we will ignore the request | ||
468 | * | ||
469 | */ | ||
470 | template<class Dialog, class Record, typename Id> | ||
471 | void OModalHelper<Dialog, Record, Id>::edited( Id id, int what, const QVariant& data ) | ||
472 | { | ||
473 | int tid; | ||
474 | if (!( tid = transactionID( id ) ) ) | ||
475 | return; | ||
476 | |||
477 | if (m_mode == New ) | ||
478 | { | ||
479 | for (DialogMap::Iterator it= m_editing.begin(); it != m_editing.end(); ++it ) | ||
480 | if ( it.data() == tid ) | ||
481 | it.key()->setData( what, data ); | ||
482 | } | ||
483 | else | ||
484 | { | ||
485 | int po = pos( tid ); | ||
486 | Dialog* dia = static_cast<Dialog*>( queuedDialog()->centerDialog() ); | ||
487 | dia->setRecord( m_ids[id] ); | ||
488 | dia->setData( what, data ); | ||
489 | queuedDialog()->setRecord( pos, m_transactions.count() ); | ||
490 | } | ||
491 | } | ||
492 | |||
493 | /** | ||
494 | * This functions either returns the unedited record the done record | ||
495 | * or a new empty Record using Record(). | ||
496 | * If a done record is retrieved all traces are removed inside this class. This | ||
497 | * is what was called popping a record. This means when you call this function | ||
498 | * with the same TransactionID an Empty record is retrieved. | ||
499 | * | ||
500 | */ | ||
501 | template<class Dialog, class Record, typename Id> | ||
502 | Record OModalHelper<Dialog, Record, Id>::record( TransactionID tid)const | ||
503 | { | ||
504 | if (m_transactions.contains( tid ) ) | ||
505 | return m_ids[ m_transactions[tid] ]; | ||
506 | else if (m_done.contains( tid ) ) | ||
507 | { | ||
508 | Record rec = m_doneIds[ m_done[ tid] ]; | ||
509 | m_doneIds.remove( m_done[ tid ] ); | ||
510 | m_done.remove( tid ); | ||
511 | return rec; | ||
512 | } | ||
513 | else | ||
514 | return Record(); | ||
515 | } | ||
516 | |||
517 | /** | ||
518 | * Returns all done Records and removes all references to them internally. A 2nd call to this will | ||
519 | * only contain done record that where edited past the point | ||
520 | */ | ||
521 | template<class Dialog, class Record, typename Id> | ||
522 | OModalHelper<Dialog,Record,Id>::RecordList OModalHelper<Dialog, Record, Id>::recordsDone()const | ||
523 | { | ||
524 | RecordList list; | ||
525 | |||
526 | for (IdMap::ConstIterator it = m_doneIds.begin(); it != m_doneIds.end(); ++it ) | ||
527 | list.append( it.data() ); | ||
528 | |||
529 | /* clean up */ | ||
530 | m_done.clear(); | ||
531 | m_doneIds.clear(); | ||
532 | |||
533 | return list; | ||
534 | } | ||
535 | |||
536 | |||
537 | /** | ||
538 | * @internal | ||
539 | */ | ||
540 | template<class Dialog, class Record, typename Id> | ||
541 | void OModalHelper<Dialog, Record, Id>::done( int status, TransactionID tid) | ||
542 | { | ||
543 | /* If we're in New mode the transaction Id does not count */ | ||
544 | Record rec; | ||
545 | |||
546 | if (m_mode == New ) | ||
547 | { | ||
548 | Dialog *dia = static_cast<Dialog*>( m_controler->dialog() ); | ||
549 | m_controler->setTransactionID( 0 ); // set the internal dialog to 0l again | ||
550 | tid = m_editing[ dia ]; | ||
551 | m_editing.remove( dia ); | ||
552 | rec = dia->record(); | ||
553 | delete dia; | ||
554 | } | ||
555 | else | ||
556 | rec = queuedDialog()->record(); | ||
557 | |||
558 | Id id = m_transactions[ tid ]; | ||
559 | if (result == QDialog::Accept ) | ||
560 | { | ||
561 | m_doneIds.insert( is, rec ); | ||
562 | m_done.insert( tid, id ); | ||
563 | } | ||
564 | |||
565 | m_transactions.remove( tid ); | ||
566 | m_ids.remove( id ); | ||
567 | |||
568 | |||
569 | if (status == QDialog::Accept ) | ||
570 | emit m_signal->accepted( tid ); | ||
571 | else | ||
572 | emit m_signal->rejected( tid ); | ||
573 | |||
574 | emit m_signal->done( result, tid ); | ||
575 | |||
576 | next( 0 ); | ||
577 | } | ||
578 | |||
579 | /** | ||
580 | * @internal | ||
581 | */ | ||
582 | template<class Dialog, class Record, typename Id> | ||
583 | void OModalHelper<Dialog, Record, Id>::next( TransactionID tid) | ||
584 | { | ||
585 | if (m_mode == New ) | ||
586 | return; | ||
587 | |||
588 | if (! (m_transactions.count() ) ) | ||
589 | { | ||
590 | m_controler->setTransactionID( 0 ); | ||
591 | queuedDialog()->setRecord( 0, 0 ); | ||
592 | return; | ||
593 | } | ||
594 | |||
595 | int next; | ||
596 | Record rec; | ||
597 | |||
598 | /* save the maybe edited record before switching */ | ||
599 | Dialog *dia = static_cast<Dialog*>( queuedDialog()->centerDialog() ); | ||
600 | rec = dia->record(); | ||
601 | m_ids.replace( m_transactions[tid], rec ); | ||
602 | |||
603 | rec = nextRecord( tid, next ); | ||
604 | queuedDialog()->setRecord( next, m_transactions.count() ); | ||
605 | dia->setRecord( rec ); | ||
606 | |||
607 | m_controler->setTransactionID( tid ); // was changed during the next call | ||
608 | } | ||
609 | |||
610 | /** | ||
611 | * @internal | ||
612 | */ | ||
613 | /* | ||
614 | * code duplication should create a template fcuntion | ||
615 | * which takes a pointer to a function ( next, prev ) function | ||
616 | */ | ||
617 | template<class Dialog, class Record, typename Id> | ||
618 | void OModalHelper<Dialog, Record, Id>::prev( TransactionID tid ) | ||
619 | { | ||
620 | if (m_mode == New ) | ||
621 | return; | ||
622 | |||
623 | if (! (m_transactions.count()) ) | ||
624 | { | ||
625 | m_controler->setTransactionID( 0 ); | ||
626 | queuedDialog()->setRecord( 0, 0 ); | ||
627 | return; | ||
628 | } | ||
629 | |||
630 | int prev; | ||
631 | Record rec; | ||
632 | |||
633 | /* save the maybe edited record before switching */ | ||
634 | Dialog *dia = static_cast<Dialog*>( queuedDialog()->centerDialog() ); | ||
635 | rec = dia->record(); | ||
636 | m_ids.replace( m_transactions[tid], rec ); | ||
637 | |||
638 | rec = prevRecord( tid, prev ); | ||
639 | queuedDialog()->setRecord( prev, m_transactions.count() ); | ||
640 | dia->setRecord( rec ); | ||
641 | |||
642 | m_controler->setTransactionID( tid ); // was changed during the next call | ||
643 | } | ||
644 | |||
645 | /** | ||
646 | * @internal | ||
647 | */ | ||
648 | template<class Dialog, class Record, typename Id> | ||
649 | Record OModalHelper<Dialog, Record, Id>::nextRecord( TransactionID &tid, int &po ) | ||
650 | { | ||
651 | /* if tid is == 0 we will take the first one */ | ||
652 | /* pos starts at 1 here */ | ||
653 | /* we know we're only called if there are records */ | ||
654 | Record rec; | ||
655 | TransactionMap::Iterator it; | ||
656 | if (!tid ) | ||
657 | { | ||
658 | po = 1; | ||
659 | TransactionMap::Iterator it = m_transactions.begin(); | ||
660 | } | ||
661 | else | ||
662 | { | ||
663 | po = pos( tid ); | ||
664 | /* if it is the last take the first as next */ | ||
665 | if ( po == m_transactions.count() ) | ||
666 | { | ||
667 | po = 1; | ||
668 | it = m_transactions.begin(); | ||
669 | } | ||
670 | else | ||
671 | { | ||
672 | /* we know we're not the last and there is one after us */ | ||
673 | it = m_transactions.find( tid ); | ||
674 | ++it; ++po; | ||
675 | } | ||
676 | } | ||
677 | |||
678 | tid = it.key(); | ||
679 | rec = m_ids[ tid ]; | ||
680 | return rec; | ||
681 | } | ||
682 | |||
683 | /** | ||
684 | * @internal | ||
685 | */ | ||
686 | template<class Dialog, class Record, typename Id> | ||
687 | Record OModalHelper<Dialog, Record, Id>::prevRecord( TransactionID& tid, int& pos ) | ||
688 | { | ||
689 | /* if tid is == 0 we will take the first one */ | ||
690 | /* pos starts at 1 here */ | ||
691 | /* we know we're only called if there are records */ | ||
692 | Record rec; | ||
693 | TransactionMap::Iterator it; | ||
694 | if (!tid ) | ||
695 | { | ||
696 | po = 1; | ||
697 | TransactionMap::Iterator it = m_transactions.begin(); | ||
698 | } | ||
699 | else | ||
700 | { | ||
701 | po = pos( tid ); | ||
702 | /* if it is the last take the first as next */ | ||
703 | if ( po == 1 ) | ||
704 | { | ||
705 | po = m_transactions.count(); | ||
706 | it = m_transactions.end(); | ||
707 | --it; | ||
708 | } | ||
709 | else | ||
710 | { | ||
711 | /* we know we're not the first and there is one before us */ | ||
712 | it = m_transactions.find( tid ); | ||
713 | --it; --po; | ||
714 | } | ||
715 | } | ||
716 | |||
717 | tid = it.key(); | ||
718 | rec = m_ids[ tid ]; | ||
719 | return rec; | ||
720 | } | ||
721 | |||
722 | /** | ||
723 | * @internal | ||
724 | */ | ||
725 | template<class Dialog, class Record, typename Id> | ||
726 | int OModalHelper<Dialog, Record, Id>::pos( TransactionID id)const | ||
727 | { | ||
728 | int i = 1; | ||
729 | for ( TransactionMap::ConstIterator it = m_transactions.begin(); it != m_transactions.end(); ++it, i++ ) | ||
730 | if ( it.key() == id ) | ||
731 | return i; | ||
732 | |||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | /** | ||
738 | * @internal | ||
739 | */ | ||
740 | template<class Dialog, class Record, typename Id> | ||
741 | Dialog* OModalHelper<Dialog, Record, Id>::newDialogRecord( const Record& rec ) | ||
742 | { | ||
743 | Dialog* dia = new Dialog; | ||
744 | dia->setRecord( rec ); | ||
745 | dia->setDisabled( m_disabled ); | ||
746 | |||
747 | QObject::connect(dia, SIGNAL(done(int) ), | ||
748 | m_controler, SLOT(done(int) ) ); | ||
749 | |||
750 | /* FIXME big screen QPEApplication needs fixed*/ | ||
751 | dia->show(); | ||
752 | } | ||
753 | |||
754 | template<class Record, class Dialog, typename Id> | ||
755 | OModalHelperDialog* OModalHelper<Record, Dialog, Id>::queuedDialog()const | ||
756 | { | ||
757 | if (!m_dialog ) | ||
758 | { | ||
759 | m_dialog = new OModalHelperDialog; | ||
760 | m_dialog->setEnabled( m_disabled ); | ||
761 | |||
762 | QObject::connect(m_dialog, SIGNAL(done(int) ), | ||
763 | m_controler, SLOT(done(int) ) ); | ||
764 | QObject::connect(m_dialog, SIGNAL(next() ), | ||
765 | m_controler, SLOT(next() ) ); | ||
766 | QObject::connect(m_dialog, SIGNAL(prev() ), | ||
767 | m_controler, SLOT(prev() ) ); | ||
768 | } | ||
769 | return m_dialog; | ||
770 | } | ||
771 | |||
772 | }; | ||
773 | |||
774 | #endif | ||
diff --git a/libopie2/opieui/big-screen/osplitter.cpp b/libopie2/opieui/big-screen/osplitter.cpp new file mode 100644 index 0000000..89f3793 --- a/dev/null +++ b/libopie2/opieui/big-screen/osplitter.cpp | |||
@@ -0,0 +1,638 @@ | |||
1 | /* | ||
2 | =. This file is part of the OPIE Project | ||
3 | .=l. Copyright (c) 2003 hOlgAr <zecke@handhelds.org> | ||
4 | .>+-= | ||
5 | _;:, .> :=|. This library is free software; you can | ||
6 | .> <`_, > . <= redistribute it and/or modify it under | ||
7 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public | ||
8 | .="- .-=="i, .._ License as published by the Free Software | ||
9 | - . .-<_> .<> Foundation; either version 2 of the License, | ||
10 | ._= =} : or (at your option) any later version. | ||
11 | .%`+i> _;_. | ||
12 | .i_,=:_. -<s. This library is distributed in the hope that | ||
13 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; | ||
14 | : .. .:, . . . without even the implied warranty of | ||
15 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A | ||
16 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU | ||
17 | ..}^=.= = ; Library General Public License for more | ||
18 | ++= -. .` .: details. | ||
19 | : = ...= . :.=- | ||
20 | -. .:....=;==+<; You should have received a copy of the GNU | ||
21 | -_. . . )=. = Library General Public License along with | ||
22 | -- :-=` this library; see the file COPYING.LIB. | ||
23 | If not, write to the Free Software Foundation, | ||
24 | Inc., 59 Temple Place - Suite 330, | ||
25 | Boston, MA 02111-1307, USA. | ||
26 | |||
27 | */ | ||
28 | |||
29 | #include "osplitter.h" | ||
30 | |||
31 | /* OPIE */ | ||
32 | #include <opie2/otabwidget.h> | ||
33 | |||
34 | /* QT */ | ||
35 | #include <qvaluelist.h> | ||
36 | #include <qvbox.h> | ||
37 | |||
38 | using namespace Opie; | ||
39 | |||
40 | /** | ||
41 | * | ||
42 | * This is the constructor of OSplitter | ||
43 | * You might want to call setSizeChange to tell | ||
44 | * OSplitter to change its layout when a specefic | ||
45 | * mark was crossed. OSplitter sets a default value. | ||
46 | * | ||
47 | * You cann add widget with addWidget to the OSplitter. | ||
48 | * OSplitter supports also grouping of Splitters where they | ||
49 | * can share one OTabBar in small screen mode. This can be used | ||
50 | * for email clients like vies but see the example. | ||
51 | * | ||
52 | * @param orient The orientation wether to layout horizontal or vertical | ||
53 | * @param parent The parent of this widget | ||
54 | * @param name The name passed on to QObject | ||
55 | * @param fl Additional widgets flags passed to QWidget | ||
56 | * | ||
57 | * @short single c'tor of the OSplitter | ||
58 | */ | ||
59 | OSplitter::OSplitter( Orientation orient, QWidget* parent, const char* name, WFlags fl ) | ||
60 | : QFrame( parent, name, fl ) | ||
61 | { | ||
62 | m_orient = orient; | ||
63 | m_hbox = 0; | ||
64 | m_size_policy = 330; | ||
65 | setFontPropagation( AllChildren ); | ||
66 | setPalettePropagation( AllChildren ); | ||
67 | |||
68 | /* start by default with the tab widget */ | ||
69 | m_tabWidget = 0; | ||
70 | m_parentTab = 0; | ||
71 | changeTab(); | ||
72 | |||
73 | } | ||
74 | |||
75 | |||
76 | /** | ||
77 | * Destructor destructs this object and cleans up. All child | ||
78 | * widgets will be deleted | ||
79 | * @see addWidget | ||
80 | */ | ||
81 | OSplitter::~OSplitter() | ||
82 | { | ||
83 | qWarning("Deleted Splitter"); | ||
84 | m_splitter.setAutoDelete( true ); | ||
85 | m_splitter.clear(); | ||
86 | |||
87 | delete m_hbox; | ||
88 | delete m_tabWidget; | ||
89 | } | ||
90 | |||
91 | |||
92 | /** | ||
93 | * Sets the label for the Splitter. This label will be used | ||
94 | * if a parent splitter is arranged as TabWidget but | ||
95 | * this splitter is in fullscreen mode. Then a tab with OSplitter::label() | ||
96 | * and iconName() gets added. | ||
97 | * | ||
98 | * @param name The name of the Label | ||
99 | */ | ||
100 | void OSplitter::setLabel( const QString& name ) | ||
101 | { | ||
102 | m_name = name; | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * @see setLabel but this is for the icon retrieved by Resource | ||
107 | * | ||
108 | * @param name The name of the icon in example ( "zoom" ) | ||
109 | */ | ||
110 | void OSplitter::setIconName( const QString& name ) | ||
111 | { | ||
112 | m_icon = name; | ||
113 | } | ||
114 | |||
115 | |||
116 | /** | ||
117 | * returns the iconName | ||
118 | * @see setIconName | ||
119 | */ | ||
120 | QString OSplitter::iconName()const | ||
121 | { | ||
122 | return m_icon; | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * returns the label set with setLabel | ||
127 | * @see setLabel | ||
128 | */ | ||
129 | QString OSplitter::label()const | ||
130 | { | ||
131 | return m_name; | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * This function sets the size change policy of the splitter. | ||
136 | * If this size marked is crossed the splitter will relayout. | ||
137 | * Note: that depending on the set Orientation it'll either look | ||
138 | * at the width or height. | ||
139 | * Note: If you want to from side to side view to tabbed view you need | ||
140 | * to make sure that the size you supply is not smaller than the minimum | ||
141 | * size of your added widgets. Note that if you use widgets like QComboBoxes | ||
142 | * you need to teach them to accept smaller sizes as well @see QWidget::setSizePolicy | ||
143 | * | ||
144 | * @param width_height The mark that will be watched. Interpreted depending on the Orientation of the Splitter. | ||
145 | * @return void | ||
146 | */ | ||
147 | void OSplitter::setSizeChange( int width_height ) | ||
148 | { | ||
149 | m_size_policy = width_height; | ||
150 | QSize sz(width(), height() ); | ||
151 | QResizeEvent ev(sz, sz ); | ||
152 | resizeEvent(&ev); | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * This functions allows to add another OSplitter and to share | ||
157 | * the OTabBar in small screen mode. The ownerships gets transfered. | ||
158 | * OSplitters are always added after normal widget items | ||
159 | */ | ||
160 | void OSplitter::addWidget( OSplitter* split ) | ||
161 | { | ||
162 | m_splitter.append( split ); | ||
163 | |||
164 | /* | ||
165 | * set tab widget | ||
166 | */ | ||
167 | if (m_tabWidget ) | ||
168 | setTabWidget( m_parentTab ); | ||
169 | else | ||
170 | { | ||
171 | Opie::OSplitterContainer con; | ||
172 | con.widget =split; | ||
173 | addToBox( con ); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * If in a tab it should be removed | ||
179 | * and if in a hbox the reparent kills it too | ||
180 | */ | ||
181 | /** | ||
182 | * This removes the splitter again. You currently need to call this | ||
183 | * before you delete or otherwise you can get mem corruption | ||
184 | * or other weird behaviour. | ||
185 | * Owner ship gets transfered back to you it's current parent | ||
186 | * is 0 | ||
187 | */ | ||
188 | void OSplitter::removeWidget( OSplitter* split) | ||
189 | { | ||
190 | split->setTabWidget( 0 ); | ||
191 | split->reparent( 0, 0, QPoint(0, 0) ); | ||
192 | } | ||
193 | |||
194 | /** | ||
195 | * Adds a widget to the Splitter. The widgets gets inserted | ||
196 | * at the end of either the Box or TabWidget. | ||
197 | * Ownership gets transfered and the widgets gets reparented. | ||
198 | * Note: icon and label is only available on small screensizes | ||
199 | * if size is smaller than the mark | ||
200 | * Warning: No null checking of the widget is done. Only on debug | ||
201 | * a message will be outputtet | ||
202 | * | ||
203 | * @param wid The widget which will be added | ||
204 | * @param icon The icon of the possible Tab | ||
205 | * @param label The label of the possible Tab | ||
206 | */ | ||
207 | void OSplitter::addWidget( QWidget* wid, const QString& icon, const QString& label ) | ||
208 | { | ||
209 | #ifdef DEBUG | ||
210 | if (!wid ) | ||
211 | { | ||
212 | qWarning("Widget is not valid!"); | ||
213 | return; | ||
214 | } | ||
215 | #endif | ||
216 | Opie::OSplitterContainer cont; | ||
217 | cont.widget = wid; | ||
218 | cont.icon =icon; | ||
219 | cont.name = label; | ||
220 | |||
221 | m_container.append( cont ); | ||
222 | |||
223 | /* | ||
224 | * | ||
225 | */ | ||
226 | if (!m_splitter.isEmpty() && (m_tabWidget || m_parentTab ) ) | ||
227 | setTabWidget( m_parentTab ); | ||
228 | else | ||
229 | { | ||
230 | if (m_hbox ) | ||
231 | addToBox( cont ); | ||
232 | else | ||
233 | addToTab( cont ); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | |||
238 | /** | ||
239 | * Removes the widget from the tab widgets if necessary. | ||
240 | * OSplitter drops ownership of this widget and the widget | ||
241 | * will be reparented i tto 0. | ||
242 | * The widget will not be deleted. | ||
243 | * | ||
244 | * @param w The widget to be removed | ||
245 | */ | ||
246 | void OSplitter::removeWidget( QWidget* w) | ||
247 | { | ||
248 | ContainerList::Iterator it; | ||
249 | for ( it = m_container.begin(); it != m_container.end(); ++it ) | ||
250 | if ( (*it).widget == w ) | ||
251 | break; | ||
252 | |||
253 | if (it == m_container.end() ) | ||
254 | return; | ||
255 | |||
256 | |||
257 | /* only tab needs to be removed.. box recognizes it */ | ||
258 | if ( !m_hbox ) | ||
259 | removeFromTab( w ); | ||
260 | |||
261 | |||
262 | /* Find reparent it and remove it from our list */ | ||
263 | |||
264 | w->reparent( 0, 0, QPoint(0, 0)); | ||
265 | it = m_container.remove( it ); | ||
266 | |||
267 | } | ||
268 | |||
269 | |||
270 | /** | ||
271 | * This method will give focus to the widget. If in a tabwidget | ||
272 | * the tabbar will be changed | ||
273 | * | ||
274 | * @param w The widget which will be set the current one | ||
275 | */ | ||
276 | void OSplitter::setCurrentWidget( QWidget* w) | ||
277 | { | ||
278 | if (m_tabWidget ) | ||
279 | m_tabWidget->setCurrentTab( w ); | ||
280 | // else | ||
281 | // m_hbox->setFocus( w ); | ||
282 | |||
283 | } | ||
284 | |||
285 | /** | ||
286 | * This is an overloaded member function and only differs in the | ||
287 | * argument it takes. | ||
288 | * Searches list of widgets for label. It'll pick the first label it finds | ||
289 | * | ||
290 | * @param label Label to look for. First match will be taken | ||
291 | */ | ||
292 | void OSplitter::setCurrentWidget( const QString& label ) | ||
293 | { | ||
294 | ContainerList::Iterator it; | ||
295 | for (it = m_container.begin(); it != m_container.end(); ++it ) | ||
296 | { | ||
297 | if ( (*it).name == label ) | ||
298 | { | ||
299 | setCurrentWidget( (*it).widget ); | ||
300 | break; | ||
301 | } | ||
302 | } | ||
303 | } | ||
304 | |||
305 | /** | ||
306 | * This will only work when the TabWidget is active | ||
307 | * If everything is visible this signal is kindly ignored | ||
308 | * @see OTabWidget::setCurrentTab(int) | ||
309 | * | ||
310 | * @param tab The tab to make current | ||
311 | */ | ||
312 | void OSplitter::setCurrentWidget( int tab ) | ||
313 | { | ||
314 | if (m_tabWidget ) | ||
315 | m_tabWidget->setCurrentTab( tab ); | ||
316 | } | ||
317 | |||
318 | /** | ||
319 | * return the currently activated widget if in tab widget mode | ||
320 | * or null because all widgets are visible | ||
321 | */ | ||
322 | QWidget* OSplitter::currentWidget() const | ||
323 | { | ||
324 | if (m_tabWidget) | ||
325 | return m_tabWidget->currentWidget(); | ||
326 | else if (m_parentTab ) | ||
327 | return m_parentTab->currentWidget(); | ||
328 | |||
329 | return 0l; | ||
330 | } | ||
331 | /* wrong */ | ||
332 | #if 0 | ||
333 | /** | ||
334 | * @reimplented for internal reasons | ||
335 | * returns the sizeHint of one of its sub widgets | ||
336 | */ | ||
337 | QSize OSplitter::sizeHint()const | ||
338 | { | ||
339 | if (m_parentTab ) | ||
340 | return QFrame::sizeHint(); | ||
341 | |||
342 | if (m_hbox ) | ||
343 | return m_hbox->sizeHint(); | ||
344 | else | ||
345 | return m_tabWidget->sizeHint(); | ||
346 | } | ||
347 | |||
348 | QSize OSplitter::minimumSizeHint()const | ||
349 | { | ||
350 | if (m_parentTab ) | ||
351 | return QFrame::minimumSizeHint(); | ||
352 | if (m_hbox) | ||
353 | return m_hbox->sizeHint(); | ||
354 | else | ||
355 | return m_tabWidget->sizeHint(); | ||
356 | } | ||
357 | #endif | ||
358 | |||
359 | /** | ||
360 | * @reimplemented for internal reasons | ||
361 | */ | ||
362 | void OSplitter::resizeEvent( QResizeEvent* res ) | ||
363 | { | ||
364 | QFrame::resizeEvent( res ); | ||
365 | /* | ||
366 | * | ||
367 | */ | ||
368 | // qWarning("Old size was width = %d height = %d", res->oldSize().width(), res->oldSize().height() ); | ||
369 | bool mode = true; | ||
370 | qWarning("New size is width = %d height = %d %s", res->size().width(), res->size().height(), name() ); | ||
371 | if ( res->size().width() > m_size_policy && | ||
372 | m_orient == Horizontal ) | ||
373 | { | ||
374 | changeHBox(); | ||
375 | mode = false; | ||
376 | } | ||
377 | else if ( (res->size().width() <= m_size_policy && | ||
378 | m_orient == Horizontal ) || | ||
379 | (res->size().height() <= m_size_policy && | ||
380 | m_orient == Vertical ) ) | ||
381 | { | ||
382 | changeTab(); | ||
383 | } | ||
384 | else if ( res->size().height() > m_size_policy && | ||
385 | m_orient == Vertical ) | ||
386 | { | ||
387 | qWarning("Changng to vbox %s", name() ); | ||
388 | changeVBox(); | ||
389 | mode = false; | ||
390 | } | ||
391 | |||
392 | emit sizeChanged(mode, m_orient ); | ||
393 | } | ||
394 | |||
395 | /* | ||
396 | * Adds a container to a tab either the parent tab | ||
397 | * or our own | ||
398 | */ | ||
399 | void OSplitter::addToTab( const Opie::OSplitterContainer& con ) | ||
400 | { | ||
401 | QWidget *wid = con.widget; | ||
402 | // not needed widgetstack will reparent as well wid.reparent(m_tabWidget, wid->getWFlags(), QPoint(0, 0) ); | ||
403 | if (m_parentTab ) | ||
404 | m_parentTab->addTab( wid, con.icon, con.name ); | ||
405 | else | ||
406 | m_tabWidget->addTab( wid, con.icon, con.name ); | ||
407 | } | ||
408 | |||
409 | |||
410 | /* | ||
411 | * adds a container to the box | ||
412 | */ | ||
413 | void OSplitter::addToBox( const Opie::OSplitterContainer& con ) | ||
414 | { | ||
415 | QWidget* wid = con.widget; | ||
416 | wid->reparent(m_hbox, 0, QPoint(0, 0) ); | ||
417 | } | ||
418 | |||
419 | |||
420 | /* | ||
421 | * Removes a widget from the tab | ||
422 | */ | ||
423 | void OSplitter::removeFromTab( QWidget* wid ) | ||
424 | { | ||
425 | if (m_parentTab ) | ||
426 | m_parentTab->removePage( wid ); | ||
427 | else | ||
428 | m_tabWidget->removePage( wid ); | ||
429 | } | ||
430 | |||
431 | /* | ||
432 | * switches over to a OTabWidget layout | ||
433 | * it is recursive | ||
434 | */ | ||
435 | void OSplitter::changeTab() | ||
436 | { | ||
437 | /* if we're the owner of the tab widget */ | ||
438 | if (m_tabWidget ) | ||
439 | { | ||
440 | raise(); | ||
441 | show(); | ||
442 | m_tabWidget->setGeometry( frameRect() ); | ||
443 | return; | ||
444 | } | ||
445 | |||
446 | qWarning(" New Tab Widget %s", name() ); | ||
447 | /* | ||
448 | * and add all widgets this will reparent them | ||
449 | * delete m_hbox set it to 0 | ||
450 | * | ||
451 | */ | ||
452 | OTabWidget *tab; | ||
453 | if ( m_parentTab ) | ||
454 | { | ||
455 | hide(); | ||
456 | tab = m_parentTab; | ||
457 | /* expensive but needed cause we're called from setTabWidget and resizeEvent*/ | ||
458 | if (!m_container.isEmpty() ) | ||
459 | { | ||
460 | ContainerList::Iterator it = m_container.begin(); | ||
461 | for (; it != m_container.end(); ++it ) | ||
462 | m_parentTab->removePage( (*it).widget ); | ||
463 | } | ||
464 | } | ||
465 | else | ||
466 | tab = m_tabWidget = new OTabWidget( this ); | ||
467 | |||
468 | connect(tab, SIGNAL(currentChanged(QWidget*) ), | ||
469 | this, SIGNAL(currentChanged(QWidget*) ) ); | ||
470 | |||
471 | for ( ContainerList::Iterator it = m_container.begin(); it != m_container.end(); ++it ) | ||
472 | { | ||
473 | qWarning("Widget is %s", (*it).name.latin1() ); | ||
474 | addToTab( (*it) ); | ||
475 | } | ||
476 | |||
477 | for ( OSplitter* split = m_splitter.first(); split; split = m_splitter.next() ) | ||
478 | { | ||
479 | split->reparent(this, 0, QPoint(0, 0) ); | ||
480 | split->setTabWidget( tab ); | ||
481 | } | ||
482 | |||
483 | |||
484 | delete m_hbox; | ||
485 | m_hbox = 0; | ||
486 | if (!m_tabWidget ) | ||
487 | return; | ||
488 | |||
489 | m_tabWidget->setGeometry( frameRect() ); | ||
490 | m_tabWidget->show(); | ||
491 | |||
492 | } | ||
493 | |||
494 | /* | ||
495 | * changes over to a box | ||
496 | * this is recursive as well | ||
497 | */ | ||
498 | void OSplitter::changeHBox() | ||
499 | { | ||
500 | if (m_hbox ) | ||
501 | { | ||
502 | m_hbox->setGeometry( frameRect() ); | ||
503 | return; | ||
504 | } | ||
505 | |||
506 | qWarning("new HBox %s", name() ); | ||
507 | m_hbox = new QHBox( this ); | ||
508 | commonChangeBox(); | ||
509 | } | ||
510 | |||
511 | void OSplitter::changeVBox() | ||
512 | { | ||
513 | if (m_hbox ) | ||
514 | { | ||
515 | m_hbox->setGeometry( frameRect() ); | ||
516 | return; | ||
517 | } | ||
518 | |||
519 | qWarning("New VBOX %s", name() ); | ||
520 | m_hbox = new QVBox( this ); | ||
521 | |||
522 | commonChangeBox(); | ||
523 | |||
524 | } | ||
525 | |||
526 | /* | ||
527 | * common box code | ||
528 | * first remove and add children | ||
529 | * the other splitters | ||
530 | * it is recursive as well due the call to setTabWidget | ||
531 | */ | ||
532 | void OSplitter::commonChangeBox() | ||
533 | { | ||
534 | qWarning(" Name of Splitters is %s", name() ); | ||
535 | |||
536 | for (ContainerList::Iterator it = m_container.begin(); it != m_container.end(); ++it ) | ||
537 | { | ||
538 | /* only if parent tab.. m_tabWidgets gets deleted and would do that as well */ | ||
539 | if (m_parentTab ) | ||
540 | removeFromTab( (*it).widget ); | ||
541 | qWarning("Adding to box %s", (*it).name.latin1() ); | ||
542 | addToBox( (*it) ); | ||
543 | } | ||
544 | for ( OSplitter* split = m_splitter.first(); split; split = m_splitter.next() ) | ||
545 | { | ||
546 | /* tell them the world had changed */ | ||
547 | split->setTabWidget( 0 ); | ||
548 | Opie::OSplitterContainer con; | ||
549 | con.widget = split; | ||
550 | // con.widget = split->m_tabWidget ? static_cast<QWidget*>(split->m_tabWidget) | ||
551 | // : static_cast<QWidget*>(split->m_hbox); | ||
552 | addToBox( con ); | ||
553 | } | ||
554 | |||
555 | |||
556 | |||
557 | if (m_parentTab ) | ||
558 | m_parentTab->addTab(m_hbox, iconName(), label() ); | ||
559 | else | ||
560 | { | ||
561 | qWarning(" setting Box geometry for %s", name() ); | ||
562 | m_hbox->setGeometry( frameRect() ); | ||
563 | m_hbox->show(); | ||
564 | delete m_tabWidget; | ||
565 | m_tabWidget = 0; | ||
566 | show(); // also show this widget | ||
567 | } | ||
568 | } | ||
569 | |||
570 | /* | ||
571 | * sets the tabwidget, removes tabs, and relayouts the widget | ||
572 | */ | ||
573 | void OSplitter::setTabWidget( OTabWidget* wid) | ||
574 | { | ||
575 | /* clean up cause m_parentTab will not be available for us */ | ||
576 | if ( m_parentTab ) | ||
577 | { | ||
578 | if (m_hbox ) | ||
579 | m_parentTab->removePage( m_hbox ); | ||
580 | else if (!m_container.isEmpty() ) | ||
581 | { | ||
582 | ContainerList::Iterator it = m_container.begin(); | ||
583 | for ( ; it != m_container.end(); ++it ) | ||
584 | m_parentTab->removePage( (*it).widget ); | ||
585 | } | ||
586 | } | ||
587 | /* the parent Splitter changed so either make us indepent or dep */ | ||
588 | |||
589 | m_parentTab = wid; | ||
590 | |||
591 | QWidget *tab = m_tabWidget; | ||
592 | QWidget *box = m_hbox; | ||
593 | m_hbox = 0; m_tabWidget = 0; | ||
594 | |||
595 | if ( layoutMode() ) | ||
596 | changeTab(); | ||
597 | else if (m_orient == Horizontal ) | ||
598 | changeHBox(); | ||
599 | else | ||
600 | changeVBox(); | ||
601 | |||
602 | /* our own crap is added and children from change* */ | ||
603 | delete tab; | ||
604 | delete box; | ||
605 | } | ||
606 | |||
607 | #if 0 | ||
608 | void OSplitter::reparentAll() | ||
609 | { | ||
610 | if (m_container.isEmpty() ) | ||
611 | return; | ||
612 | |||
613 | ContainerList::Iterator it = m_container.begin(); | ||
614 | for ( ; it != m_container.end(); ++it ) | ||
615 | (*it).wid->reparent(0, 0, QPoint(0, 0) ); | ||
616 | |||
617 | |||
618 | } | ||
619 | #endif | ||
620 | |||
621 | /** | ||
622 | * @internal | ||
623 | */ | ||
624 | bool OSplitter::layoutMode()const | ||
625 | { | ||
626 | if ( size().width() > m_size_policy && | ||
627 | m_orient == Horizontal ) | ||
628 | { | ||
629 | return false; | ||
630 | } | ||
631 | else if ( size().height() > m_size_policy && | ||
632 | m_orient == Vertical ) | ||
633 | { | ||
634 | return false; | ||
635 | } | ||
636 | |||
637 | return true; | ||
638 | } | ||
diff --git a/libopie2/opieui/big-screen/osplitter.h b/libopie2/opieui/big-screen/osplitter.h new file mode 100644 index 0000000..2daae7f --- a/dev/null +++ b/libopie2/opieui/big-screen/osplitter.h | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | =. This file is part of the OPIE Project | ||
3 | .=l. Copyright (c) 2003 hOlgAr <zecke@handhelds.org> | ||
4 | .>+-= | ||
5 | _;:, .> :=|. This library is free software; you can | ||
6 | .> <`_, > . <= redistribute it and/or modify it under | ||
7 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public | ||
8 | .="- .-=="i, .._ License as published by the Free Software | ||
9 | - . .-<_> .<> Foundation; either version 2 of the License, | ||
10 | ._= =} : or (at your option) any later version. | ||
11 | .%`+i> _;_. | ||
12 | .i_,=:_. -<s. This library is distributed in the hope that | ||
13 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; | ||
14 | : .. .:, . . . without even the implied warranty of | ||
15 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A | ||
16 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU | ||
17 | ..}^=.= = ; Library General Public License for more | ||
18 | ++= -. .` .: details. | ||
19 | : = ...= . :.=- | ||
20 | -. .:....=;==+<; You should have received a copy of the GNU | ||
21 | -_. . . )=. = Library General Public License along with | ||
22 | -- :-=` this library; see the file COPYING.LIB. | ||
23 | If not, write to the Free Software Foundation, | ||
24 | Inc., 59 Temple Place - Suite 330, | ||
25 | Boston, MA 02111-1307, USA. | ||
26 | |||
27 | */ | ||
28 | |||
29 | #ifndef OSPLITTER_H | ||
30 | #define OSPLITTER_H | ||
31 | |||
32 | #include "obigscreen_p.h" | ||
33 | |||
34 | /* QT */ | ||
35 | #include <qframe.h> | ||
36 | #include <qlist.h> | ||
37 | #include <qstring.h> | ||
38 | #include <qvaluelist.h> | ||
39 | |||
40 | class QHBox; | ||
41 | |||
42 | //template class QValueList<Opie::OSplitterContainer>; | ||
43 | |||
44 | /* | ||
45 | * TODO | ||
46 | * -check API docu | ||
47 | * -one more example | ||
48 | * -allow inserting at a position | ||
49 | */ | ||
50 | |||
51 | namespace Opie | ||
52 | { | ||
53 | class OTabWidget; | ||
54 | |||
55 | /** | ||
56 | * | ||
57 | * If you've widgets that could be placed side by side but you think | ||
58 | * on small resolutions is not enough place but it would really make sense | ||
59 | * on bigger resolutions this class will help you. | ||
60 | * You can add as many widgets you want to it. Set a poliy on which width/height it | ||
61 | * should switch the layout. | ||
62 | * You can either say to place widgets vertical or horizontal. | ||
63 | * This class uses QHBox, QVBox and QTAbWidget internally. | ||
64 | * OSplitter takes ownership of the widgets | ||
65 | * | ||
66 | * @since 1.2 | ||
67 | * | ||
68 | * @short a small dynamically changing its layout to store two or more widgets side by side | ||
69 | * @version 0.1 | ||
70 | * @author zecke | ||
71 | */ | ||
72 | class OSplitter : public QFrame | ||
73 | { | ||
74 | Q_OBJECT | ||
75 | public: | ||
76 | typedef QValueList<Opie::OSplitterContainer> ContainerList; | ||
77 | OSplitter( Qt::Orientation = Horizontal, QWidget *parent = 0, | ||
78 | const char* name = 0, WFlags fl = 0 ); | ||
79 | ~OSplitter(); | ||
80 | |||
81 | void setLabel( const QString& name ); | ||
82 | void setIconName( const QString& name ); | ||
83 | QString label()const; | ||
84 | QString iconName()const; | ||
85 | |||
86 | void setSizeChange( int width_height ); | ||
87 | |||
88 | void addWidget( OSplitter* splitter ); | ||
89 | void addWidget( QWidget* wid, const QString& icon, const QString& label ); | ||
90 | void removeWidget( QWidget* ); | ||
91 | void removeWidget( OSplitter* ); | ||
92 | |||
93 | void setCurrentWidget( QWidget* ); | ||
94 | void setCurrentWidget( const QString& label ); | ||
95 | void setCurrentWidget( int ); | ||
96 | QWidget* currentWidget()const; | ||
97 | |||
98 | |||
99 | signals: | ||
100 | /** | ||
101 | * Emitted if in tab and comes directly from the tab widget | ||
102 | * | ||
103 | */ | ||
104 | void currentChanged( QWidget* ); | ||
105 | |||
106 | /** | ||
107 | * emitted whenever a border is crossed | ||
108 | * true if in small screen mode | ||
109 | * false if in bigscreen | ||
110 | * this signal is emitted after the layout switch | ||
111 | * @param b The layout mode | ||
112 | * @param ori The orientation | ||
113 | */ | ||
114 | void sizeChanged( bool b, Orientation ori); | ||
115 | public: | ||
116 | // QSize sizeHint()const; | ||
117 | // QSize minimumSizeHint()const; | ||
118 | |||
119 | protected: | ||
120 | void resizeEvent( QResizeEvent* ); | ||
121 | |||
122 | private: | ||
123 | /* true if OTabMode */ | ||
124 | bool layoutMode()const; | ||
125 | // void reparentAll(); | ||
126 | void setTabWidget( OTabWidget*); | ||
127 | void addToTab( const Opie::OSplitterContainer& ); | ||
128 | void addToBox( const Opie::OSplitterContainer& ); | ||
129 | void removeFromTab( QWidget* ); | ||
130 | void changeTab(); | ||
131 | void changeHBox(); | ||
132 | void changeVBox(); | ||
133 | void commonChangeBox(); | ||
134 | QHBox *m_hbox; | ||
135 | OTabWidget *m_tabWidget; | ||
136 | OTabWidget *m_parentTab; | ||
137 | Orientation m_orient; | ||
138 | int m_size_policy; | ||
139 | |||
140 | ContainerList m_container; | ||
141 | QList<OSplitter> m_splitter; | ||
142 | |||
143 | QString m_icon, m_name; | ||
144 | |||
145 | struct Private; | ||
146 | Private *d; | ||
147 | }; | ||
148 | }; | ||
149 | |||
150 | #endif | ||
diff --git a/libopie2/opieui/big-screen/owidgetstack.cpp b/libopie2/opieui/big-screen/owidgetstack.cpp new file mode 100644 index 0000000..57e97e3 --- a/dev/null +++ b/libopie2/opieui/big-screen/owidgetstack.cpp | |||
@@ -0,0 +1,435 @@ | |||
1 | /* | ||
2 | =. This file is part of the OPIE Project | ||
3 | .=l. Copyright (c) 2003 hOlgAr <zecke@handhelds.org> | ||
4 | .>+-= | ||
5 | _;:, .> :=|. This library is free software; you can | ||
6 | .> <`_, > . <= redistribute it and/or modify it under | ||
7 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public | ||
8 | .="- .-=="i, .._ License as published by the Free Software | ||
9 | - . .-<_> .<> Foundation; either version 2 of the License, | ||
10 | ._= =} : or (at your option) any later version. | ||
11 | .%`+i> _;_. | ||
12 | .i_,=:_. -<s. This library is distributed in the hope that | ||
13 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; | ||
14 | : .. .:, . . . without even the implied warranty of | ||
15 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A | ||
16 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU | ||
17 | ..}^=.= = ; Library General Public License for more | ||
18 | ++= -. .` .: details. | ||
19 | : = ...= . :.=- | ||
20 | -. .:....=;==+<; You should have received a copy of the GNU | ||
21 | -_. . . )=. = Library General Public License along with | ||
22 | -- :-=` this library; see the file COPYING.LIB. | ||
23 | If not, write to the Free Software Foundation, | ||
24 | Inc., 59 Temple Place - Suite 330, | ||
25 | Boston, MA 02111-1307, USA. | ||
26 | |||
27 | */ | ||
28 | |||
29 | #include "owidgetstack.h" | ||
30 | |||
31 | /* QT */ | ||
32 | #include <qapplication.h> | ||
33 | #include <qwidgetstack.h> | ||
34 | |||
35 | namespace { | ||
36 | const int mode_size = 330; | ||
37 | } | ||
38 | |||
39 | using namespace Opie; | ||
40 | |||
41 | /** | ||
42 | * This is the standard widget. For simple usage see the example. Normally this widget | ||
43 | * is the central widget of a QMainWindow. | ||
44 | * Use removeWidget before you delete a widget yourself. OWidgetStack does not | ||
45 | * yet recognize removal of children. | ||
46 | * | ||
47 | * @param parent The parent widget. It maybe 0 but then you need to take care of deletion. | ||
48 | * Or you use QPEApplication::showMainWidget(). | ||
49 | * @param name Name will be passed on to QObject | ||
50 | * @param fl Additional window flags passed to QFrame. see @Qt::WFlags | ||
51 | */ | ||
52 | OWidgetStack::OWidgetStack( QWidget* parent, const char* name, WFlags fl) | ||
53 | : QFrame( parent, name, fl ) | ||
54 | { | ||
55 | m_last = m_mWidget = 0; | ||
56 | m_forced = false; | ||
57 | |||
58 | QApplication::desktop()->installEventFilter( this ); | ||
59 | setFontPropagation ( AllChildren ); | ||
60 | setPalettePropagation( AllChildren ); | ||
61 | |||
62 | /* sets m_mode and initializes more */ | ||
63 | /* if you change this call change switchTop as well */ | ||
64 | m_stack = 0; | ||
65 | switchStack(); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * The destructor. It deletes also all added widgets. | ||
70 | * | ||
71 | */ | ||
72 | OWidgetStack::~OWidgetStack() { | ||
73 | if (m_mode == BigScreen && !m_list.isEmpty() ) { | ||
74 | QMap<int, QWidget*>::Iterator it = m_list.begin(); | ||
75 | for ( ; it != m_list.end(); ++it ) | ||
76 | delete it.data(); | ||
77 | } | ||
78 | m_list.clear(); | ||
79 | |||
80 | } | ||
81 | |||
82 | /** | ||
83 | * return the mode of the desktop. There are currently two modes. SmallScreen | ||
84 | * with a normal PDA resolution and BigScreen with resolutions greater than | ||
85 | * 330 for width and height. | ||
86 | * You can also force the mode this widget is in with forceMode() | ||
87 | * Note that NoForce will be never returned from here | ||
88 | */ | ||
89 | enum OWidgetStack::Mode OWidgetStack::mode()const { | ||
90 | return m_mode; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * You can also force one of the modes and then | ||
95 | * this widget stops on listening to size changes. You | ||
96 | * can revert to the scanning behaviour by setting mode | ||
97 | * to NoForce | ||
98 | */ | ||
99 | void OWidgetStack::forceMode( enum Mode mode) { | ||
100 | m_forced = mode != NoForce; | ||
101 | |||
102 | /* we need to see which mode we're in */ | ||
103 | if (!m_forced ) { | ||
104 | if ( QApplication::desktop()->width() >= | ||
105 | mode_size ) | ||
106 | mode = BigScreen; | ||
107 | else | ||
108 | mode = SmallScreen; | ||
109 | } | ||
110 | switch( mode ) { | ||
111 | case NoForce: | ||
112 | case SmallScreen: | ||
113 | switchStack(); | ||
114 | break; | ||
115 | case BigScreen: | ||
116 | switchTop(); | ||
117 | break; | ||
118 | |||
119 | } | ||
120 | |||
121 | m_mode = mode; | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * Adds a widget to the stack. The first widget added is considered | ||
126 | * to be the mainwindow. This is important because if Opie is in | ||
127 | * BigScreen mode the sizeHint of the MainWindow will be returned. | ||
128 | * In Small Screen the sizeHint of the QWidgetStack is returned. | ||
129 | * See QWidgetStack::sizeHint. | ||
130 | * This widget takes ownership of the widget and may even reparent. | ||
131 | * All windows will be hidden | ||
132 | * | ||
133 | * @param wid The QWidget to be added | ||
134 | * @param id An ID for the Widget. If the ID is duplicated the | ||
135 | last set widget will be related to the id | ||
136 | * | ||
137 | */ | ||
138 | void OWidgetStack::addWidget( QWidget* wid, int id) { | ||
139 | if (!wid) | ||
140 | return; | ||
141 | |||
142 | /* set our main widget */ | ||
143 | if (!m_mWidget) | ||
144 | m_mWidget = wid; | ||
145 | |||
146 | m_list.insert( id, wid ); | ||
147 | |||
148 | /** | ||
149 | * adding does not raise any widget | ||
150 | * But for our mainwidget we prepare | ||
151 | * the right position with the right parent | ||
152 | */ | ||
153 | if (m_mode == SmallScreen ) | ||
154 | m_stack->addWidget( wid,id ); | ||
155 | else if ( m_mWidget == wid ) { | ||
156 | wid->reparent(this, 0, contentsRect().topLeft() ); | ||
157 | wid->hide(); | ||
158 | }else { | ||
159 | wid->reparent(0, WType_TopLevel, QPoint(10, 10) ); | ||
160 | wid->hide(); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | |||
165 | /** | ||
166 | * Remove the widget from the stack it'll be reparented to 0 | ||
167 | * and ownership is dropped. You need to delete it. | ||
168 | * If the removed widget was the mainwindow consider | ||
169 | * to call setMainWindow. | ||
170 | * | ||
171 | * @param wid The QWidget to be removed | ||
172 | */ | ||
173 | void OWidgetStack::removeWidget( QWidget* wid) { | ||
174 | if (!wid) | ||
175 | return; | ||
176 | |||
177 | if (m_mode == SmallScreen ) | ||
178 | m_stack->removeWidget( wid ); | ||
179 | |||
180 | |||
181 | wid->reparent(0, 0, QPoint(0, 0) ); | ||
182 | m_list.remove( id(wid) ); | ||
183 | |||
184 | if ( wid == m_mWidget ) | ||
185 | m_mWidget = 0; | ||
186 | } | ||
187 | |||
188 | #if 0 | ||
189 | /** | ||
190 | * @internal_resons | ||
191 | */ | ||
192 | QSizeHint OWidgetStack::sizeHint()const { | ||
193 | |||
194 | } | ||
195 | |||
196 | /** | ||
197 | * @internal_reasons | ||
198 | */ | ||
199 | QSizeHint OWidgetStack::minimumSizeHint()const { | ||
200 | |||
201 | } | ||
202 | #endif | ||
203 | |||
204 | /** | ||
205 | * This function tries to find the widget with the id. | ||
206 | * You supplied a possible id in addWIdget. Note that not | ||
207 | * QWidget::winId() is used. | ||
208 | * | ||
209 | * @param id The id to search for | ||
210 | * | ||
211 | * @return The widget or null | ||
212 | * @see addWidget | ||
213 | */ | ||
214 | QWidget* OWidgetStack::widget( int id) const { | ||
215 | return m_list[id]; | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * Tries to find the assigned id for the widget | ||
220 | * or returns -1 if no widget could be found | ||
221 | * @param wid The widget to look for | ||
222 | */ | ||
223 | int OWidgetStack::id( QWidget* wid)const{ | ||
224 | if (m_list.isEmpty() ) | ||
225 | return -1; | ||
226 | |||
227 | QMap<int, QWidget*>::ConstIterator it = m_list.begin(); | ||
228 | for ( ; it != m_list.end(); ++it ) | ||
229 | if ( it.data() == wid ) | ||
230 | break; | ||
231 | |||
232 | /* if not at the end return the key */ | ||
233 | return it == m_list.end() ? -1 : it.key(); | ||
234 | } | ||
235 | |||
236 | |||
237 | /** | ||
238 | * This function returns the currently visible | ||
239 | * widget. In BigScreen mode the mainwindow | ||
240 | * is returned | ||
241 | */ | ||
242 | QWidget* OWidgetStack::visibleWidget()const { | ||
243 | if (m_mode == SmallScreen ) | ||
244 | return m_stack->visibleWidget(); | ||
245 | else | ||
246 | return m_mWidget; | ||
247 | |||
248 | } | ||
249 | |||
250 | /** | ||
251 | * This method raises the widget wit the specefic id. | ||
252 | * Note that in BigScreen mode the widget is made visible | ||
253 | * but the other ( previous) visible widget(s) will not | ||
254 | * be made invisible. If you need this use hideWidget(). | ||
255 | * | ||
256 | * @param id Raise the widget with id | ||
257 | */ | ||
258 | void OWidgetStack::raiseWidget( int id) { | ||
259 | return raiseWidget( widget( id ) ); | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * This is an overloaded function and only differs in its parameters. | ||
264 | * @see raiseWidget( int ) | ||
265 | */ | ||
266 | void OWidgetStack::raiseWidget( QWidget* wid) { | ||
267 | m_last = wid; | ||
268 | if (m_mode == SmallScreen ) | ||
269 | m_stack->raiseWidget( wid ); | ||
270 | else { | ||
271 | int ide; | ||
272 | emit aboutToShow( wid ); | ||
273 | /* if someone is connected and the widget is actually available */ | ||
274 | if ( receivers( SIGNAL(aboutToShow(int) ) ) && | ||
275 | ( (ide = id( wid ) ) != -1 ) ) | ||
276 | emit aboutToShow( ide ); | ||
277 | |||
278 | /* ### FIXME PLACE THE WIDGET right */ | ||
279 | wid->show(); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | /** | ||
284 | * This will hide the currently visible widget | ||
285 | * and raise the widget specified by the parameter. | ||
286 | * Note that this method does not use visibleWIdget but remembers | ||
287 | * the last raisedWidget | ||
288 | */ | ||
289 | void OWidgetStack::hideWidget( int id) { | ||
290 | /* hiding our main widget wouldn't be smart */ | ||
291 | if ( m_mode == BigScreen && m_last != m_mWidget ) | ||
292 | m_last->hide(); | ||
293 | raiseWidget( id ); | ||
294 | } | ||
295 | |||
296 | /** | ||
297 | * This is overloaded and only differs in the parameters | ||
298 | * it takes. | ||
299 | */ | ||
300 | void OWidgetStack::hideWidget( QWidget* wid) { | ||
301 | /* still not smart */ | ||
302 | if ( m_mode == BigScreen && m_last != m_mWidget ) | ||
303 | m_last->hide(); | ||
304 | |||
305 | raiseWidget( wid ); | ||
306 | } | ||
307 | |||
308 | |||
309 | bool OWidgetStack::eventFilter( QObject* obj, QEvent* e) { | ||
310 | qWarning(" %s %s", obj->name(), obj->className() ); | ||
311 | if ( e->type() == QEvent::Resize ) { | ||
312 | QResizeEvent *res = static_cast<QResizeEvent*>( e ); | ||
313 | QSize size = res->size(); | ||
314 | if ( size.width() >= mode_size ) | ||
315 | switchTop(); | ||
316 | else | ||
317 | switchStack(); | ||
318 | } | ||
319 | return false; | ||
320 | } | ||
321 | |||
322 | |||
323 | /** | ||
324 | * @internal_resons | ||
325 | */ | ||
326 | void OWidgetStack::resizeEvent( QResizeEvent* ev ) { | ||
327 | QFrame::resizeEvent( ev ); | ||
328 | if (m_mode == SmallScreen ) | ||
329 | m_stack->setGeometry( frameRect() ); | ||
330 | else | ||
331 | if (m_mWidget ) | ||
332 | m_mWidget->setGeometry( frameRect() ); | ||
333 | |||
334 | } | ||
335 | |||
336 | /** | ||
337 | * setMainWindow gives the OWidgetStack a hint which | ||
338 | * window should always stay inside the stack. | ||
339 | * Normally the first added widget is considered to be | ||
340 | * the mainwindow but you can change this with this | ||
341 | * function. | ||
342 | * If in BigScreen mode the current mainwindow will be reparented | ||
343 | * and hidden. The position will be taken by the new one. | ||
344 | * If the old MainWindow was hidden the new window will | ||
345 | * also be hidden. If the window was visible the new mainwindow | ||
346 | * will be made visible too and the old one hidden. If there | ||
347 | * was no mainwindow it will be hidden as well. | ||
348 | * | ||
349 | * @param wid The new mainwindow | ||
350 | */ | ||
351 | void OWidgetStack::setMainWindow( QWidget* wid ) { | ||
352 | if (m_mode == BigScreen ) { | ||
353 | bool wasVisible = false; | ||
354 | if (m_mWidget ) { | ||
355 | wasVisible = !m_mWidget->isHidden(); | ||
356 | /* hidden by default */ | ||
357 | m_mWidget->reparent(0, WType_TopLevel, QPoint(10, 10) ); | ||
358 | } | ||
359 | wid->reparent(this, 0, frameRect().topLeft() ); | ||
360 | |||
361 | if (wasVisible) | ||
362 | wid->show(); | ||
363 | } | ||
364 | |||
365 | m_mWidget = wid; | ||
366 | } | ||
367 | |||
368 | /** | ||
369 | * this is an overloaded member and only differs | ||
370 | * in the type of arguments. | ||
371 | * @see setMainWindow(QWidget*) | ||
372 | */ | ||
373 | void OWidgetStack::setMainWindow( int id) { | ||
374 | setMainWindow( widget( id ) ); | ||
375 | } | ||
376 | |||
377 | |||
378 | /* | ||
379 | * this function switches to a stack ;) | ||
380 | */ | ||
381 | void OWidgetStack::switchStack() { | ||
382 | if (m_stack ) { | ||
383 | m_stack->setGeometry( frameRect() ); | ||
384 | return; | ||
385 | } | ||
386 | |||
387 | m_mode = SmallScreen; | ||
388 | m_stack = new QWidgetStack(this); | ||
389 | |||
390 | connect(m_stack, SIGNAL(aboutToShow(QWidget*) ), | ||
391 | this, SIGNAL(aboutToShow(QWidget*) ) ); | ||
392 | connect(m_stack, SIGNAL(aboutToShow(int) ), | ||
393 | this, SIGNAL(aboutToShow(int) ) ); | ||
394 | |||
395 | /* now reparent the widgets... luckily QWidgetSatck does most of the work */ | ||
396 | if (m_list.isEmpty() ) | ||
397 | return; | ||
398 | |||
399 | QMap<int, QWidget*>::Iterator it = m_list.begin(); | ||
400 | for ( ; it != m_list.end(); ++it ) | ||
401 | m_stack->addWidget( it.data(), it.key() ); | ||
402 | |||
403 | |||
404 | } | ||
405 | |||
406 | /* | ||
407 | * we will switch to top level mode | ||
408 | * reparent the list of widgets and then delete the stack | ||
409 | */ | ||
410 | void OWidgetStack::switchTop() { | ||
411 | m_mode = BigScreen; | ||
412 | /* this works because it is guaranteed that switchStack was called at least once*/ | ||
413 | if (!m_stack && m_mWidget) { | ||
414 | m_mWidget->setGeometry( frameRect() ); | ||
415 | return; | ||
416 | }else if (!m_stack) | ||
417 | return; | ||
418 | |||
419 | if (!m_list.isEmpty() ) { | ||
420 | QMap<int, QWidget*>::Iterator it = m_list.begin(); | ||
421 | for ( ; it != m_list.end(); ++it ) { | ||
422 | /* better than reparenting twice */ | ||
423 | if ( it.data() == m_mWidget ) { | ||
424 | m_mWidget->reparent(this, 0, frameRect().topLeft() ); | ||
425 | m_mWidget->setGeometry( frameRect() ); | ||
426 | m_mWidget->show(); | ||
427 | }else | ||
428 | /* ### FIXME we need to place the widget better */ | ||
429 | it.data()->reparent(0, WType_TopLevel, QPoint(10, 10) ); | ||
430 | } | ||
431 | } | ||
432 | |||
433 | delete m_stack; | ||
434 | m_stack = 0; | ||
435 | } | ||
diff --git a/libopie2/opieui/big-screen/owidgetstack.h b/libopie2/opieui/big-screen/owidgetstack.h new file mode 100644 index 0000000..53818c8 --- a/dev/null +++ b/libopie2/opieui/big-screen/owidgetstack.h | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | =. This file is part of the OPIE Project | ||
3 | .=l. Copyright (c) 2003 hOlgAr <zecke@handhelds.org> | ||
4 | .>+-= | ||
5 | _;:, .> :=|. This library is free software; you can | ||
6 | .> <`_, > . <= redistribute it and/or modify it under | ||
7 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public | ||
8 | .="- .-=="i, .._ License as published by the Free Software | ||
9 | - . .-<_> .<> Foundation; either version 2 of the License, | ||
10 | ._= =} : or (at your option) any later version. | ||
11 | .%`+i> _;_. | ||
12 | .i_,=:_. -<s. This library is distributed in the hope that | ||
13 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; | ||
14 | : .. .:, . . . without even the implied warranty of | ||
15 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A | ||
16 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU | ||
17 | ..}^=.= = ; Library General Public License for more | ||
18 | ++= -. .` .: details. | ||
19 | : = ...= . :.=- | ||
20 | -. .:....=;==+<; You should have received a copy of the GNU | ||
21 | -_. . . )=. = Library General Public License along with | ||
22 | -- :-=` this library; see the file COPYING.LIB. | ||
23 | If not, write to the Free Software Foundation, | ||
24 | Inc., 59 Temple Place - Suite 330, | ||
25 | Boston, MA 02111-1307, USA. | ||
26 | |||
27 | */ | ||
28 | |||
29 | #ifndef OWIDGETSTACK_H | ||
30 | #define OWIDGETSTACK_H | ||
31 | |||
32 | /* QT*/ | ||
33 | #include <qframe.h> | ||
34 | #include <qmap.h> | ||
35 | |||
36 | class QWidgetStack; | ||
37 | |||
38 | namespace Opie | ||
39 | { | ||
40 | /** | ||
41 | * | ||
42 | * OWidgetStack is the answer to the problem of using Opie at different screen | ||
43 | * sizes and to have a different behaviour. Most applications use a QWidgetStack | ||
44 | * to supply a view on click. And by clicking the (X) you go back but this | ||
45 | * behaviour feels strange on bigger screens. It's ok on smaller one because | ||
46 | * one can't determine the difference. | ||
47 | * This stack reads the default out of the size of the desktop widget but | ||
48 | * can be forced to have either the one or the other behaviour. | ||
49 | * The first widget added is considered the 'main' widget and its | ||
50 | * sizeHint will be taking if in BigScreen mode. | ||
51 | * In small screen mode this widget behaves exactly like a QWidgetStack and in BigScreen | ||
52 | * mode it'll use the MainWindow as child of this widget and arranges the others as | ||
53 | * hidden top level widgets. | ||
54 | * | ||
55 | * @version 0.1 | ||
56 | * @author hOlgAr F. | ||
57 | * @short Either a true stack or a list of top Level widgets | ||
58 | */ | ||
59 | class OWidgetStack : public QFrame { | ||
60 | Q_OBJECT | ||
61 | public: | ||
62 | enum Mode { SmallScreen, BigScreen, NoForce }; | ||
63 | OWidgetStack( QWidget* parent, const char* name = 0, WFlags fl = 0 ); | ||
64 | ~OWidgetStack(); | ||
65 | |||
66 | enum Mode mode()const; | ||
67 | void forceMode( enum Mode ); | ||
68 | |||
69 | void addWidget( QWidget* , int ); | ||
70 | void removeWidget( QWidget* ); | ||
71 | |||
72 | // QSizeHint sizeHint()const; | ||
73 | // QSizeHint minimumSizeHint()const; | ||
74 | |||
75 | QWidget *widget( int )const; | ||
76 | int id( QWidget* )const; | ||
77 | |||
78 | |||
79 | |||
80 | QWidget* visibleWidget() const; | ||
81 | |||
82 | bool eventFilter( QObject*, QEvent* ); | ||
83 | signals: | ||
84 | /** | ||
85 | * OWidgetStack monitors the Desktop Widget for | ||
86 | * size changes if it recignizes a change size it'll | ||
87 | * send a signal and adjust its mode. After the signal | ||
88 | * was emitted. During the signal a call to mode() the | ||
89 | * old mode will be returned. Note that if a size change happens | ||
90 | * but no modeChange no signal will be emitted | ||
91 | * | ||
92 | * | ||
93 | * @param mode The new mode of the desktop | ||
94 | */ | ||
95 | void modeChanged( enum Mode mode); | ||
96 | |||
97 | /** | ||
98 | * These two signals are emitted whenever we're about to | ||
99 | * show one of the widgets | ||
100 | */ | ||
101 | void aboutToShow( QWidget* ); | ||
102 | void aboutToShow( int ); | ||
103 | |||
104 | public slots: | ||
105 | void raiseWidget( int ); | ||
106 | void raiseWidget( QWidget* ); | ||
107 | void hideWidget( int ); | ||
108 | void hideWidget( QWidget* ); | ||
109 | void setMainWindow( QWidget* ); | ||
110 | void setMainWindow( int ); | ||
111 | |||
112 | protected: | ||
113 | void resizeEvent( QResizeEvent* ); | ||
114 | |||
115 | private: | ||
116 | void switchStack(); | ||
117 | void switchTop(); | ||
118 | QMap<int, QWidget*> m_list; | ||
119 | QWidgetStack *m_stack; | ||
120 | QWidget *m_mWidget; | ||
121 | QWidget *m_last; | ||
122 | |||
123 | enum Mode m_mode; | ||
124 | bool m_forced : 1; | ||
125 | |||
126 | struct Private; | ||
127 | Private *d; | ||
128 | }; | ||
129 | |||
130 | }; | ||
131 | |||
132 | #endif | ||
diff --git a/libopie2/opieui/opieui.pro b/libopie2/opieui/opieui.pro index b9bf203..b07976b 100644 --- a/libopie2/opieui/opieui.pro +++ b/libopie2/opieui/opieui.pro | |||
@@ -47,6 +47,8 @@ SOURCES = ocheckitem.cpp \ | |||
47 | otaskbarapplet.cpp \ | 47 | otaskbarapplet.cpp \ |
48 | oseparator.cpp | 48 | oseparator.cpp |
49 | 49 | ||
50 | include ( big-screen/big-screen.pro ) | ||
51 | |||
50 | INTERFACES = otimepickerbase.ui | 52 | INTERFACES = otimepickerbase.ui |
51 | 53 | ||
52 | TARGET = opieui2 | 54 | TARGET = opieui2 |