Diffstat (limited to 'libopie2/opieui/big-screen/owidgetstack.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libopie2/opieui/big-screen/owidgetstack.cpp | 435 |
1 files changed, 435 insertions, 0 deletions
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 | } | ||