summaryrefslogtreecommitdiff
path: root/libopie2/qt3/opiecore
Unidiff
Diffstat (limited to 'libopie2/qt3/opiecore') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/qt3/opiecore/ocompletion.cpp1061
-rw-r--r--libopie2/qt3/opiecore/ocompletion.h603
-rw-r--r--libopie2/qt3/opiecore/ocompletionbase.cpp171
-rw-r--r--libopie2/qt3/opiecore/ocompletionbase.h403
-rw-r--r--libopie2/qt3/opiecore/opair.h99
-rw-r--r--libopie2/qt3/opiecore/osortablevaluelist.h117
-rw-r--r--libopie2/qt3/opiecore/otl.h325
7 files changed, 2779 insertions, 0 deletions
diff --git a/libopie2/qt3/opiecore/ocompletion.cpp b/libopie2/qt3/opiecore/ocompletion.cpp
new file mode 100644
index 0000000..7b263ab
--- a/dev/null
+++ b/libopie2/qt3/opiecore/ocompletion.cpp
@@ -0,0 +1,1061 @@
1/*
2                 This file is part of the Opie Project
3 Originally part of the KDE Project
4 Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29*/
30
31#include <opie2/ocompletion.h>
32
33class OCompTreeNode;
34
35/**************************************************************************************************/
36/* OCompTreeNodeList
37/**************************************************************************************************/
38
39class OCompTreeNodeList
40{
41public:
42 OCompTreeNodeList() : first(0), last(0), m_count(0) {}
43 OCompTreeNode *begin() const { return first; }
44 OCompTreeNode *end() const { return last; }
45
46 OCompTreeNode *at(uint index) const;
47 void append(OCompTreeNode *item);
48 void prepend(OCompTreeNode *item);
49 void insert(OCompTreeNode *after, OCompTreeNode *item);
50 OCompTreeNode *remove(OCompTreeNode *item);
51 uint count() const { return m_count; }
52
53private:
54 OCompTreeNode *first, *last;
55 uint m_count;
56};
57
58typedef OCompTreeNodeList OCompTreeChildren;
59typedef OSortableValueList<QString> OCompletionMatchesList;
60
61/**
62 * A helper class for OCompletion. Implements a tree of QChar.
63 *
64 * The tree looks like this (containing the items "kde", "kde-ui",
65 * "kde-core" and "pfeiffer". Every item is delimited with QChar( 0x0 )
66 *
67 * some_root_node
68 * / \
69 * k p
70 * | |
71 * d f
72 * | |
73 * e e
74 * /| |
75 * 0x0 - i
76 * / \ |
77 * u c f
78 * | | |
79 * i o f
80 * | | |
81 * 0x0 r e
82 * | |
83 * e r
84 * | |
85 * 0x0 0x0
86 *
87 * @author Carsten Pfeiffer <pfeiffer@kde.org>
88 * @internal
89 */
90
91/**************************************************************************************************/
92/* OCompTreeNode
93/**************************************************************************************************/
94
95class OCompTreeNode : public QChar
96{
97public:
98 OCompTreeNode():QChar(), myWeight(0) {}
99 OCompTreeNode( const QChar& ch, uint weight = 0 ):QChar( ch ), myWeight( weight ) {}
100 ~OCompTreeNode();
101
102 // FIXME: Do we need this for Opie? [see also the static ZoneAllocater below]
103 //void * operator new( size_t s ) {
104 // return alloc.allocate( s );
105 //}
106 //void operator delete( void * s ) {
107 // alloc.deallocate( s );
108 //}
109
110 // Returns a child of this node matching ch, if available.
111 // Otherwise, returns 0L
112 inline OCompTreeNode * find( const QChar& ch ) const {
113 OCompTreeNode * cur = myChildren.begin();
114 while (cur && (*cur != ch)) cur = cur->next;
115 return cur;
116 }
117
118 OCompTreeNode * insert( const QChar&, bool sorted );
119 void remove( const QString& );
120
121 inline int childrenCount() const { return myChildren.count(); };
122
123 // weighting
124 inline void confirm() { myWeight++; };
125 inline void confirm(uint w) { myWeight += w; };
126 inline void decline() { myWeight--; };
127 inline uint weight() const { return myWeight; };
128
129 inline const OCompTreeChildren * children() const { return &myChildren; };
130 inline const OCompTreeNode * childAt(int index) const { return myChildren.at(index); };
131 inline const OCompTreeNode * firstChild() const { return myChildren.begin(); };
132 inline const OCompTreeNode * lastChild() const { return myChildren.end(); };
133
134 /* We want to handle a list of OCompTreeNodes on our own, to not
135 need to use QValueList<>. And to make it even more fast we don't
136 use an accessor, but just a public member. */
137 OCompTreeNode *next;
138
139private:
140 uint myWeight;
141 OCompTreeNodeListmyChildren;
142 //static OZoneAllocator alloc; // FIXME: Do we need this for Opie?
143};
144
145/**************************************************************************************************/
146/* OCompletionMatchesWrapper
147/**************************************************************************************************/
148
149class OCompletionMatchesWrapper
150{
151public:
152 OCompletionMatchesWrapper( bool sort = false )
153 : sortedList( sort ? new OCompletionMatchesList : 0L ),
154 dirty( false )
155 {}
156 ~OCompletionMatchesWrapper() {
157 delete sortedList;
158 }
159
160 void setSorting( bool sort ) {
161 if ( sort && !sortedList )
162 sortedList = new OCompletionMatchesList;
163 else if ( !sort ) {
164 delete sortedList;
165 sortedList = 0L;
166 }
167 stringList.clear();
168 dirty = false;
169 }
170
171 bool sorting() const {
172 return sortedList != 0L;
173 }
174
175 void append( int i, const QString& string ) {
176 if ( sortedList )
177 sortedList->insert( i, string );
178 else
179 stringList.append( string );
180 dirty = true;
181 }
182
183 void clear() {
184 if ( sortedList )
185 sortedList->clear();
186 stringList.clear();
187 dirty = false;
188 }
189
190 uint count() const {
191 if ( sortedList )
192 return sortedList->count();
193 return stringList.count();
194 }
195
196 bool isEmpty() const {
197 return count() == 0;
198 }
199
200 QString first() const {
201 return list().first();
202 }
203
204 QString last() const {
205 return list().last();
206 }
207
208 QStringList list() const;
209
210 mutable QStringList stringList;
211 OCompletionMatchesList *sortedList;
212 mutable bool dirty;
213};
214
215/**************************************************************************************************/
216/* OCompletionPrivate
217/**************************************************************************************************/
218
219class OCompletionPrivate
220{
221public:
222 // not a member to avoid #including kcompletion_private.h from kcompletion.h
223 // list used for nextMatch() and previousMatch()
224 OCompletionMatchesWrapper matches;
225};
226
227/**************************************************************************************************/
228/* OCompletion
229/**************************************************************************************************/
230
231OCompletion::OCompletion()
232{
233 d = new OCompletionPrivate;
234
235 myCompletionMode = OGlobalSettings::completionMode();
236 myTreeRoot = new OCompTreeNode;
237 myBeep = true;
238 myIgnoreCase = false;
239 myHasMultipleMatches = false;
240 myRotationIndex = 0;
241 setOrder( Insertion );
242}
243
244
245OCompletion::~OCompletion()
246{
247 delete d;
248 delete myTreeRoot;
249}
250
251
252void OCompletion::setOrder( CompOrder order )
253{
254 myOrder = order;
255 d->matches.setSorting( order == Weighted );
256}
257
258
259void OCompletion::setIgnoreCase( bool ignoreCase )
260{
261 myIgnoreCase = ignoreCase;
262}
263
264
265void OCompletion::setItems( const QStringList& items )
266{
267 clear();
268 insertItems( items );
269}
270
271
272void OCompletion::insertItems( const QStringList& items )
273{
274 bool weighted = (myOrder == Weighted);
275 QStringList::ConstIterator it;
276 if ( weighted ) { // determine weight
277 for ( it = items.begin(); it != items.end(); ++it ) addWeightedItem( *it );
278 }
279 else {
280 for ( it = items.begin(); it != items.end(); ++it ) addItem( *it, 0 );
281 }
282}
283
284
285QStringList OCompletion::items() const
286{
287 OCompletionMatchesWrapper list; // unsorted
288 bool addWeight = (myOrder == Weighted);
289 extractStringsFromNode( myTreeRoot, QString::null, &list, addWeight );
290
291 return list.list();
292}
293
294
295void OCompletion::addItem( const QString& item )
296{
297 d->matches.clear();
298 myRotationIndex = 0;
299 myLastString = QString::null;
300
301 addItem( item, 0 );
302}
303
304
305void OCompletion::addItem( const QString& item, uint weight )
306{
307 if ( item.isEmpty() ) return;
308
309 OCompTreeNode *node = myTreeRoot;
310 uint len = item.length();
311
312 bool sorted = (myOrder == Sorted);
313 bool weighted = ((myOrder == Weighted) && weight > 1);
314
315 // knowing the weight of an item, we simply add this weight to all of its
316 // nodes.
317
318 for ( uint i = 0; i < len; i++ ) {
319 node = node->insert( item.at(i), sorted );
320 if ( weighted ) node->confirm( weight -1 ); // node->insert() sets weighting to 1
321 }
322
323 // add 0x0-item as delimiter with evtl. weight
324 node = node->insert( 0x0, true );
325 if ( weighted )
326 node->confirm( weight -1 );
327 //qDebug( "OCompletion: added: %s (%i)", item.latin1(), node->weight());
328}
329
330
331void OCompletion::addWeightedItem( const QString& item )
332{
333 if ( myOrder != Weighted ) {
334 addItem( item, 0 );
335 return;
336 }
337
338 uint len = item.length();
339 uint weight = 0;
340
341 // find out the weighting of this item (appended to the string as ":num")
342 int index = item.findRev(':');
343 if ( index > 0 ) {
344 bool ok;
345 weight = item.mid( index + 1 ).toUInt( &ok );
346 if ( !ok )
347 weight = 0;
348
349 len = index; // only insert until the ':'
350 }
351
352 addItem( item.left( len ), weight );
353 return;
354}
355
356
357void OCompletion::removeItem( const QString& item )
358{
359 d->matches.clear();
360 myRotationIndex = 0;
361 myLastString = QString::null;
362
363 myTreeRoot->remove( item );
364}
365
366
367void OCompletion::clear()
368{
369 d->matches.clear();
370 myRotationIndex = 0;
371 myLastString = QString::null;
372
373 delete myTreeRoot;
374 myTreeRoot = new OCompTreeNode;
375}
376
377
378QString OCompletion::makeCompletion( const QString& string )
379{
380 if ( myCompletionMode == OGlobalSettings::CompletionNone )
381 return QString::null;
382
383 //qDebug( "OCompletion: completing: %s", string );
384
385 d->matches.clear();
386 myRotationIndex = 0;
387 myHasMultipleMatches = false;
388 myLastMatch = myCurrentMatch;
389
390 // in Shell-completion-mode, emit all matches when we get the same
391 // complete-string twice
392 if ( myCompletionMode == OGlobalSettings::CompletionShell &&
393 string == myLastString ) {
394 // Don't use d->matches since calling postProcessMatches()
395 // on d->matches here would interfere with call to
396 // postProcessMatch() during rotation
397
398 findAllCompletions( string, &d->matches, myHasMultipleMatches );
399 QStringList l = d->matches.list();
400 postProcessMatches( &l );
401 emit matches( l );
402
403 if ( l.isEmpty() )
404 doBeep( NoMatch );
405
406 return QString::null;
407 }
408
409 QString completion;
410 // in case-insensitive popup mode, we search all completions at once
411 if ( myCompletionMode == OGlobalSettings::CompletionPopup ||
412 myCompletionMode == OGlobalSettings::CompletionPopupAuto ) {
413 findAllCompletions( string, &d->matches, myHasMultipleMatches );
414 if ( !d->matches.isEmpty() )
415 completion = d->matches.first();
416 }
417 else
418 completion = findCompletion( string );
419
420 if ( myHasMultipleMatches )
421 emit multipleMatches();
422
423 myLastString = string;
424 myCurrentMatch = completion;
425
426 postProcessMatch( &completion );
427
428 if ( !string.isEmpty() ) { // only emit match when string != ""
429 //qDebug( "OCompletion: Match: %s", completion );
430 emit match( completion );
431 }
432
433 if ( completion.isNull() )
434 doBeep( NoMatch );
435
436 return completion;
437}
438
439QStringList OCompletion::substringCompletion( const QString& string ) const
440{
441 // get all items in the tree, eventually in sorted order
442 bool sorted = (myOrder == Weighted);
443 OCompletionMatchesWrapper allItems( sorted );
444 extractStringsFromNode( myTreeRoot, QString::null, &allItems, false );
445
446 QStringList list = allItems.list();
447
448 // subStringMatches is invoked manually, via a shortcut, so we should
449 // beep here, if necessary.
450 if ( list.isEmpty() ) {
451 doBeep( NoMatch );
452 return list;
453 }
454
455 if ( string.isEmpty() ) { // shortcut
456 postProcessMatches( &list );
457 return list;
458 }
459
460 QStringList matches;
461 QStringList::ConstIterator it = list.begin();
462
463 for( ; it != list.end(); ++it ) {
464 QString item = *it;
465 if ( item.find( string, 0, false ) != -1 ) { // always case insensitive
466 postProcessMatch( &item );
467 matches.append( item );
468 }
469 }
470
471 if ( matches.isEmpty() )
472 doBeep( NoMatch );
473
474 return matches;
475}
476
477
478void OCompletion::setCompletionMode( OGlobalSettings::Completion mode )
479{
480 myCompletionMode = mode;
481}
482
483
484QStringList OCompletion::allMatches()
485{
486 // Don't use d->matches since calling postProcessMatches()
487 // on d->matches here would interfere with call to
488 // postProcessMatch() during rotation
489 OCompletionMatchesWrapper matches( myOrder == Weighted );
490 bool dummy;
491 findAllCompletions( myLastString, &matches, dummy );
492 QStringList l = matches.list();
493 postProcessMatches( &l );
494 return l;
495}
496
497
498OCompletionMatches OCompletion::allWeightedMatches()
499{
500 // Don't use d->matches since calling postProcessMatches()
501 // on d->matches here would interfere with call to
502 // postProcessMatch() during rotation
503 OCompletionMatchesWrapper matches( myOrder == Weighted );
504 bool dummy;
505 findAllCompletions( myLastString, &matches, dummy );
506 OCompletionMatches ret( matches );
507 postProcessMatches( &ret );
508 return ret;
509}
510
511QStringList OCompletion::allMatches( const QString &string )
512{
513 OCompletionMatchesWrapper matches( myOrder == Weighted );
514 bool dummy;
515 findAllCompletions( string, &matches, dummy );
516 QStringList l = matches.list();
517 postProcessMatches( &l );
518 return l;
519}
520
521OCompletionMatches OCompletion::allWeightedMatches( const QString &string )
522{
523 OCompletionMatchesWrapper matches( myOrder == Weighted );
524 bool dummy;
525 findAllCompletions( string, &matches, dummy );
526 OCompletionMatches ret( matches );
527 postProcessMatches( &ret );
528 return ret;
529}
530
531/////////////////////////////////////////////////////
532///////////////// tree operations ///////////////////
533
534
535QString OCompletion::nextMatch()
536{
537 QString completion;
538 myLastMatch = myCurrentMatch;
539
540 if ( d->matches.isEmpty() ) {
541 findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
542 completion = d->matches.first();
543 myCurrentMatch = completion;
544 myRotationIndex = 0;
545 postProcessMatch( &completion );
546 emit match( completion );
547 return completion;
548 }
549
550 QStringList matches = d->matches.list();
551 myLastMatch = matches[ myRotationIndex++ ];
552
553 if ( myRotationIndex == matches.count() -1 )
554 doBeep( Rotation ); // indicate last matching item -> rotating
555
556 else if ( myRotationIndex == matches.count() )
557 myRotationIndex = 0;
558
559 completion = matches[ myRotationIndex ];
560 myCurrentMatch = completion;
561 postProcessMatch( &completion );
562 emit match( completion );
563 return completion;
564}
565
566
567
568QString OCompletion::previousMatch()
569{
570 QString completion;
571 myLastMatch = myCurrentMatch;
572
573 if ( d->matches.isEmpty() ) {
574 findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
575 completion = d->matches.last();
576 myCurrentMatch = completion;
577 myRotationIndex = 0;
578 postProcessMatch( &completion );
579 emit match( completion );
580 return completion;
581 }
582
583 QStringList matches = d->matches.list();
584 myLastMatch = matches[ myRotationIndex ];
585 if ( myRotationIndex == 1 )
586 doBeep( Rotation ); // indicate first item -> rotating
587
588 else if ( myRotationIndex == 0 )
589 myRotationIndex = matches.count();
590
591 myRotationIndex--;
592
593 completion = matches[ myRotationIndex ];
594 myCurrentMatch = completion;
595 postProcessMatch( &completion );
596 emit match( completion );
597 return completion;
598}
599
600
601
602// tries to complete "string" from the tree-root
603QString OCompletion::findCompletion( const QString& string )
604{
605 QChar ch;
606 QString completion;
607 const OCompTreeNode *node = myTreeRoot;
608
609 // start at the tree-root and try to find the search-string
610 for( uint i = 0; i < string.length(); i++ ) {
611 ch = string.at( i );
612 node = node->find( ch );
613
614 if ( node )
615 completion += ch;
616 else
617 return QString::null; // no completion
618 }
619
620 // Now we have the last node of the to be completed string.
621 // Follow it as long as it has exactly one child (= longest possible
622 // completion)
623
624 while ( node->childrenCount() == 1 ) {
625 node = node->firstChild();
626 if ( !node->isNull() )
627 completion += *node;
628 }
629 // if multiple matches and auto-completion mode
630 // -> find the first complete match
631 if ( node && node->childrenCount() > 1 ) {
632 myHasMultipleMatches = true;
633
634 if ( myCompletionMode == OGlobalSettings::CompletionAuto ) {
635 myRotationIndex = 1;
636 if (myOrder != Weighted) {
637 while ( (node = node->firstChild()) ) {
638 if ( !node->isNull() )
639 completion += *node;
640 else
641 break;
642 }
643 }
644 else {
645 // don't just find the "first" match, but the one with the
646 // highest priority
647
648 const OCompTreeNode* temp_node = 0L;
649 while(1) {
650 int count = node->childrenCount();
651 temp_node = node->firstChild();
652 uint weight = temp_node->weight();
653 const OCompTreeNode* hit = temp_node;
654 for( int i = 1; i < count; i++ ) {
655 temp_node = node->childAt(i);
656 if( temp_node->weight() > weight ) {
657 hit = temp_node;
658 weight = hit->weight();
659 }
660 }
661 // 0x0 has the highest priority -> we have the best match
662 if ( hit->isNull() )
663 break;
664
665 node = hit;
666 completion += *node;
667 }
668 }
669 }
670
671 else
672 doBeep( PartialMatch ); // partial match -> beep
673 }
674
675 return completion;
676}
677
678
679void OCompletion::findAllCompletions(const QString& string,
680 OCompletionMatchesWrapper *matches,
681 bool& hasMultipleMatches) const
682{
683 //qDebug( "OCompletion: finding all completions for %s", (const char*) string );
684
685 if ( string.isEmpty() )
686 return;
687
688 if ( myIgnoreCase ) { // case insensitive completion
689 extractStringsFromNodeCI( myTreeRoot, QString::null, string, matches );
690 hasMultipleMatches = (matches->count() > 1);
691 return;
692 }
693
694 QChar ch;
695 QString completion;
696 const OCompTreeNode *node = myTreeRoot;
697
698 // start at the tree-root and try to find the search-string
699 for( uint i = 0; i < string.length(); i++ ) {
700 ch = string.at( i );
701 node = node->find( ch );
702
703 if ( node )
704 completion += ch;
705 else
706 return; // no completion -> return empty list
707 }
708
709 // Now we have the last node of the to be completed string.
710 // Follow it as long as it has exactly one child (= longest possible
711 // completion)
712
713 while ( node->childrenCount() == 1 ) {
714 node = node->firstChild();
715 if ( !node->isNull() )
716 completion += *node;
717 // kdDebug() << completion << node->latin1();
718 }
719
720
721 // there is just one single match)
722 if ( node->childrenCount() == 0 )
723 matches->append( node->weight(), completion );
724
725 else {
726 // node has more than one child
727 // -> recursively find all remaining completions
728 hasMultipleMatches = true;
729 extractStringsFromNode( node, completion, matches );
730 }
731}
732
733
734void OCompletion::extractStringsFromNode( const OCompTreeNode *node,
735 const QString& beginning,
736 OCompletionMatchesWrapper *matches,
737 bool addWeight ) const
738{
739 if ( !node || !matches ) return;
740
741 // kDebug() << "Beginning: " << beginning << endl;
742 const OCompTreeChildren *list = node->children();
743 QString string;
744 QString w;
745
746 // loop thru all children
747 for ( OCompTreeNode *cur = list->begin(); cur ; cur = cur->next) {
748 string = beginning;
749 node = cur;
750 if ( !node->isNull() )
751 string += *node;
752
753 while ( node && node->childrenCount() == 1 ) {
754 node = node->firstChild();
755 if ( node->isNull() ) break;
756 string += *node;
757 }
758
759 if ( node && node->isNull() ) { // we found a leaf
760 if ( addWeight ) {
761 // add ":num" to the string to store the weighting
762 string += ':';
763 w.setNum( node->weight() );
764 string.append( w );
765 }
766 matches->append( node->weight(), string );
767 }
768
769 // recursively find all other strings.
770 if ( node && node->childrenCount() > 1 )
771 extractStringsFromNode( node, string, matches, addWeight );
772 }
773}
774
775void OCompletion::extractStringsFromNodeCI( const OCompTreeNode *node,
776 const QString& beginning,
777 const QString& restString,
778 OCompletionMatchesWrapper *matches ) const
779{
780 if ( restString.isEmpty() ) {
781 extractStringsFromNode( node, beginning, matches, false /*noweight*/ );
782 return;
783 }
784
785 QChar ch1 = restString.at(0);
786 QString newRest = restString.mid(1);
787 OCompTreeNode *child1, *child2;
788
789 child1 = node->find( ch1 ); // the correct match
790 if ( child1 )
791 extractStringsFromNodeCI( child1, beginning + *child1, newRest,
792 matches );
793
794 // append the case insensitive matches, if available
795 if ( ch1.isLetter() ) {
796 // find out if we have to lower or upper it. Is there a better way?
797 QChar ch2 = ch1.lower();
798 if ( ch1 == ch2 )
799 ch2 = ch1.upper();
800 if ( ch1 != ch2 ) {
801 child2 = node->find( ch2 );
802 if ( child2 )
803 extractStringsFromNodeCI( child2, beginning + *child2, newRest,
804 matches );
805 }
806 }
807}
808
809// FIXME: Revise this for Opie?
810
811void OCompletion::doBeep( BeepMode mode ) const
812{
813 if ( !myBeep ) return;
814
815 QString text, event;
816
817 switch ( mode ) {
818 case Rotation:
819 event = QString::fromLatin1("Textcompletion: rotation");
820 text = tr("You reached the end of the list\nof matching items.\n");
821 break;
822 case PartialMatch:
823 if ( myCompletionMode == OGlobalSettings::CompletionShell ||
824 myCompletionMode == OGlobalSettings::CompletionMan ) {
825 event = QString::fromLatin1("Textcompletion: partial match");
826 text = tr("The completion is ambiguous, more than one\nmatch is available.\n");
827 }
828 break;
829 case NoMatch:
830 if ( myCompletionMode == OGlobalSettings::CompletionShell ) {
831 event = QString::fromLatin1("Textcompletion: no match");
832 text = tr("There is no matching item available.\n");
833 }
834 break;
835 }
836
837 //if ( !text.isEmpty() )
838 //ONotifyClient::event( event, text ); // FIXME: Revise for Opie?
839}
840
841// Implements the tree. Every node is a QChar and has a list of children, which
842// are Nodes as well.
843// QChar( 0x0 ) is used as the delimiter of a string; the last child of each
844// inserted string is 0x0.
845
846OCompTreeNode::~OCompTreeNode()
847{
848 // delete all children
849 OCompTreeNode *cur = myChildren.begin();
850 while (cur) {
851 OCompTreeNode * next = cur->next;
852 delete myChildren.remove(cur);
853 cur = next;
854 }
855}
856
857
858// Adds a child-node "ch" to this node. If such a node is already existant,
859// it will not be created. Returns the new/existing node.
860OCompTreeNode * OCompTreeNode::insert( const QChar& ch, bool sorted )
861{
862 OCompTreeNode *child = find( ch );
863 if ( !child ) {
864 child = new OCompTreeNode( ch );
865
866 // FIXME, first (slow) sorted insertion implementation
867 if ( sorted ) {
868 OCompTreeNode * prev = 0;
869 OCompTreeNode * cur = myChildren.begin();
870 while ( cur ) {
871 if ( ch > *cur ) {
872 prev = cur;
873 cur = cur->next;
874 } else
875 break;
876 }
877 if (prev)
878 myChildren.insert( prev, child );
879 else
880 myChildren.prepend(child);
881 }
882
883 else
884 myChildren.append( child );
885 }
886
887 // implicit weighting: the more often an item is inserted, the higher
888 // priority it gets.
889 child->confirm();
890
891 return child;
892}
893
894
895// Recursively removes a string from the tree (untested :-)
896void OCompTreeNode::remove( const QString& string )
897{
898 OCompTreeNode *child = 0L;
899
900 if ( string.isEmpty() ) {
901 child = find( 0x0 );
902 delete myChildren.remove( child );
903 return;
904 }
905
906 QChar ch = string.at(0);
907 child = find( ch );
908 if ( child ) {
909 child->remove( string.right( string.length() -1 ) );
910 if ( child->myChildren.count() == 0 ) {
911 delete myChildren.remove( child );
912 }
913 }
914}
915
916QStringList OCompletionMatchesWrapper::list() const {
917 if ( sortedList && dirty ) {
918 sortedList->sort();
919 dirty = false;
920
921 stringList.clear();
922
923 // high weight == sorted last -> reverse the sorting here
924 QValueListConstIterator<OSortableItem<QString> > it;
925 for ( it = sortedList->begin(); it != sortedList->end(); ++it )
926 stringList.prepend( (*it).value() );
927 }
928
929 return stringList;
930}
931
932OCompletionMatches::OCompletionMatches( bool sort_P )
933 : _sorting( sort_P )
934{
935}
936
937OCompletionMatches::OCompletionMatches( const OCompletionMatchesWrapper& matches )
938 : _sorting( matches.sorting())
939{
940 if( matches.sortedList != 0L )
941 OCompletionMatchesList::operator=( *matches.sortedList );
942 else {
943 QStringList l = matches.list();
944 for( QStringList::ConstIterator it = l.begin();
945 it != l.end();
946 ++it )
947 prepend( OSortableItem<QString, int>( 1, *it ) );
948 }
949}
950
951OCompletionMatches::~OCompletionMatches()
952{
953}
954
955QStringList OCompletionMatches::list( bool sort_P ) const
956{
957 if( _sorting && sort_P )
958 const_cast< OCompletionMatches* >( this )->sort();
959 QStringList stringList;
960 // high weight == sorted last -> reverse the sorting here
961 for ( ConstIterator it = begin(); it != end(); ++it )
962 stringList.prepend( (*it).value() );
963 return stringList;
964}
965
966void OCompletionMatches::removeDuplicates()
967{
968 Iterator it1, it2;
969 for ( it1 = begin(); it1 != end(); ++it1 ) {
970 for ( (it2 = it1), ++it2; it2 != end();) {
971 if( (*it1).value() == (*it2).value()) {
972 // use the max height
973 //(*it1).first = kMax( (*it1).index(), (*it2).index());
974 (*it1).first = (*it2).index() < (*it1).index() ? (*it1).index() : (*it2).index();
975 it2 = remove( it2 );
976 continue;
977 }
978 ++it2;
979 }
980 }
981}
982
983void OCompTreeNodeList::append(OCompTreeNode *item)
984{
985 m_count++;
986 if (!last) {
987 last = item;
988 last->next = 0;
989 first = item;
990 return;
991 }
992 last->next = item;
993 item->next = 0;
994 last = item;
995}
996
997void OCompTreeNodeList::prepend(OCompTreeNode *item)
998{
999 m_count++;
1000 if (!last) {
1001 last = item;
1002 last->next = 0;
1003 first = item;
1004 return;
1005 }
1006 item->next = first;
1007 first = item;
1008}
1009
1010void OCompTreeNodeList::insert(OCompTreeNode *after, OCompTreeNode *item)
1011{
1012 if (!after) {
1013 append(item);
1014 return;
1015 }
1016
1017 m_count++;
1018
1019 item->next = after->next;
1020 after->next = item;
1021
1022 if (after == last)
1023 last = item;
1024}
1025
1026OCompTreeNode *OCompTreeNodeList::remove(OCompTreeNode *item)
1027{
1028 if (!first || !item)
1029 return 0;
1030 OCompTreeNode *cur = 0;
1031
1032 if (item == first)
1033 first = first->next;
1034 else {
1035 cur = first;
1036 while (cur && cur->next != item) cur = cur->next;
1037 if (!cur)
1038 return 0;
1039 cur->next = item->next;
1040 }
1041 if (item == last)
1042 last = cur;
1043 m_count--;
1044 return item;
1045}
1046
1047OCompTreeNode *OCompTreeNodeList::at(uint index) const
1048{
1049 OCompTreeNode *cur = first;
1050 while (index-- && cur) cur = cur->next;
1051 return cur;
1052}
1053
1054// FIXME: Revise for Opie?
1055//OZoneAllocator OCompTreeNode::alloc(8192);
1056
1057//void OCompletion::virtual_hook( int, void* )
1058//{ /*BASE::virtual_hook( id, data );*/ }
1059
1060//void OCompletionBase::virtual_hook( int, void* )
1061//{ /*BASE::virtual_hook( id, data );*/ }
diff --git a/libopie2/qt3/opiecore/ocompletion.h b/libopie2/qt3/opiecore/ocompletion.h
new file mode 100644
index 0000000..0317c1b
--- a/dev/null
+++ b/libopie2/qt3/opiecore/ocompletion.h
@@ -0,0 +1,603 @@
1/*
2                 This file is part of the Opie Project
3 Originally part of the KDE Project
4 Copyright (C) 1999,2000 Carsten Pfeiffer <pfeiffer@kde.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29*/
30
31#ifndef OCOMPLETION_H
32#define OCOMPLETION_H
33
34/* QT */
35
36#include <qmap.h>
37#include <qlist.h>
38#include <qobject.h>
39#include <qstring.h>
40#include <qstringlist.h>
41#include <qguardedptr.h>
42
43/* OPIE */
44
45#include <opie2/oglobalsettings.h>
46#include <opie2/osortablevaluelist.h>
47
48/* FORWARDS */
49
50class OCompTreeNode;
51class OCompletionPrivate;
52class OCompletionBasePrivate;
53class OCompletionMatchesWrapper;
54class OCompletionMatches;
55class QPopupMenu;
56
57// FIXME: Do we need special ShortCut handling in Opie? If so, revise this.
58class OShortcut
59{
60public:
61 bool isNull() const { return true; };
62 bool operator == ( const OShortcut& bla ) const { return false; };
63};
64
65
66/**
67 * This class offers easy use of "auto-completion", "manual-completion" or
68 * "shell completion" on QString objects. A common use is completing filenames
69 * or URLs (see @ref OURLCompletion()).
70 * But it is not limited to URL-completion -- everything should be completable!
71 * The user should be able to complete email-addresses, telephone-numbers,
72 * commands, SQL queries, ...
73 * Every time your program knows what the user can type into an edit-field, you
74 * should offer completion. With OCompletion, this is very easy, and if you are
75 * using a line edit widget (@ref OLineEdit), it is even more easy.
76 * Basically, you tell a OCompletion object what strings should be completable
77 * and whenever completion should be invoked, you call @ref makeCompletion().
78 * OLineEdit and (an editable) OComboBox even do this automatically for you.
79 *
80 * OCompletion offers the completed string via the signal @ref match() and
81 * all matching strings (when the result is ambiguous) via the method
82 * @ref allMatches().
83 *
84 * Notice: auto-completion, shell completion and manual completion work
85 * slightly differently:
86 *
87 * @li auto-completion always returns a complete item as match.
88 * When more than one matching items are available, it will deliver just
89 * the first (depending on sorting order) item. Iterating over all matches
90 * is possible via @ref nextMatch() and @ref previousMatch().
91 *
92 * @li popup-completion works in the same way, the only difference being that
93 * the completed items are not put into the edit-widget, but into a
94 * separate popup-box.
95 *
96 * @li manual completion works the same way as auto-completion, the
97 * subtle difference is, that it isn't invoked automatically while the user
98 * is typing, but only when the user presses a special key. The difference
99 * of manual and auto-completion is therefore only visible in UI classes,
100 * OCompletion needs to know whether to deliver partial matches
101 * (shell completion) or whole matches (auto/manual completion), therefore
102 * @ref OGlobalSettings::CompletionMan and
103 * @ref OGlobalSettings::CompletionAuto have the exact same effect in
104 * OCompletion.
105 *
106 * @li shell completion works like how shells complete filenames:
107 * when multiple matches are available, the longest possible string of all
108 * matches is returned (i.e. only a partial item).
109 * Iterating over all matching items (complete, not partial) is possible
110 * via @ref nextMatch() and @ref previousMatch().
111 *
112 * You don't have to worry much about that though, OCompletion handles
113 * that for you, according to the setting @ref setCompletionMode().
114 * The default setting is globally configured by the user and read
115 * from @ref OGlobalSettings::completionMode().
116 *
117 * A short example:
118 * <pre>
119 * OCompletion completion;
120 * completion.setOrder( OCompletion::Sorted );
121 * completion.addItem( "pfeiffer@kde.org" );
122 * completion.addItem( "coolo@kde.org" );
123 * completion.addItem( "carpdjih@sp.zrz.tu-berlin.de" );
124 * completion.addItem( "carp@cs.tu-berlin.de" );
125 *
126 * cout << completion.makeCompletion( "ca" ).latin1() << endl;
127 * </pre>
128 * In shell-completion-mode, this will be "carp"; in auto-completion-
129 * mode it will be "carp@cs.tu-berlin.de", as that is alphabetically
130 * smaller.
131 * If setOrder was set to Insertion, "carpdjih@sp.zrz.tu-berlin.de"
132 * would be completed in auto-completion-mode, as that was inserted before
133 * "carp@cs.tu-berlin.de".
134 *
135 * You can dynamically update the completable items by removing and adding them
136 * whenever you want.
137 * For advanced usage, you could even use multiple OCompletion objects. E.g.
138 * imagine an editor like kwrite with multiple open files. You could store
139 * items of each file in a different OCompletion object, so that you know (and
140 * tell the user) where a completion comes from.
141 *
142 * Note: OCompletion does not work with strings that contain 0x0 characters
143 * (unicode nul), as this is used internally as a delimiter.
144 *
145 * You may inherit from OCompletion and override @ref makeCompletion() in
146 * special cases (like reading directories/urls and then supplying the
147 * contents to OCompletion, as OURLCompletion does), but generally, this is
148 * not necessary.
149 *
150 *
151 * @short A generic class for completing QStrings
152 * @author Carsten Pfeiffer <pfeiffer@kde.org>
153 * @version $Id$
154 */
155
156class OCompletion : public QObject
157{
158 Q_ENUMS( CompOrder )
159 Q_PROPERTY( CompOrder order READ order WRITE setOrder )
160 Q_PROPERTY( bool ignoreCase READ ignoreCase WRITE setIgnoreCase )
161 Q_PROPERTY( QStringList items READ items WRITE setItems )
162 Q_OBJECT
163
164 public:
165 /**
166 * Constants that represent the order in which OCompletion performs
167 * completion-lookups.
168 */
169 enum CompOrder { Sorted, Insertion, Weighted };
170
171 /**
172 * Constructor, nothing special here :)
173 */
174 OCompletion();
175
176 // FIXME: copy constructor, assignment constructor...
177
178 /**
179 * Destructor, nothing special here, either.
180 */
181 virtual ~OCompletion();
182
183 /**
184 * Attempts to find an item in the list of available completions,
185 * that begins with @p string. Will either return the first matching item
186 * (if there is more than one match) or QString::null, if no match was
187 * found.
188 *
189 * In the latter case, a sound will be issued, depending on
190 * @ref isSoundsEnabled().
191 * If a match was found, it will also be emitted via the signal
192 * @ref match().
193 *
194 * If this is called twice or more often with the same string while no
195 * items were added or removed in the meantime, all available completions
196 * will be emitted via the signal @ref matches().
197 * This happens only in shell-completion-mode.
198 *
199 * @returns the matching item, or QString::null if there is no matching
200 * item.
201 * @see #slotMakeCompletion
202 * @see #substringCompletion
203 */
204 virtual QString makeCompletion( const QString& string );
205
206 /**
207 * @returns a list of items which all contain @p text as a substring,
208 * i.e. not necessarily at the beginning.
209 *
210 * @see #makeCompletion
211 */
212 QStringList substringCompletion( const QString& string ) const;
213
214 /**
215 * @returns the next item from the matching-items-list.
216 * When reaching the beginning, the list is rotated so it will return the
217 * last match and a sound is issued (depending on @ref isSoundsEnabled()).
218 * When there is no match, QString::null is returned and
219 * a sound is be issued.
220 * @see #slotPreviousMatch
221 */
222 QString previousMatch();
223
224 /**
225 * @returns the previous item from the matching-items-list
226 * When reaching the last item, the list is rotated, so it will return
227 * the first match and a sound is issued (depending on
228 * @ref isSoundsEnabled()). When there is no match, QString::null is
229 * returned and a sound is issued.
230 * @see #slotNextMatch
231 */
232 QString nextMatch();
233
234 /**
235 * @returns the last match. Might be useful if you need to check whether
236 * a completion is different from the last one.
237 * QString::null is returned when there is no last match.
238 */
239 virtual const QString& lastMatch() const { return myLastMatch; }
240
241 /**
242 * Returns a list of all items inserted into OCompletion. This is useful
243 * if you need to save the state of a OCompletion object and restore it
244 * later.
245 *
246 * Important note: when @ref order() == Weighted, then every item in the
247 * stringlist has its weight appended, delimited by a colon. E.g. an item
248 * "www.kde.org" might look like "www.kde.org:4", where 4 is the weight.
249 *
250 * This is necessary so that you can save the items along with its
251 * weighting on disk and load them back with @ref setItems(), restoring its
252 * weight as well. If you really don't want the appended weightings, call
253 * @ref setOrder( OCompletion::Insertion )
254 * before calling items().
255 *
256 * @returns a list of all items
257 * @see #setItems
258 */
259 QStringList items() const;
260
261 /**
262 * Sets the completion mode to Auto/Manual, Shell or None.
263 * If you don't set the mode explicitly, the global default value
264 * OGlobalSettings::completionMode() is used.
265 * @ref OGlobalSettings::CompletionNone disables completion.
266 * @see #completionMode
267 * @see #OGlobalSettings::completionMode
268 */
269 virtual void setCompletionMode( OGlobalSettings::Completion mode );
270
271 /**
272 * @returns the current completion mode.
273 * May be different from @ref OGlobalSettings::completionMode(), if you
274 * explicitly called @ref setCompletionMode().
275 * @see #setCompletionMode
276 */
277 OGlobalSettings::Completion completionMode() const { return myCompletionMode; };
278
279 /**
280 * OCompletion offers three different ways in which it offers its items:
281 * @li in the order of insertion
282 * @li sorted alphabetically
283 * @li weighted
284 *
285 * Choosing weighted makes OCompletion perform an implicit weighting based
286 * on how often an item is inserted. Imagine a web browser with a location
287 * bar, where the user enters URLs. The more often a URL is entered, the
288 * higher priority it gets.
289 *
290 * Note: Setting the order to sorted only affects new inserted items,
291 * already existing items will stay in the current order. So you probably
292 * want to call setOrder( Sorted ) before inserting items, when you want
293 * everything sorted.
294 *
295 * Default is insertion order
296 * @see #order
297 */
298 virtual void setOrder( CompOrder order );
299
300 /**
301 * @returns the current completion order.
302 * @see #setOrder
303 */
304 CompOrder order() const { return myOrder; }
305
306 /**
307 * Setting this to true makes OCompletion behave case insensitively.
308 * E.g. makeCompletion( "CA" ); might return "carp@cs.tu-berlin.de".
309 * Default is false (case sensitive).
310 * @see #ignoreCase
311 */
312 virtual void setIgnoreCase( bool ignoreCase );
313
314 /**
315 * @returns whether OCompletion acts case insensitively or not.
316 * Default is false (case sensitive).
317 * @see #setIgnoreCase
318 */
319 bool ignoreCase() const { return myIgnoreCase; };
320
321 /**
322 * @returns a list of all items matching the last completed string.
323 * Might take some time, when you have LOTS of items.
324 *
325 * @see #substringCompletion
326 */
327 QStringList allMatches();
328
329 /**
330 * @returns a list of all items matching @p string.
331 */
332 QStringList allMatches( const QString& string );
333
334 /**
335 * @returns a list of all items matching the last completed string.
336 * Might take some time, when you have LOTS of items.
337 * The matches are returned as OCompletionMatches, which also
338 * keeps the weight of the matches, allowing
339 * you to modify some matches or merge them with matches
340 * from another call to allWeightedMatches(), and sort the matches
341 * after that in order to have the matches ordered correctly
342 *
343 * @see #substringCompletion
344 */
345 OCompletionMatches allWeightedMatches();
346
347 /**
348 * @returns a list of all items matching @p string.
349 */
350 OCompletionMatches allWeightedMatches( const QString& string );
351
352 /**
353 * Enables/disables playing a sound when
354 * @li @ref makeCompletion() can't find a match
355 * @li there is a partial completion (= multiple matches in
356 * Shell-completion mode)
357 * @li @ref nextMatch() or @ref previousMatch() hit the last possible
358 * match -> rotation
359 *
360 * For playing the sounds, @ref ONotifyClient() is used. // FIXME: Revise this for Opie
361 *
362 * @see #isSoundsEnabled
363 */
364 virtual void setEnableSounds( bool enable ) { myBeep = enable; }
365
366 /**
367 * Tells you whether OCompletion will play sounds on certain occasions.
368 * Default is enabled
369 * @see #enableSounds
370 * @see #disableSounds
371 */
372 bool isSoundsEnabled() const { return myBeep; };
373
374 /**
375 * @returns true when more than one match is found
376 * @see #multipleMatches
377 */
378 bool hasMultipleMatches() const { return myHasMultipleMatches; };
379
380 public slots:
381 /**
382 * Attempts to complete "string" and emits the completion via @ref match().
383 * Same as @ref makeCompletion() (just as a slot).
384 * @see #makeCompletion
385 */
386 void slotMakeCompletion( const QString& string ) { (void) makeCompletion( string ); };
387
388 /**
389 * Searches the previous matching item and emits it via @ref match()
390 * Same as @ref previousMatch() (just as a slot).
391 * @see #previousMatch
392 */
393 void slotPreviousMatch() { (void) previousMatch(); };
394
395 /**
396 * Searches the next matching item and emits it via @ref match()
397 * Same as @ref nextMatch() (just as a slot).
398 * @see #nextMatch
399 */
400 void slotNextMatch() { (void) nextMatch(); };
401
402 /**
403 * Inserts @p items into the list of possible completions.
404 * Does the same as @ref setItems(), but does not call @ref clear() before.
405 */
406 void insertItems( const QStringList& items );
407
408 /**
409 * Sets the list of items available for completion. Removes all previous
410 * items.
411 *
412 * Notice: when order() == Weighted, then the weighting is looked up for
413 * every item in the stringlist. Every item should have ":number" appended,
414 * where number is an unsigned integer, specifying the weighting.
415 *
416 * If you don't like this, call
417 * setOrder( OCompletion::Insertion )
418 * before calling setItems().
419 *
420 * @see #items
421 */
422 virtual void setItems( const QStringList& );
423
424 /**
425 * Adds an item to the list of available completions.
426 * Resets the current item-state (@ref previousMatch() and @ref nextMatch()
427 * won't work anymore).
428 */
429 void addItem( const QString& );
430
431 /**
432 * Adds an item to the list of available completions.
433 * Resets the current item-state (@ref previousMatch() and @ref nextMatch()
434 * won't work anymore).
435 *
436 * Sets the weighting of the item to @p weight or adds it to the current
437 * weighting if the item is already available. The weight has to be greater
438 * than 1 to take effect (default weight is 1).
439 */
440 void addItem( const QString&, uint weight );
441
442 /**
443 * Removes an item from the list of available completions.
444 * Resets the current item-state (@ref previousMatch() and @ref nextMatch()
445 * won't work anymore).
446 */
447 void removeItem( const QString& );
448
449 /**
450 * Removes all inserted items.
451 */
452 virtual void clear();
453
454 signals:
455 /**
456 * The matching item. Will be emitted by @ref makeCompletion(),
457 * @ref previousMatch() or @ref nextMatch(). May be QString::null if there
458 * is no matching item.
459 */
460 void match( const QString& );
461
462 /**
463 * All matching items. Will be emitted by @ref makeCompletion() in shell-
464 * completion-mode, when the same string is passed to makeCompletion twice
465 * or more often.
466 */
467 void matches( const QStringList& );
468
469 /**
470 * This signal is emitted, when calling @ref makeCompletion() and more than
471 * one matching item is found.
472 * @see #hasMultipleMatches
473 */
474 void multipleMatches();
475
476 protected:
477 /**
478 * This method is called after a completion is found and before the
479 * matching string is emitted. You can override this method to modify the
480 * string that will be emitted.
481 * This is necessary e.g. in @ref OURLCompletion(), where files with spaces
482 * in their names are shown escaped ("filename\ with\ spaces"), but stored
483 * unescaped inside OCompletion.
484 * Never delete that pointer!
485 *
486 * Default implementation does nothing.
487 * @see #postProcessMatches
488 */
489 virtual void postProcessMatch( QString * /*match*/ ) const {}
490
491 /**
492 * This method is called before a list of all available completions is
493 * emitted via @ref matches. You can override this method to modify the
494 * found items before @ref match() or @ref matches() are emitted.
495 * Never delete that pointer!
496 *
497 * Default implementation does nothing.
498 * @see #postProcessMatch
499 */
500 virtual void postProcessMatches( QStringList * /*matches*/ ) const {}
501
502 /**
503 * This method is called before a list of all available completions is
504 * emitted via @ref matches. You can override this method to modify the
505 * found items before @ref match() or @ref matches() are emitted.
506 * Never delete that pointer!
507 *
508 * Default implementation does nothing.
509 * @see #postProcessMatch
510 */
511 virtual void postProcessMatches( OCompletionMatches * /*matches*/ ) const {}
512
513private:
514 void addWeightedItem( const QString& );
515 QString findCompletion( const QString& string );
516 void findAllCompletions( const QString&, OCompletionMatchesWrapper *matches, bool& hasMultipleMatches ) const;
517
518 void extractStringsFromNode( const OCompTreeNode *,
519 const QString& beginning,
520 OCompletionMatchesWrapper *matches,
521 bool addWeight = false ) const;
522 void extractStringsFromNodeCI( const OCompTreeNode *,
523 const QString& beginning,
524 const QString& restString,
525 OCompletionMatchesWrapper *matches) const;
526
527 enum BeepMode { NoMatch, PartialMatch, Rotation };
528 void doBeep( BeepMode ) const;
529
530 OGlobalSettings::Completion myCompletionMode;
531
532 CompOrder myOrder;
533 QString myLastString;
534 QString myLastMatch;
535 QString myCurrentMatch;
536 OCompTreeNode * myTreeRoot;
537 QStringList myRotations;
538 bool myBeep;
539 bool myIgnoreCase;
540 bool myHasMultipleMatches;
541 uint myRotationIndex;
542
543 private:
544 OCompletionPrivate *d;
545};
546
547// some more helper stuff
548typedef OSortableValueList<QString> OCompletionMatchesList;
549class OCompletionMatchesPrivate;
550
551/**
552 * This structure is returned by @ref OCompletion::allWeightedMatches .
553 * It also keeps the weight of the matches, allowing
554 * you to modify some matches or merge them with matches
555 * from another call to allWeightedMatches(), and sort the matches
556 * after that in order to have the matches ordered correctly
557 *
558 * Example (a simplified example of what Oonqueror's completion does):
559 * <pre>
560 * OCompletionMatches matches = completion->allWeightedMatches( location );
561 * if( !location.startsWith( "www." ))
562 matches += completion->allWeightedmatches( "www." + location" );
563 * matches.removeDuplicates();
564 * QStringList list = matches.list();
565 * </pre>
566 *
567 * @short List for keeping matches returned from OCompletion
568 */
569
570class OCompletionMatches
571 : public OCompletionMatchesList
572{
573 public:
574 OCompletionMatches( bool sort );
575 /**
576 * @internal
577 */
578 OCompletionMatches( const OCompletionMatchesWrapper& matches );
579 ~OCompletionMatches();
580 /**
581 * Removes duplicate matches. Needed only when you merged several matches
582 * results and there's a possibility of duplicates.
583 */
584 void removeDuplicates();
585 /**
586 * Returns the matches as a QStringList.
587 * @param sort if false, the matches won't be sorted before the conversion,
588 * use only if you're sure the sorting is not needed
589 */
590 QStringList list( bool sort = true ) const;
591 /**
592 * If sorting() returns false, the matches aren't sorted by their weight,
593 * even if true is passed to list().
594 */
595 bool sorting() const {
596 return _sorting;
597 }
598private:
599 bool _sorting;
600 OCompletionMatchesPrivate* d;
601};
602
603#endif // OCOMPLETION_H
diff --git a/libopie2/qt3/opiecore/ocompletionbase.cpp b/libopie2/qt3/opiecore/ocompletionbase.cpp
new file mode 100644
index 0000000..6ff129a
--- a/dev/null
+++ b/libopie2/qt3/opiecore/ocompletionbase.cpp
@@ -0,0 +1,171 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 Inspired by the KDE completion classes which are
6 Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31*/
32
33#include <opie2/ocompletion.h>
34#include <opie2/ocompletionbase.h>
35
36OCompletionBase::OCompletionBase()
37{
38 m_delegate = 0L;
39 // Assign the default completion type to use.
40 m_iCompletionMode = OGlobalSettings::completionMode();
41
42 // Initialize all key-bindings to 0 by default so that
43 // the event filter will use the global settings.
44 useGlobalKeyBindings();
45
46 // By default we initialize everything to false.
47 // All the variables would be setup properly when
48 // the appropriate member functions are called.
49 setup( false, false, false );
50}
51
52OCompletionBase::~OCompletionBase()
53{
54 if( m_bAutoDelCompObj && m_pCompObj )
55 {
56 delete m_pCompObj;
57 }
58}
59
60void OCompletionBase::setDelegate( OCompletionBase *delegate )
61{
62 m_delegate = delegate;
63
64 if ( m_delegate ) {
65 m_delegate->m_bAutoDelCompObj = m_bAutoDelCompObj;
66 m_delegate->m_bHandleSignals = m_bHandleSignals;
67 m_delegate->m_bEmitSignals = m_bEmitSignals;
68 m_delegate->m_iCompletionMode = m_iCompletionMode;
69 m_delegate->m_keyMap = m_keyMap;
70 }
71}
72
73OCompletion* OCompletionBase::completionObject( bool hsig )
74{
75 if ( m_delegate )
76 return m_delegate->completionObject( hsig );
77
78 if ( !m_pCompObj )
79 {
80 setCompletionObject( new OCompletion(), hsig );
81 m_bAutoDelCompObj = true;
82 }
83 return m_pCompObj;
84}
85
86void OCompletionBase::setCompletionObject( OCompletion* compObj, bool hsig )
87{
88 if ( m_delegate ) {
89 m_delegate->setCompletionObject( compObj, hsig );
90 return;
91 }
92
93 if ( m_bAutoDelCompObj && compObj != m_pCompObj )
94 delete m_pCompObj;
95
96 m_pCompObj = compObj;
97
98 // We emit rotation and completion signals
99 // if completion object is not NULL.
100 setup( false, hsig, !m_pCompObj.isNull() );
101}
102
103// BC: Inline this function and possibly rename it to setHandleEvents??? (DA)
104void OCompletionBase::setHandleSignals( bool handle )
105{
106 if ( m_delegate )
107 m_delegate->setHandleSignals( handle );
108 else
109 m_bHandleSignals = handle;
110}
111
112void OCompletionBase::setCompletionMode( OGlobalSettings::Completion mode )
113{
114 if ( m_delegate ) {
115 m_delegate->setCompletionMode( mode );
116 return;
117 }
118
119 m_iCompletionMode = mode;
120 // Always sync up OCompletion mode with ours as long as we
121 // are performing completions.
122 if( m_pCompObj && m_iCompletionMode != OGlobalSettings::CompletionNone )
123 m_pCompObj->setCompletionMode( m_iCompletionMode );
124}
125
126bool OCompletionBase::setKeyBinding( KeyBindingType item, const OShortcut& cut )
127{
128 if ( m_delegate )
129 return m_delegate->setKeyBinding( item, cut );
130
131
132 if( !cut.isNull() )
133 {
134 for( KeyBindingMap::Iterator it = m_keyMap.begin(); it != m_keyMap.end(); ++it )
135 if( it.data() == cut ) return false;
136 }
137 m_keyMap.replace( item, cut );
138 return true;
139}
140
141void OCompletionBase::useGlobalKeyBindings()
142{
143
144/*
145
146 if ( m_delegate ) {
147 m_delegate->useGlobalKeyBindings();
148 return;
149 }
150
151 m_keyMap.clear();
152 m_keyMap.insert( TextCompletion, 0 );
153 m_keyMap.insert( PrevCompletionMatch, 0 );
154 m_keyMap.insert( NextCompletionMatch, 0 );
155 m_keyMap.insert( SubstringCompletion, 0 );
156
157*/
158
159}
160
161void OCompletionBase::setup( bool autodel, bool hsig, bool esig )
162{
163 if ( m_delegate ) {
164 m_delegate->setup( autodel, hsig, esig );
165 return;
166 }
167
168 m_bAutoDelCompObj = autodel;
169 m_bHandleSignals = hsig;
170 m_bEmitSignals = esig;
171}
diff --git a/libopie2/qt3/opiecore/ocompletionbase.h b/libopie2/qt3/opiecore/ocompletionbase.h
new file mode 100644
index 0000000..517667e
--- a/dev/null
+++ b/libopie2/qt3/opiecore/ocompletionbase.h
@@ -0,0 +1,403 @@
1/*
2                 This file is part of the Opie Project
3
4              Copyright (C) 2003 Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>
5 Inspired by the KDE completion classes which are
6 Copyright (C) 2000 Dawit Alemayehu <adawit@kde.org>
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31*/
32
33#ifndef OCOMPLETIONBASE_H
34#define OCOMPLETIONBASE_H
35
36/**
37 * An abstract base class for adding a completion feature
38 * into widgets.
39 *
40 * This is a convenience class that provides the basic functions
41 * needed to add text completion support into widgets. All that
42 * is required is an implementation for the pure virtual function
43 * @ref setCompletedText. Refer to @ref OLineEdit or @ref OComboBox
44 * to see how easily such support can be added using this as a base
45 * class.
46 *
47 * @short An abstract class for adding text completion support to widgets.
48 * @author Dawit Alemayehu <adawit@kde.org>
49 */
50
51class OCompletionBase
52{
53
54 public:
55
56 /**
57 * Constants that represent the items whose short-cut
58 * key-binding is programmable. The default key-bindings
59 * for these items are defined in @ref OStdAccel.
60 */
61 enum KeyBindingType {
62 /**
63 * Text completion (by default Ctrl-E).
64 */
65 TextCompletion,
66 /**
67 * Switch to previous completion (by default Ctrl-Up).
68 */
69 PrevCompletionMatch,
70 /**
71 * Switch to next completion (by default Ctrl-Down).
72 */
73 NextCompletionMatch,
74 /**
75 * Substring completion (by default Ctrl-T).
76 */
77 SubstringCompletion
78 };
79
80
81 // Map for the key binding types mentioned above.
82 typedef QMap<KeyBindingType, OShortcut> KeyBindingMap;
83
84 /**
85 * Default constructor.
86 */
87 OCompletionBase();
88
89 /**
90 * Destructor.
91 */
92 virtual ~OCompletionBase();
93
94 /**
95 * Returns a pointer to the current completion object.
96 *
97 * If the object does not exist, it is automatically
98 * created. Note that the completion object created
99 * here is used by default to handle the signals
100 * internally. It is also deleted when this object's
101 * destructor is invoked. If you do not want these
102 * default settings, use @ref setAutoDeleteCompletionObject
103 * and @ref setHandleSignals to change the behavior.
104 * Alternatively, you can set the boolean parameter to
105 * false to disable the automatic handling of the signals
106 * by this object. Note that the boolean argument will be
107 * ignored if there already exists a completion object since
108 * no new object needs to be created. You need to use either
109 * @ref setHandleSignals or @ref setCompletionObject for
110 * such cases depending on your requirement.
111 *
112 * @param hsig if true, handles signals internally.
113 * @return a pointer the completion object.
114 */
115 OCompletion* completionObject( bool hsig = true );
116
117 /**
118 * Sets up the completion object to be used.
119 *
120 * This method assigns the completion object and sets it
121 * up to automatically handle the completion and rotation
122 * signals internally. You should use this function if
123 * you want to share one completion object among you widgets
124 * or need to use a customized completion object.
125 *
126 * The object assigned through this method is not deleted
127 * when this object's destructor is invoked unless you
128 * explicitly call @ref setAutoDeleteCompletionObject after
129 * calling this method. Also if you do not want the signals
130 * to be handled by an internal implementation, be sure to
131 * set the bool argument to false.
132 *
133 * This method is also called when a completion-object is created
134 * automatically, when completionObject() is called the first time.
135 *
136 * @param compObj a @ref OCompletion() or a derived child object.
137 * @param hsig if true, handles signals internally.
138 */
139 virtual void setCompletionObject( OCompletion* /*compObj*/, bool hsig = true );
140
141 /**
142 * Enables this object to handle completion and rotation
143 * events internally.
144 *
145 * This function simply assigns a boolean value that
146 * indicates whether it should handle rotation and
147 * completion events or not. Note that this does not
148 * stop the object from emitting signals when these
149 * events occur.
150 *
151 * @param handle if true, handle completion & rotation internally.
152 */
153 virtual void setHandleSignals( bool /*handle*/ );
154
155 /**
156 * Returns true if the completion object is deleted
157 * upon this widget's destruction.
158 *
159 * See @ref setCompletionObject() and @ref enableCompletion()
160 * for details.
161 *
162 * @return true if the completion object
163 */
164 bool isCompletionObjectAutoDeleted() const {
165 return m_delegate ? m_delegate->isCompletionObjectAutoDeleted() : m_bAutoDelCompObj;
166 }
167
168 /**
169 * Sets the completion object when this widget's destructor
170 * is called.
171 *
172 * If the argument is set to true, the completion object
173 * is deleted when this widget's destructor is called.
174 *
175 * @param autoDelete if true, delete completion object on destruction.
176 */
177 void setAutoDeleteCompletionObject( bool autoDelete ) {
178 if ( m_delegate )
179 m_delegate->setAutoDeleteCompletionObject( autoDelete );
180 else
181 m_bAutoDelCompObj = autoDelete;
182 }
183
184 /**
185 * Sets the widget's ability to emit text completion and
186 * rotation signals.
187 *
188 * Invoking this function with @p enable set to @p false will
189 * cause the completion & rotation signals not to be emitted.
190 * However, unlike setting the completion object to @p NULL
191 * using @ref setCompletionObject, disabling the emition of
192 * the signals through this method does not affect the current
193 * completion object.
194 *
195 * There is no need to invoke this function by default. When a
196 * completion object is created through @ref completionObject or
197 * @ref setCompletionObject, these signals are set to emit
198 * automatically. Also note that disabling this signals will not
199 * necessarily interfere with the objects ability to handle these
200 * events internally. See @ref setHandleSignals.
201 *
202 * @param enable if false, disables the emition of completion & rotation signals.
203 */
204 void setEnableSignals( bool enable ) {
205 if ( m_delegate )
206 m_delegate->setEnableSignals( enable );
207 else
208 m_bEmitSignals = enable;
209 }
210
211 /**
212 * Returns true if the object handles the signals
213 *
214 * @return true if this signals are handled internally.
215 */
216 bool handleSignals() const { return m_delegate ? m_delegate->handleSignals() : m_bHandleSignals; }
217
218 /**
219 * Returns true if the object emits the signals
220 *
221 * @return true if signals are emitted
222 */
223 bool emitSignals() const { return m_delegate ? m_delegate->emitSignals() : m_bEmitSignals; }
224
225 /**
226 * Sets the type of completion to be used.
227 *
228 * The completion modes supported are those defined in
229 * @ref OGlobalSettings(). See below.
230 *
231 * @param mode Completion type:
232 * @li CompletionNone: Disables completion feature.
233 * @li CompletionAuto: Attempts to find a match &
234 * fills-in the remaining text.
235 * @li CompletionMan: Acts the same as the above
236 * except the action has to be
237 * manually triggered through
238 * pre-defined completion key.
239 * @li CompletionShell: Mimics the completion feature
240 * found in typical *nix shell
241 * environments.
242 * @li CompletionPopup: Shows all available completions at once,
243 * in a listbox popping up.
244 */
245 virtual void setCompletionMode( OGlobalSettings::Completion mode );
246
247 /**
248 * Returns the current completion mode.
249 *
250 * The return values are of type @ref OGlobalSettings::Completion.
251 * See @ref setCompletionMode() for details.
252 *
253 * @return the completion mode.
254 */
255 OGlobalSettings::Completion completionMode() const {
256 return m_delegate ? m_delegate->completionMode() : m_iCompletionMode;
257 }
258
259 /**
260 * Sets the key-binding to be used for manual text
261 * completion, text rotation in a history list as
262 * well as a completion list.
263 *
264 *
265 * When the keys set by this function are pressed, a
266 * signal defined by the inheriting widget will be activated.
267 * If the default value or 0 is specified by the second
268 * parameter, then the key-binding as defined in the global
269 * setting should be used. This method returns false value
270 * for @p key is negative or the supplied key-binding conflicts
271 * with the ones set for one of the other features.
272 *
273 * NOTE: To use a modifier key (Shift, Ctrl, Alt) as part of
274 * the key-binding simply simply @p sum up the values of the
275 * modifier and the actual key. For example, to use CTRL+E as
276 * a key binding for one of the items, you would simply supply
277 * @p "Qt::CtrlButton + Qt::Key_E" as the second argument to this
278 * function.
279 *
280 * @param item the feature whose key-binding needs to be set:
281 *
282 * @li TextCompletionthe manual completion key-binding.
283 * @li PrevCompletionMatchthe previous match key for multiple completion.
284 * @li NextCompletionMatchthe next match key for for multiple completion.
285 * @li SubstringCompletion the key for substring completion
286 *
287 * @param key key-binding used to rotate down in a list.
288 *
289 * @return true if key-binding can successfully be set.
290 * @see #getKeyBinding
291 */
292 bool setKeyBinding( KeyBindingType /*item*/ , const OShortcut& cut );
293
294 /**
295 * Returns the key-binding used for the specified item.
296 *
297 * This methods returns the key-binding used to activate
298 * the feature feature given by @p item. If the binding
299 * contains modifier key(s), the SUM of the modifier key
300 * and the actual key code are returned.
301 *
302 * @return the key-binding used for the feature given by @p item.
303 * @see #setKeyBinding
304 */
305 const OShortcut& getKeyBinding( KeyBindingType item ) const {
306 return m_delegate ? m_delegate->getKeyBinding( item ) : m_keyMap[ item ];
307 }
308
309 /**
310 * Sets this object to use global values for key-bindings.
311 *
312 * This method changes the values of the key bindings for
313 * rotation and completion features to the default values
314 * provided in OGlobalSettings.
315 *
316 * NOTE: By default inheriting widgets should uses the
317 * global key-bindings so that there will be no need to
318 * call this method.
319 */
320 void useGlobalKeyBindings();
321
322 /**
323 * A pure virtual function that must be implemented by
324 * all inheriting classes.
325 *
326 * This function is intended to allow external completion
327 * implementations to set completed text appropriately. It
328 * is mostly relevant when the completion mode is set to
329 * CompletionAuto and CompletionManual modes. See
330 * @ref OCompletionBase::setCompletedText.
331 * Does nothing in CompletionPopup mode, as all available
332 * matches will be shown in the popup.
333 *
334 * @param text the completed text to be set in the widget.
335 */
336 virtual void setCompletedText( const QString& text ) = 0;
337
338 /**
339 * A pure virtual function that must be implemented by
340 * all inheriting classes.
341 *
342 */
343 virtual void setCompletedItems( const QStringList& items ) = 0;
344
345 /**
346 * Returns a pointer to the completion object.
347 *
348 * This method is only different from @ref completionObject()
349 * in that it does not create a new OCompletion object even if
350 * the internal pointer is @p NULL. Use this method to get the
351 * pointer to a completion object when inheriting so that you
352 * won't inadvertently create it!!
353 *
354 * @returns the completion object or NULL if one does not exist.
355 */
356 OCompletion* compObj() const { return m_delegate ? m_delegate->compObj() : (OCompletion*) m_pCompObj; }
357
358protected:
359 /**
360 * Returns a key-binding map
361 *
362 * This method is the same as @ref getKeyBinding() except it
363 * returns the whole keymap containing the key-bindings.
364 *
365 * @return the key-binding used for the feature given by @p item.
366 */
367 KeyBindingMap getKeyBindings() const { return m_delegate ? m_delegate->getKeyBindings() : m_keyMap; }
368
369 void setDelegate( OCompletionBase *delegate );
370 OCompletionBase *delegate() const { return m_delegate; }
371
372private:
373 // This method simply sets the autodelete boolean for
374 // the completion object, the emit signals and handle
375 // signals internally flags to the provided values.
376 void setup( bool, bool, bool );
377
378 // Flag that determined whether the completion object
379 // should be deleted when this object is destroyed.
380 bool m_bAutoDelCompObj;
381 // Determines whether this widget handles completion signals
382 // internally or not
383 bool m_bHandleSignals;
384 // Determines whether this widget fires rotation signals
385 bool m_bEmitSignals;
386 // Stores the completion mode locally.
387 OGlobalSettings::Completion m_iCompletionMode;
388 // Pointer to Completion object.
389 QGuardedPtr<OCompletion> m_pCompObj;
390 // Keybindings
391 KeyBindingMap m_keyMap;
392 // we may act as a proxy to another OCompletionBase object
393 OCompletionBase *m_delegate;
394
395 // FIXME: Revise this for Opie?
396 //protected:
397 // virtual void virtual_hook( int id, void* data );
398 private:
399 OCompletionBasePrivate *d;
400};
401
402#endif // OCOMPLETIONBASE_H
403
diff --git a/libopie2/qt3/opiecore/opair.h b/libopie2/qt3/opiecore/opair.h
new file mode 100644
index 0000000..26f617d
--- a/dev/null
+++ b/libopie2/qt3/opiecore/opair.h
@@ -0,0 +1,99 @@
1// QPair minus QT_INLINE_TEMPLATE (instead directly using 'inline' directive)
2//FIXME: remove and use qpair.h as soon as we're on Qt3
3
4/****************************************************************************
5**
6** Definition of QPair class
7**
8**
9** Copyright (C) 1992-2001 Trolltech AS. All rights reserved.
10**
11** This file is part of the tools module of the Qt GUI Toolkit.
12**
13** This file may be distributed under the terms of the Q Public License
14** as defined by Trolltech AS of Norway and appearing in the file
15** LICENSE.QPL included in the packaging of this file.
16**
17** This file may be distributed and/or modified under the terms of the
18** GNU General Public License version 2 as published by the Free Software
19** Foundation and appearing in the file LICENSE.GPL included in the
20** packaging of this file.
21**
22** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
23** licenses may use this file in accordance with the Qt Commercial License
24** Agreement provided with the Software.
25**
26** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
27** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28**
29** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
30** information about Qt Commercial License Agreements.
31** See http://www.trolltech.com/qpl/ for QPL licensing information.
32** See http://www.trolltech.com/gpl/ for GPL licensing information.
33**
34** Contact info@trolltech.com if any conditions of this licensing are
35** not clear to you.
36**
37**********************************************************************/
38
39#ifndef QPAIR_H
40#define QPAIR_H
41
42#ifndef QT_H
43#include "qglobal.h"
44#include "qdatastream.h"
45#endif // QT_H
46
47template <class T1, class T2>
48struct QPair
49{
50 typedef T1 first_type;
51 typedef T2 second_type;
52
53 QPair()
54 : first( T1() ), second( T2() )
55 {}
56 QPair( const T1& t1, const T2& t2 )
57 : first( t1 ), second( t2 )
58 {}
59
60 T1 first;
61 T2 second;
62};
63
64template <class T1, class T2>
65inline bool operator==( const QPair<T1, T2>& x, const QPair<T1, T2>& y )
66{
67 return x.first == y.first && x.second == y.second;
68}
69
70template <class T1, class T2>
71inline bool operator<( const QPair<T1, T2>& x, const QPair<T1, T2>& y )
72{
73 return x.first < y.first ||
74 ( !( y.first < x.first ) && x.second < y.second );
75}
76
77template <class T1, class T2>
78inline QPair<T1, T2> qMakePair( const T1& x, const T2& y )
79{
80 return QPair<T1, T2>( x, y );
81}
82
83#ifndef QT_NO_DATASTREAM
84template <class T1, class T2>
85inline QDataStream& operator>>( QDataStream& s, QPair<T1, T2>& p )
86{
87 s >> p.first >> p.second;
88 return s;
89}
90
91template <class T1, class T2>
92inline QDataStream& operator<<( QDataStream& s, const QPair<T1, T2>& p )
93{
94 s << p.first << p.second;
95 return s;
96}
97#endif
98
99#endif
diff --git a/libopie2/qt3/opiecore/osortablevaluelist.h b/libopie2/qt3/opiecore/osortablevaluelist.h
new file mode 100644
index 0000000..f66cf25
--- a/dev/null
+++ b/libopie2/qt3/opiecore/osortablevaluelist.h
@@ -0,0 +1,117 @@
1/*
2                 This file is part of the Opie Project
3 Originally a part of the KDE Project
4 (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29*/
30
31#ifndef OSORTABLEVALUELIST_H
32#define OSORTABLEVALUELIST_H
33
34#if QT_VERSION > 290
35#include <qtl.h>
36#include <qpair.h>
37#else
38#include <opie2/otl.h>
39#include <opie2/opair.h>
40#endif
41#include <qvaluelist.h>
42
43template<class T, class Key = int> class OSortableItem : public QPair<Key,T>
44{
45public:
46 OSortableItem( Key i, const T& t ) : QPair<Key, T>( i, t ) {}
47 OSortableItem( const OSortableItem<T, Key> &rhs )
48 : QPair<Key,T>( rhs.first, rhs.second ) {}
49
50 OSortableItem() {}
51
52 OSortableItem<T, Key> &operator=( const OSortableItem<T, Key>& i ) {
53 first = i.first;
54 second = i.second;
55 return *this;
56 }
57
58 // operators for sorting
59 bool operator> ( const OSortableItem<T, Key>& i2 ) const {
60 return (i2.first < first);
61 }
62 bool operator< ( const OSortableItem<T, Key>& i2 ) const {
63 return (first < i2.first);
64 }
65 bool operator>= ( const OSortableItem<T, Key>& i2 ) const {
66 return (first >= i2.first);
67 }
68 bool operator<= ( const OSortableItem<T, Key>& i2 ) const {
69 return !(i2.first < first);
70 }
71 bool operator== ( const OSortableItem<T, Key>& i2 ) const {
72 return (first == i2.first);
73 }
74 bool operator!= ( const OSortableItem<T, Key>& i2 ) const {
75 return (first != i2.first);
76 }
77
78 T& value() {
79 return second;
80 }
81 const T& value() const {
82 return second;
83 }
84
85 Key index() const {
86 return first;
87 }
88};
89
90
91// convenience
92template <class T, class Key = int>
93class OSortableValueList : public QValueList<OSortableItem<T, Key> >
94{
95public:
96 void insert( Key i, const T& t ) {
97 QValueList<OSortableItem<T, Key> >::append( OSortableItem<T, Key>( i, t ) );
98 }
99 // add more as you please...
100
101 T& operator[]( Key i ) {
102 return QValueList<OSortableItem<T, Key> >::operator[]( i ).value();
103 }
104 const T& operator[]( Key i ) const {
105 return QValueList<OSortableItem<T, Key> >::operator[]( i ).value();
106 }
107
108 void sort() {
109 qHeapSort( *this );
110 }
111};
112
113// template <class T> class OSortableValueListIterator : public QValueListIterator<OSortableItem<T> >
114// {
115// };
116
117#endif // OSORTABLEVALUELIST_H
diff --git a/libopie2/qt3/opiecore/otl.h b/libopie2/qt3/opiecore/otl.h
new file mode 100644
index 0000000..ee2a28e
--- a/dev/null
+++ b/libopie2/qt3/opiecore/otl.h
@@ -0,0 +1,325 @@
1// qtl minus QT_INLINE_TEMPLATE and QT_EXPLICIT (instead directly using 'inline' directive)
2//FIXME: remove and use qtl.h as soon as we're on Qt3
3
4/****************************************************************************
5** $Id$
6**
7** Definition of Qt template library classes
8**
9** Created : 990128
10**
11** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
12**
13** This file is part of the tools module of the Qt GUI Toolkit.
14**
15** This file may be distributed under the terms of the Q Public License
16** as defined by Trolltech AS of Norway and appearing in the file
17** LICENSE.QPL included in the packaging of this file.
18**
19** This file may be distributed and/or modified under the terms of the
20** GNU General Public License version 2 as published by the Free Software
21** Foundation and appearing in the file LICENSE.GPL included in the
22** packaging of this file.
23**
24** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
25** licenses may use this file in accordance with the Qt Commercial License
26** Agreement provided with the Software.
27**
28** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30**
31** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
32** information about Qt Commercial License Agreements.
33** See http://www.trolltech.com/qpl/ for QPL licensing information.
34** See http://www.trolltech.com/gpl/ for GPL licensing information.
35**
36** Contact info@trolltech.com if any conditions of this licensing are
37** not clear to you.
38**
39**********************************************************************/
40
41#ifndef QTL_H
42#define QTL_H
43
44#ifndef QT_H
45#include "qglobal.h"
46#include "qtextstream.h"
47#include "qstring.h"
48#endif // QT_H
49
50#ifndef QT_NO_TEXTSTREAM
51template <class T>
52class QTextOStreamIterator
53{
54protected:
55 QTextOStream& stream;
56 QString separator;
57
58public:
59 QTextOStreamIterator( QTextOStream& s) : stream( s ) {}
60 QTextOStreamIterator( QTextOStream& s, const QString& sep )
61 : stream( s ), separator( sep ) {}
62 QTextOStreamIterator<T>& operator= ( const T& x ) {
63 stream << x;
64 if ( !separator.isEmpty() )
65 stream << separator;
66 return *this;
67 }
68 QTextOStreamIterator<T>& operator*() { return *this; }
69 QTextOStreamIterator<T>& operator++() { return *this; }
70 QTextOStreamIterator<T>& operator++(int) { return *this; }
71};
72#endif //QT_NO_TEXTSTREAM
73
74template <class InputIterator, class OutputIterator>
75inline OutputIterator qCopy( InputIterator _begin, InputIterator _end,
76 OutputIterator _dest )
77{
78 while( _begin != _end )
79 *_dest++ = *_begin++;
80 return _dest;
81}
82
83template <class BiIterator, class BiOutputIterator>
84inline BiOutputIterator qCopyBackward( BiIterator _begin, BiIterator _end,
85 BiOutputIterator _dest )
86{
87 while ( _begin != _end )
88 *--_dest = *--_end;
89 return _dest;
90}
91
92template <class InputIterator1, class InputIterator2>
93inline bool qEqual( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2 )
94{
95 // ### compare using !(*first1 == *first2) in Qt 4.0
96 for ( ; first1 != last1; ++first1, ++first2 )
97 if ( *first1 != *first2 )
98 return FALSE;
99 return TRUE;
100}
101
102template <class ForwardIterator, class T>
103inline void qFill( ForwardIterator first, ForwardIterator last, const T& val )
104{
105 for ( ; first != last; ++first )
106 *first = val;
107}
108
109#if 0
110template <class BiIterator, class OutputIterator>
111inline OutputIterator qReverseCopy( BiIterator _begin, BiIterator _end,
112 OutputIterator _dest )
113{
114 while ( _begin != _end ) {
115 --_end;
116 *_dest = *_end;
117 ++_dest;
118 }
119 return _dest;
120}
121#endif
122
123
124template <class InputIterator, class T>
125inline InputIterator qFind( InputIterator first, InputIterator last,
126 const T& val )
127{
128 while ( first != last && *first != val )
129 ++first;
130 return first;
131}
132
133template <class InputIterator, class T, class Size>
134inline void qCount( InputIterator first, InputIterator last, const T& value,
135 Size& n )
136{
137 for ( ; first != last; ++first )
138 if ( *first == value )
139 ++n;
140}
141
142template <class T>
143inline void qSwap( T& _value1, T& _value2 )
144{
145 T tmp = _value1;
146 _value1 = _value2;
147 _value2 = tmp;
148}
149
150
151template <class InputIterator>
152inline void qBubbleSort( InputIterator b, InputIterator e )
153{
154 // Goto last element;
155 InputIterator last = e;
156 --last;
157 // only one element or no elements ?
158 if ( last == b )
159 return;
160
161 // So we have at least two elements in here
162 while( b != last ) {
163 bool swapped = FALSE;
164 InputIterator swap_pos = b;
165 InputIterator x = e;
166 InputIterator y = x;
167 y--;
168 do {
169 --x;
170 --y;
171 if ( *x < *y ) {
172 swapped = TRUE;
173 qSwap( *x, *y );
174 swap_pos = y;
175 }
176 } while( y != b );
177 if ( !swapped )
178 return;
179 b = swap_pos;
180 b++;
181 }
182}
183
184
185template <class Container>
186inline void qBubbleSort( Container &c )
187{
188 qBubbleSort( c.begin(), c.end() );
189}
190
191
192template <class Value>
193inline void qHeapSortPushDown( Value* heap, int first, int last )
194{
195 int r = first;
196 while ( r <= last / 2 ) {
197 if ( last == 2 * r ) {
198 // node r has only one child
199 if ( heap[2 * r] < heap[r] )
200 qSwap( heap[r], heap[2 * r] );
201 r = last;
202 } else {
203 // node r has two children
204 if ( heap[2 * r] < heap[r] && !(heap[2 * r + 1] < heap[2 * r]) ) {
205 // swap with left child
206 qSwap( heap[r], heap[2 * r] );
207 r *= 2;
208 } else if ( heap[2 * r + 1] < heap[r]
209 && heap[2 * r + 1] < heap[2 * r] ) {
210 // swap with right child
211 qSwap( heap[r], heap[2 * r + 1] );
212 r = 2 * r + 1;
213 } else {
214 r = last;
215 }
216 }
217 }
218}
219
220
221template <class InputIterator, class Value>
222inline void qHeapSortHelper( InputIterator b, InputIterator e, Value, uint n )
223{
224 // Create the heap
225 InputIterator insert = b;
226 Value* realheap = new Value[n];
227 // Wow, what a fake. But I want the heap to be indexed as 1...n
228 Value* heap = realheap - 1;
229 int size = 0;
230 for( ; insert != e; ++insert ) {
231 heap[++size] = *insert;
232 int i = size;
233 while( i > 1 && heap[i] < heap[i / 2] ) {
234 qSwap( heap[i], heap[i / 2] );
235 i /= 2;
236 }
237 }
238
239 // Now do the sorting
240 for( uint i = n; i > 0; i-- ) {
241 *b++ = heap[1];
242 if ( i > 1 ) {
243 heap[1] = heap[i];
244 qHeapSortPushDown( heap, 1, (int)i - 1 );
245 }
246 }
247
248 delete[] realheap;
249}
250
251
252template <class InputIterator>
253inline void qHeapSort( InputIterator b, InputIterator e )
254{
255 // Empty ?
256 if ( b == e )
257 return;
258
259 // How many entries have to be sorted ?
260 InputIterator it = b;
261 uint n = 0;
262 while ( it != e ) {
263 ++n;
264 ++it;
265 }
266
267 // The second last parameter is a hack to retrieve the value type
268 // Do the real sorting here
269 qHeapSortHelper( b, e, *b, n );
270}
271
272
273template <class Container>
274inline void qHeapSort( Container &c )
275{
276 if ( c.begin() == c.end() )
277 return;
278
279 // The second last parameter is a hack to retrieve the value type
280 // Do the real sorting here
281 qHeapSortHelper( c.begin(), c.end(), *(c.begin()), (uint)c.count() );
282}
283
284template <class Container>
285class QBackInsertIterator
286{
287public:
288 QBackInsertIterator( Container &c )
289 : container( &c )
290 {
291 }
292
293 QBackInsertIterator<Container>&
294 operator=( const typename Container::value_type &value )
295 {
296 container->push_back( value );
297 return *this;
298 }
299
300 QBackInsertIterator<Container>& operator*()
301 {
302 return *this;
303 }
304
305 QBackInsertIterator<Container>& operator++()
306 {
307 return *this;
308 }
309
310 QBackInsertIterator<Container>& operator++(int)
311 {
312 return *this;
313 }
314
315protected:
316 Container *container;
317};
318
319template <class Container>
320inline QBackInsertIterator<Container> qBackInserter( Container &c )
321{
322 return QBackInsertIterator<Container>( c );
323}
324
325#endif