author | mickeyl <mickeyl> | 2003-03-28 15:11:52 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2003-03-28 15:11:52 (UTC) |
commit | 11304d02942e9fa493e4e80943a828f9c65f6772 (patch) (unidiff) | |
tree | a0223c10c067e1afc70d15c2b82be3f3c15e41ae /libopie2/qt3/opieui/ocompletionbox.cpp | |
parent | b271d575fa05cf570a1a829136517761bd47e69b (diff) | |
download | opie-11304d02942e9fa493e4e80943a828f9c65f6772.zip opie-11304d02942e9fa493e4e80943a828f9c65f6772.tar.gz opie-11304d02942e9fa493e4e80943a828f9c65f6772.tar.bz2 |
skeleton and the start of libopie2, please read README, ROADMAP and STATUS and comment...
Diffstat (limited to 'libopie2/qt3/opieui/ocompletionbox.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libopie2/qt3/opieui/ocompletionbox.cpp | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/libopie2/qt3/opieui/ocompletionbox.cpp b/libopie2/qt3/opieui/ocompletionbox.cpp new file mode 100644 index 0000000..b594b8e --- a/dev/null +++ b/libopie2/qt3/opieui/ocompletionbox.cpp | |||
@@ -0,0 +1,408 @@ | |||
1 | /* | ||
2 | This file Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de> | ||
3 | is part of the Copyright (C) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org> | ||
4 | Opie Project Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de> | ||
5 | Copyright (C) 2000,2001 Dawit Alemayehu <adawit@kde.org> | ||
6 | =. | ||
7 | .=l. Originally part of the KDE Project | ||
8 | .>+-= | ||
9 | _;:, .> :=|. This program is free software; you can | ||
10 | .> <`_, > . <= redistribute it and/or modify it under | ||
11 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public | ||
12 | .="- .-=="i, .._ License as published by the Free Software | ||
13 | - . .-<_> .<> Foundation; either version 2 of the License, | ||
14 | ._= =} : or (at your option) any later version. | ||
15 | .%`+i> _;_. | ||
16 | .i_,=:_. -<s. This program is distributed in the hope that | ||
17 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; | ||
18 | : .. .:, . . . without even the implied warranty of | ||
19 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A | ||
20 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU | ||
21 | ..}^=.= = ; Library General Public License for more | ||
22 | ++= -. .` .: details. | ||
23 | : = ...= . :.=- | ||
24 | -. .:....=;==+<; You should have received a copy of the GNU | ||
25 | -_. . . )=. = Library General Public License along with | ||
26 | -- :-=` this library; see the file COPYING.LIB. | ||
27 | If not, write to the Free Software Foundation, | ||
28 | Inc., 59 Temple Place - Suite 330, | ||
29 | Boston, MA 02111-1307, USA. | ||
30 | |||
31 | */ | ||
32 | |||
33 | #include <qapplication.h> | ||
34 | #include <qevent.h> | ||
35 | #include <qstyle.h> | ||
36 | |||
37 | #include <opie2/ocompletionbox.h> | ||
38 | |||
39 | #define OListBox QListBox | ||
40 | |||
41 | class OCompletionBox::OCompletionBoxPrivate | ||
42 | { | ||
43 | public: | ||
44 | QWidget *m_parent; // necessary to set the focus back | ||
45 | QString cancelText; | ||
46 | bool tabHandling; | ||
47 | bool down_workaround; | ||
48 | }; | ||
49 | |||
50 | OCompletionBox::OCompletionBox( QWidget *parent, const char *name ) | ||
51 | :OListBox( parent, name, WType_Popup ) | ||
52 | { | ||
53 | d = new OCompletionBoxPrivate; | ||
54 | d->m_parent = parent; | ||
55 | d->tabHandling = true; | ||
56 | d->down_workaround = false; | ||
57 | |||
58 | setColumnMode( 1 ); | ||
59 | setLineWidth( 1 ); | ||
60 | setFrameStyle( QFrame::Box | QFrame::Plain ); | ||
61 | |||
62 | if ( parent ) | ||
63 | setFocusProxy( parent ); | ||
64 | else | ||
65 | setFocusPolicy( NoFocus ); | ||
66 | |||
67 | setVScrollBarMode( Auto ); | ||
68 | setHScrollBarMode( AlwaysOff ); | ||
69 | |||
70 | connect( this, SIGNAL( doubleClicked( QListBoxItem * )), | ||
71 | SLOT( slotActivated( QListBoxItem * )) ); | ||
72 | |||
73 | // grmbl, just QListBox workarounds :[ Thanks Volker. | ||
74 | connect( this, SIGNAL( currentChanged( QListBoxItem * )), | ||
75 | SLOT( slotCurrentChanged() )); | ||
76 | connect( this, SIGNAL( clicked( QListBoxItem * )), | ||
77 | SLOT( slotItemClicked( QListBoxItem * )) ); | ||
78 | } | ||
79 | |||
80 | OCompletionBox::~OCompletionBox() | ||
81 | { | ||
82 | d->m_parent = 0L; | ||
83 | delete d; | ||
84 | } | ||
85 | |||
86 | QStringList OCompletionBox::items() const | ||
87 | { | ||
88 | QStringList list; | ||
89 | for ( uint i = 0; i < count(); i++ ) { | ||
90 | list.append( text( i ) ); | ||
91 | } | ||
92 | return list; | ||
93 | } | ||
94 | |||
95 | void OCompletionBox::slotActivated( QListBoxItem *item ) | ||
96 | { | ||
97 | if ( !item ) | ||
98 | return; | ||
99 | |||
100 | hide(); | ||
101 | emit activated( item->text() ); | ||
102 | } | ||
103 | |||
104 | bool OCompletionBox::eventFilter( QObject *o, QEvent *e ) | ||
105 | { | ||
106 | int type = e->type(); | ||
107 | |||
108 | if ( o == d->m_parent ) { | ||
109 | if ( isVisible() ) { | ||
110 | if ( type == QEvent::KeyPress ) { | ||
111 | QKeyEvent *ev = static_cast<QKeyEvent *>( e ); | ||
112 | switch ( ev->key() ) { | ||
113 | case Key_BackTab: | ||
114 | if ( d->tabHandling ) { | ||
115 | up(); | ||
116 | ev->accept(); | ||
117 | return true; | ||
118 | } | ||
119 | break; | ||
120 | case Key_Tab: | ||
121 | if ( d->tabHandling ) { | ||
122 | down(); // Only on TAB!! | ||
123 | ev->accept(); | ||
124 | return true; | ||
125 | } | ||
126 | break; | ||
127 | case Key_Down: | ||
128 | down(); | ||
129 | ev->accept(); | ||
130 | return true; | ||
131 | case Key_Up: | ||
132 | up(); | ||
133 | ev->accept(); | ||
134 | return true; | ||
135 | case Key_Prior: | ||
136 | pageUp(); | ||
137 | ev->accept(); | ||
138 | return true; | ||
139 | case Key_Next: | ||
140 | pageDown(); | ||
141 | ev->accept(); | ||
142 | return true; | ||
143 | case Key_Escape: | ||
144 | cancelled(); | ||
145 | ev->accept(); | ||
146 | return true; | ||
147 | case Key_Enter: | ||
148 | case Key_Return: | ||
149 | if ( ev->state() & ShiftButton ) { | ||
150 | hide(); | ||
151 | ev->accept(); // Consume the Enter event | ||
152 | return true; | ||
153 | } | ||
154 | break; | ||
155 | default: | ||
156 | break; | ||
157 | } | ||
158 | } | ||
159 | else if ( type == QEvent::AccelOverride ) { | ||
160 | // Override any acceleartors that match | ||
161 | // the key sequences we use here... | ||
162 | QKeyEvent *ev = static_cast<QKeyEvent *>( e ); | ||
163 | switch ( ev->key() ) { | ||
164 | case Key_Tab: | ||
165 | case Key_BackTab: | ||
166 | case Key_Down: | ||
167 | case Key_Up: | ||
168 | case Key_Prior: | ||
169 | case Key_Next: | ||
170 | case Key_Escape: | ||
171 | case Key_Enter: | ||
172 | case Key_Return: | ||
173 | ev->accept(); | ||
174 | return true; | ||
175 | break; | ||
176 | default: | ||
177 | break; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | // parent loses focus or gets a click -> we hide | ||
182 | else if ( type == QEvent::FocusOut || type == QEvent::Resize || | ||
183 | type == QEvent::Close || type == QEvent::Hide || | ||
184 | type == QEvent::Move ) { | ||
185 | hide(); | ||
186 | } | ||
187 | else if ( type == QEvent::Move ) | ||
188 | move( d->m_parent->mapToGlobal(QPoint(0, d->m_parent->height()))); | ||
189 | else if ( type == QEvent::Resize ) | ||
190 | resize( sizeHint() ); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | // any mouse-click on something else than "this" makes us hide | ||
195 | else if ( type == QEvent::MouseButtonPress ) { | ||
196 | QMouseEvent *ev = static_cast<QMouseEvent *>( e ); | ||
197 | if ( !rect().contains( ev->pos() )) // this widget | ||
198 | hide(); | ||
199 | } | ||
200 | |||
201 | return OListBox::eventFilter( o, e ); | ||
202 | } | ||
203 | |||
204 | |||
205 | void OCompletionBox::popup() | ||
206 | { | ||
207 | if ( count() == 0 ) | ||
208 | hide(); | ||
209 | else { | ||
210 | ensureCurrentVisible(); | ||
211 | bool block = signalsBlocked(); | ||
212 | blockSignals( true ); | ||
213 | setCurrentItem( 0 ); | ||
214 | blockSignals( block ); | ||
215 | clearSelection(); | ||
216 | if ( !isVisible() ) | ||
217 | show(); | ||
218 | else if ( size().height() < sizeHint().height() ) | ||
219 | resize( sizeHint() ); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | void OCompletionBox::show() | ||
224 | { | ||
225 | resize( sizeHint() ); | ||
226 | |||
227 | if ( d->m_parent ) | ||
228 | { | ||
229 | //QDesktopWidget *screen = QApplication::desktop(); | ||
230 | QWidget *screen = QApplication::desktop(); | ||
231 | |||
232 | QPoint orig = d->m_parent->mapToGlobal( QPoint(0, d->m_parent->height()) ); | ||
233 | int x = orig.x(); | ||
234 | int y = orig.y(); | ||
235 | |||
236 | if ( x + width() > screen->width() ) | ||
237 | x = screen->width() - width(); | ||
238 | if (y + height() > screen->height() ) | ||
239 | y = y - height() - d->m_parent->height(); | ||
240 | |||
241 | move( x, y); | ||
242 | qApp->installEventFilter( this ); | ||
243 | } | ||
244 | |||
245 | // ### we shouldn't need to call this, but without this, the scrollbars | ||
246 | // are pretty b0rked. | ||
247 | //triggerUpdate( true ); | ||
248 | |||
249 | OListBox::show(); | ||
250 | } | ||
251 | |||
252 | void OCompletionBox::hide() | ||
253 | { | ||
254 | if ( d->m_parent ) | ||
255 | qApp->removeEventFilter( this ); | ||
256 | d->cancelText = QString::null; | ||
257 | OListBox::hide(); | ||
258 | } | ||
259 | |||
260 | QSize OCompletionBox::sizeHint() const | ||
261 | { | ||
262 | int ih = itemHeight(); | ||
263 | int h = QMIN( 15 * ih, (int) count() * ih ) +1; | ||
264 | h = QMAX( h, OListBox::minimumSizeHint().height() ); | ||
265 | |||
266 | int w = (d->m_parent) ? d->m_parent->width() : OListBox::minimumSizeHint().width(); | ||
267 | w = QMAX( OListBox::minimumSizeHint().width(), w ); | ||
268 | return QSize( w, h ); | ||
269 | } | ||
270 | |||
271 | void OCompletionBox::down() | ||
272 | { | ||
273 | int i = currentItem(); | ||
274 | |||
275 | if ( i == 0 && d->down_workaround ) { | ||
276 | d->down_workaround = false; | ||
277 | setCurrentItem( 0 ); | ||
278 | setSelected( 0, true ); | ||
279 | emit highlighted( currentText() ); | ||
280 | } | ||
281 | |||
282 | else if ( i < (int) count() - 1 ) | ||
283 | setCurrentItem( i + 1 ); | ||
284 | } | ||
285 | |||
286 | void OCompletionBox::up() | ||
287 | { | ||
288 | if ( currentItem() > 0 ) | ||
289 | setCurrentItem( currentItem() - 1 ); | ||
290 | } | ||
291 | |||
292 | void OCompletionBox::pageDown() | ||
293 | { | ||
294 | int i = currentItem() + numItemsVisible(); | ||
295 | i = i > (int)count() - 1 ? (int)count() - 1 : i; | ||
296 | setCurrentItem( i ); | ||
297 | } | ||
298 | |||
299 | void OCompletionBox::pageUp() | ||
300 | { | ||
301 | int i = currentItem() - numItemsVisible(); | ||
302 | i = i < 0 ? 0 : i; | ||
303 | setCurrentItem( i ); | ||
304 | } | ||
305 | |||
306 | void OCompletionBox::home() | ||
307 | { | ||
308 | setCurrentItem( 0 ); | ||
309 | } | ||
310 | |||
311 | void OCompletionBox::end() | ||
312 | { | ||
313 | setCurrentItem( count() -1 ); | ||
314 | } | ||
315 | |||
316 | void OCompletionBox::setTabHandling( bool enable ) | ||
317 | { | ||
318 | d->tabHandling = enable; | ||
319 | } | ||
320 | |||
321 | bool OCompletionBox::isTabHandling() const | ||
322 | { | ||
323 | return d->tabHandling; | ||
324 | } | ||
325 | |||
326 | void OCompletionBox::setCancelledText( const QString& text ) | ||
327 | { | ||
328 | d->cancelText = text; | ||
329 | } | ||
330 | |||
331 | QString OCompletionBox::cancelledText() const | ||
332 | { | ||
333 | return d->cancelText; | ||
334 | } | ||
335 | |||
336 | void OCompletionBox::cancelled() | ||
337 | { | ||
338 | if ( !d->cancelText.isNull() ) | ||
339 | emit userCancelled( d->cancelText ); | ||
340 | if ( isVisible() ) | ||
341 | hide(); | ||
342 | } | ||
343 | |||
344 | class OCompletionBoxItem : public QListBoxItem | ||
345 | { | ||
346 | public: | ||
347 | void reuse( const QString &text ) { setText( text ); } | ||
348 | }; | ||
349 | |||
350 | |||
351 | void OCompletionBox::insertItems( const QStringList& items, int index ) | ||
352 | { | ||
353 | bool block = signalsBlocked(); | ||
354 | blockSignals( true ); | ||
355 | insertStringList( items, index ); | ||
356 | blockSignals( block ); | ||
357 | d->down_workaround = true; | ||
358 | } | ||
359 | |||
360 | void OCompletionBox::setItems( const QStringList& items ) | ||
361 | { | ||
362 | bool block = signalsBlocked(); | ||
363 | blockSignals( true ); | ||
364 | |||
365 | QListBoxItem* item = firstItem(); | ||
366 | if ( !item ) { | ||
367 | insertStringList( items ); | ||
368 | } | ||
369 | else { | ||
370 | for ( QStringList::ConstIterator it = items.begin(); it != items.end(); it++) { | ||
371 | if ( item ) { | ||
372 | ((OCompletionBoxItem*)item)->reuse( *it ); | ||
373 | item = item->next(); | ||
374 | } | ||
375 | else { | ||
376 | insertItem( new QListBoxText( *it ) ); | ||
377 | } | ||
378 | } | ||
379 | QListBoxItem* tmp = item; | ||
380 | while ( (item = tmp ) ) { | ||
381 | tmp = item->next(); | ||
382 | delete item; | ||
383 | } | ||
384 | triggerUpdate( false ); | ||
385 | } | ||
386 | |||
387 | blockSignals( block ); | ||
388 | d->down_workaround = true; | ||
389 | } | ||
390 | |||
391 | void OCompletionBox::slotCurrentChanged() | ||
392 | { | ||
393 | d->down_workaround = false; | ||
394 | } | ||
395 | |||
396 | void OCompletionBox::slotItemClicked( QListBoxItem *item ) | ||
397 | { | ||
398 | if ( item ) | ||
399 | { | ||
400 | if ( d->down_workaround ) { | ||
401 | d->down_workaround = false; | ||
402 | emit highlighted( item->text() ); | ||
403 | } | ||
404 | |||
405 | hide(); | ||
406 | emit activated( item->text() ); | ||
407 | } | ||
408 | } | ||