|
|
|
/**********************************************************************
|
|
|
|
**
|
|
|
|
**
|
|
|
|
** Implementation of QComboView widget class
|
|
|
|
**
|
|
|
|
** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
|
|
|
|
** Copyright (C) 2003 Alexander Dymo <cloudtemple@mksat.net>
|
|
|
|
**
|
|
|
|
** This file may be distributed and/or modified under the terms of the
|
|
|
|
** GNU General Public License version 2 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
|
|
|
** packaging of this file.
|
|
|
|
**
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#include "qcomboview.h"
|
|
|
|
#include <tdeversion.h>
|
|
|
|
#ifndef TQT_NO_COMBOBOX
|
|
|
|
#include "tqpopupmenu.h"
|
|
|
|
#include "tqlistview.h"
|
|
|
|
#include "tqpainter.h"
|
|
|
|
#include "tqdrawutil.h"
|
|
|
|
#include "tqstrlist.h"
|
|
|
|
#include "tqpixmap.h"
|
|
|
|
#include "tqtimer.h"
|
|
|
|
#include "tqapplication.h"
|
|
|
|
#include "tqlineedit.h"
|
|
|
|
#include "tqbitmap.h"
|
|
|
|
#include "tqeffects_p.h"
|
|
|
|
#include "tqstringlist.h"
|
|
|
|
#include "tqcombobox.h"
|
|
|
|
#include "tqstyle.h"
|
|
|
|
#include "tqheader.h"
|
|
|
|
#include <limits.h>
|
|
|
|
|
|
|
|
class QComboViewData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
QComboViewData( QComboView *cb ): current(0), lView( 0 ), combo( cb )
|
|
|
|
{
|
|
|
|
duplicatesEnabled = TRUE;
|
|
|
|
cb->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Fixed ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
inline TQListView * listView() { return lView; }
|
|
|
|
void updateLinedGeometry();
|
|
|
|
|
|
|
|
void setListView( TQListView *l ) { lView = l ;
|
|
|
|
l->setMouseTracking( TRUE );}
|
|
|
|
|
|
|
|
TQListViewItem *current;
|
|
|
|
int maxCount;
|
|
|
|
int sizeLimit;
|
|
|
|
QComboView::Policy p;
|
|
|
|
bool autoresize;
|
|
|
|
bool poppedUp;
|
|
|
|
bool mouseWasInsidePopup;
|
|
|
|
bool arrowPressed;
|
|
|
|
bool arrowDown;
|
|
|
|
bool discardNextMousePress;
|
|
|
|
bool shortClick;
|
|
|
|
bool useCompletion;
|
|
|
|
bool completeNow;
|
|
|
|
int completeAt;
|
|
|
|
bool duplicatesEnabled;
|
|
|
|
int fullHeight, currHeight;
|
|
|
|
|
|
|
|
TQLineEdit * ed; // /bin/ed rules!
|
|
|
|
TQTimer *completionTimer;
|
|
|
|
|
|
|
|
TQSize sizeHint;
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool usinglView;
|
|
|
|
TQListView *lView;
|
|
|
|
QComboView *combo;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
void QComboViewData::updateLinedGeometry()
|
|
|
|
{
|
|
|
|
if ( !ed || !combo )
|
|
|
|
return;
|
|
|
|
TQRect r = TQStyle::visualRect( combo->style().querySubControlMetrics(TQStyle::CC_ComboBox, combo,
|
|
|
|
TQStyle::SC_ComboBoxEditField), combo );
|
|
|
|
|
|
|
|
// tqWarning("updateLinedGeometry(): currentItem is %d", combo->currentItem() == 0 ? 0 : 1);
|
|
|
|
const TQPixmap *pix = combo->currentItem() ? combo->currentItem()->pixmap(0) : 0;
|
|
|
|
if ( pix && pix->width() < r.width() )
|
|
|
|
r.setLeft( r.left() + pix->width() + 4 );
|
|
|
|
if ( r != ed->geometry() )
|
|
|
|
ed->setGeometry( r );
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool checkInsertIndex( const char *method, const char * name,
|
|
|
|
int count, int *index)
|
|
|
|
{
|
|
|
|
bool range_err = (*index > count);
|
|
|
|
#if defined(TQT_CHECK_RANGE)
|
|
|
|
if ( range_err )
|
|
|
|
tqWarning( "QComboView::%s: (%s) Index %d out of range",
|
|
|
|
method, name ? name : "<no name>", *index );
|
|
|
|
#else
|
|
|
|
Q_UNUSED( method )
|
|
|
|
Q_UNUSED( name )
|
|
|
|
#endif
|
|
|
|
if ( *index < 0 ) // append
|
|
|
|
*index = count;
|
|
|
|
return !range_err;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline bool checkIndex( const char *method, const char * name,
|
|
|
|
int count, int index )
|
|
|
|
{
|
|
|
|
bool range_err = (index >= count);
|
|
|
|
#if defined(TQT_CHECK_RANGE)
|
|
|
|
if ( range_err )
|
|
|
|
tqWarning( "QComboView::%s: (%s) Index %i out of range",
|
|
|
|
method, name ? name : "<no name>", index );
|
|
|
|
#else
|
|
|
|
Q_UNUSED( method )
|
|
|
|
Q_UNUSED( name )
|
|
|
|
#endif
|
|
|
|
return !range_err;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Constructs a combobox with a maximum size and either Motif 2.0 or
|
|
|
|
Windows look and feel.
|
|
|
|
|
|
|
|
The input field can be edited if \a rw is TRUE, otherwise the user
|
|
|
|
may only choose one of the items in the combobox.
|
|
|
|
|
|
|
|
The \a parent and \a name arguments are passed on to the TQWidget
|
|
|
|
constructor.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
QComboView::QComboView( bool rw, TQWidget *parent, const char *name )
|
|
|
|
: TQWidget( parent, name, WResizeNoErase )
|
|
|
|
{
|
|
|
|
d = new QComboViewData( this );
|
|
|
|
setUpListView();
|
|
|
|
|
|
|
|
d->current = 0;
|
|
|
|
d->maxCount = INT_MAX;
|
|
|
|
setSizeLimit(10);
|
|
|
|
d->p = AtBottom;
|
|
|
|
d->autoresize = FALSE;
|
|
|
|
d->poppedUp = FALSE;
|
|
|
|
d->arrowDown = FALSE;
|
|
|
|
d->discardNextMousePress = FALSE;
|
|
|
|
d->shortClick = FALSE;
|
|
|
|
d->useCompletion = FALSE;
|
|
|
|
d->completeAt = 0;
|
|
|
|
d->completeNow = FALSE;
|
|
|
|
d->completionTimer = new TQTimer( this );
|
|
|
|
|
|
|
|
setFocusPolicy( TQ_StrongFocus );
|
|
|
|
|
|
|
|
d->ed = 0;
|
|
|
|
if ( rw )
|
|
|
|
setUpLineEdit();
|
|
|
|
setBackgroundMode( PaletteButton, PaletteBase );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Destroys the combobox.
|
|
|
|
*/
|
|
|
|
|
|
|
|
QComboView::~QComboView()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QComboView::setDuplicatesEnabled( bool enable )
|
|
|
|
{
|
|
|
|
d->duplicatesEnabled = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QComboView::duplicatesEnabled() const
|
|
|
|
{
|
|
|
|
return d->duplicatesEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
int QComboView::childCount() const
|
|
|
|
{
|
|
|
|
return d->listView()->childCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Removes all comboview items.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::clear()
|
|
|
|
{
|
|
|
|
d->listView()->resize( 0, 0 );
|
|
|
|
d->listView()->clear();
|
|
|
|
|
|
|
|
d->current = 0;
|
|
|
|
if ( d->ed ) {
|
|
|
|
d->ed->setText( TQString::fromLatin1("") );
|
|
|
|
d->updateLinedGeometry();
|
|
|
|
}
|
|
|
|
currentChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQListViewItem *QComboView::currentItem() const
|
|
|
|
{
|
|
|
|
return d->current;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QComboView::setCurrentItem( TQListViewItem *item )
|
|
|
|
{
|
|
|
|
if ( item == d->current && !d->ed ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!item)
|
|
|
|
{
|
|
|
|
d->current = 0;
|
|
|
|
if ( d->ed ) {
|
|
|
|
// d->ed->setText( "" );
|
|
|
|
d->updateLinedGeometry();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->current = item;
|
|
|
|
d->completeAt = 0;
|
|
|
|
if ( d->ed ) {
|
|
|
|
d->ed->setText( item->text(0) );
|
|
|
|
// tqWarning("setCurrentItem( %s )", item->text(0).latin1());
|
|
|
|
d->updateLinedGeometry();
|
|
|
|
}
|
|
|
|
if ( d->listView() ) {
|
|
|
|
d->listView()->setCurrentItem( item );
|
|
|
|
} else {
|
|
|
|
internalHighlight( item );
|
|
|
|
// internalActivate( item ); ### this leads to weird behavior, as in 3.0.1
|
|
|
|
}
|
|
|
|
|
|
|
|
currentChanged();
|
|
|
|
|
|
|
|
d->listView()->ensureItemVisible(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QComboView::autoResize() const
|
|
|
|
{
|
|
|
|
return d->autoresize;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QComboView::setAutoResize( bool enable )
|
|
|
|
{
|
|
|
|
if ( (bool)d->autoresize != enable ) {
|
|
|
|
d->autoresize = enable;
|
|
|
|
if ( enable )
|
|
|
|
adjustSize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
reimp
|
|
|
|
|
|
|
|
This implementation caches the size hint to avoid resizing when
|
|
|
|
the contents change dynamically. To invalidate the cached value
|
|
|
|
call setFont().
|
|
|
|
*/
|
|
|
|
TQSize QComboView::sizeHint() const
|
|
|
|
{
|
|
|
|
if ( isVisible() && d->sizeHint.isValid() )
|
|
|
|
return d->sizeHint;
|
|
|
|
|
|
|
|
constPolish();
|
|
|
|
// int i, w;
|
|
|
|
TQFontMetrics fm = fontMetrics();
|
|
|
|
|
|
|
|
int maxW = childCount() ? 18 : 7 * fm.width(TQChar('x')) + 18;
|
|
|
|
int maxH = TQMAX( fm.lineSpacing(), 14 ) + 2;
|
|
|
|
|
|
|
|
/* for( i = 0; i < count(); i++ ) {
|
|
|
|
w = d->listView()->item( i )->width( d->listView() );
|
|
|
|
if ( w > maxW )
|
|
|
|
maxW = w;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
d->sizeHint = (style().tqsizeFromContents(TQStyle::CT_ComboBox, this,
|
|
|
|
TQSize(maxW, maxH)).expandedTo(TQApplication::globalStrut()));
|
|
|
|
|
|
|
|
return d->sizeHint;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\internal
|
|
|
|
Receives activated signals from an internal popup list and emits
|
|
|
|
the activated() signal.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::internalActivate( TQListViewItem * item )
|
|
|
|
{
|
|
|
|
if (!item)
|
|
|
|
{
|
|
|
|
d->current = 0;
|
|
|
|
if ( d->ed ) {
|
|
|
|
// d->ed->setText( "" );
|
|
|
|
d->updateLinedGeometry();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
popDownListView();
|
|
|
|
d->poppedUp = FALSE;
|
|
|
|
|
|
|
|
d->current = item;
|
|
|
|
|
|
|
|
TQString t( item->text(0) );
|
|
|
|
if ( d->ed ) {
|
|
|
|
d->ed->setText( t );
|
|
|
|
// tqWarning("internalActivate( %s )", item->text(0).latin1());
|
|
|
|
d->updateLinedGeometry();
|
|
|
|
}
|
|
|
|
emit activated( item );
|
|
|
|
emit activated( t );
|
|
|
|
|
|
|
|
// item->setOpen(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\internal
|
|
|
|
Receives highlighted signals from an internal popup list and emits
|
|
|
|
the highlighted() signal.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::internalHighlight( TQListViewItem * item )
|
|
|
|
{
|
|
|
|
if (!item)
|
|
|
|
{
|
|
|
|
d->current = 0;
|
|
|
|
if ( d->ed ) {
|
|
|
|
// d->ed->setText( "" );
|
|
|
|
d->updateLinedGeometry();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
emit highlighted( item );
|
|
|
|
TQString t = item->text(0);
|
|
|
|
if ( !t.isNull() )
|
|
|
|
emit highlighted( t );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\internal
|
|
|
|
Receives timeouts after a click. Used to decide if a Motif style
|
|
|
|
popup should stay up or not after a click.
|
|
|
|
*/
|
|
|
|
void QComboView::internalClickTimeout()
|
|
|
|
{
|
|
|
|
d->shortClick = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Sets the palette for both the combobox button and the combobox
|
|
|
|
popup list to \a palette.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::setPalette( const TQPalette &palette )
|
|
|
|
{
|
|
|
|
TQWidget::setPalette( palette );
|
|
|
|
if( d ) {
|
|
|
|
if(d->listView())
|
|
|
|
d->listView()->setPalette( palette );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Sets the font for both the combobox button and the combobox popup
|
|
|
|
list to \a font.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::setFont( const TQFont &font )
|
|
|
|
{
|
|
|
|
d->sizeHint = TQSize(); // invalidate size hint
|
|
|
|
TQWidget::setFont( font );
|
|
|
|
d->listView()->setFont( font );
|
|
|
|
if (d->ed)
|
|
|
|
d->ed->setFont( font );
|
|
|
|
if ( d->autoresize )
|
|
|
|
adjustSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!reimp
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::resizeEvent( TQResizeEvent * e )
|
|
|
|
{
|
|
|
|
if ( d->ed )
|
|
|
|
d->updateLinedGeometry();
|
|
|
|
d->listView()->resize( width(), d->listView()->height() );
|
|
|
|
TQWidget::resizeEvent( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!reimp
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::paintEvent( TQPaintEvent * )
|
|
|
|
{
|
|
|
|
TQPainter p( this );
|
|
|
|
const TQColorGroup & g = colorGroup();
|
|
|
|
p.setPen(g.text());
|
|
|
|
|
|
|
|
TQStyle::SFlags flags = TQStyle::Style_Default;
|
|
|
|
if (isEnabled())
|
|
|
|
flags |= TQStyle::Style_Enabled;
|
|
|
|
if (hasFocus())
|
|
|
|
flags |= TQStyle::Style_HasFocus;
|
|
|
|
|
|
|
|
if ( width() < 5 || height() < 5 ) {
|
|
|
|
qDrawShadePanel( &p, rect(), g, FALSE, 2,
|
|
|
|
&g.brush( TQColorGroup::Button ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// bool reverse = TQApplication::reverseLayout();
|
|
|
|
style().drawComplexControl( TQStyle::CC_ComboBox, &p, this, rect(), g,
|
|
|
|
flags, TQStyle::SC_All,
|
|
|
|
(d->arrowDown ?
|
|
|
|
TQStyle::SC_ComboBoxArrow :
|
|
|
|
TQStyle::SC_None ));
|
|
|
|
|
|
|
|
TQRect re = style().querySubControlMetrics( TQStyle::CC_ComboBox, this,
|
|
|
|
TQStyle::SC_ComboBoxEditField );
|
|
|
|
re = TQStyle::visualRect(re, this);
|
|
|
|
p.setClipRect( re );
|
|
|
|
|
|
|
|
if ( !d->ed ) {
|
|
|
|
TQListViewItem * item = d->current;
|
|
|
|
if ( item ) {
|
|
|
|
// we calculate the TQListBoxTexts height (ignoring strut)
|
|
|
|
int itemh = d->listView()->fontMetrics().lineSpacing() + 2;
|
|
|
|
p.translate( re.x(), re.y() + (re.height() - itemh)/2 );
|
|
|
|
item->paintCell( &p, d->listView()->colorGroup(), 0, width(), AlignLeft | AlignVCenter );
|
|
|
|
}
|
|
|
|
} else if ( d->listView() && d->listView()->currentItem( ) && d->current ) {
|
|
|
|
TQListViewItem * item = d->current ;
|
|
|
|
const TQPixmap *pix = item->pixmap(0);
|
|
|
|
if ( pix ) {
|
|
|
|
p.fillRect( re.x(), re.y(), pix->width() + 4, re.height(),
|
|
|
|
colorGroup().brush( TQColorGroup::Base ) );
|
|
|
|
p.drawPixmap( re.x() + 2, re.y() +
|
|
|
|
( re.height() - pix->height() ) / 2, *pix );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p.setClipping( FALSE );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!reimp
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::mousePressEvent( TQMouseEvent *e )
|
|
|
|
{
|
|
|
|
if ( e->button() != Qt::LeftButton )
|
|
|
|
return;
|
|
|
|
if ( d->discardNextMousePress ) {
|
|
|
|
d->discardNextMousePress = FALSE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
TQRect arrowRect = style().querySubControlMetrics( TQStyle::CC_ComboBox, this,
|
|
|
|
TQStyle::SC_ComboBoxArrow);
|
|
|
|
arrowRect = TQStyle::visualRect(arrowRect, this);
|
|
|
|
|
|
|
|
// Correction for motif style, where arrow is smaller
|
|
|
|
// and thus has a rect that doesn't fit the button.
|
|
|
|
arrowRect.setHeight( TQMAX( height() - (2 * arrowRect.y()), arrowRect.height() ) );
|
|
|
|
|
|
|
|
if ( childCount() && ( !editable() || arrowRect.contains( e->pos() ) ) ) {
|
|
|
|
d->arrowPressed = FALSE;
|
|
|
|
listView()->blockSignals( TRUE );
|
|
|
|
tqApp->sendEvent( listView(), e ); // trigger the listbox's autoscroll
|
|
|
|
listView()->blockSignals( FALSE );
|
|
|
|
popup();
|
|
|
|
if ( arrowRect.contains( e->pos() ) ) {
|
|
|
|
d->arrowPressed = TRUE;
|
|
|
|
d->arrowDown = TRUE;
|
|
|
|
repaint( FALSE );
|
|
|
|
}
|
|
|
|
TQTimer::singleShot( 200, this, TQT_SLOT(internalClickTimeout()));
|
|
|
|
d->shortClick = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!reimp
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::mouseMoveEvent( TQMouseEvent * )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!reimp
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::mouseReleaseEvent( TQMouseEvent * )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!reimp
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::mouseDoubleClickEvent( TQMouseEvent *e )
|
|
|
|
{
|
|
|
|
mousePressEvent( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!reimp
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::keyPressEvent( TQKeyEvent *e )
|
|
|
|
{
|
|
|
|
TQListViewItem *c = currentItem();
|
|
|
|
if ( ( e->key() == Key_F4 && e->state() == 0 ) ||
|
|
|
|
( e->key() == Key_Down && (e->state() & AltButton) ) ||
|
|
|
|
( !d->ed && e->key() == Key_Space ) ) {
|
|
|
|
if ( childCount() ) {
|
|
|
|
popup();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
} else if ( e->key() == Key_Up ) {
|
|
|
|
/* if ((!c) && (listView()->firstChild()))
|
|
|
|
setCurrentItem(listView()->firstChild());*/
|
|
|
|
if (c && c->itemAbove() )
|
|
|
|
setCurrentItem( c->itemAbove() );
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
} else if ( e->key() == Key_Down ) {
|
|
|
|
if ((!c) && (listView()->firstChild()))
|
|
|
|
{
|
|
|
|
setCurrentItem(listView()->firstChild());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ( c && c->itemBelow() )
|
|
|
|
setCurrentItem( c->itemBelow() );
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
} else if ( e->key() == Key_Home && ( !d->ed || !d->ed->hasFocus() ) ) {
|
|
|
|
if (listView()->firstChild())
|
|
|
|
setCurrentItem( listView()->firstChild() );
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
} else if ( e->key() == Key_End && ( !d->ed || !d->ed->hasFocus() ) ) {
|
|
|
|
if (listView()->lastItem())
|
|
|
|
setCurrentItem( listView()->lastItem() );
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
} else if ( !d->ed && e->ascii() >= 32 && !e->text().isEmpty() ) {
|
|
|
|
if ( !d->completionTimer->isActive() ) {
|
|
|
|
d->completeAt = 0;
|
|
|
|
c = completionIndex( e->text(), c->itemBelow() );
|
|
|
|
if ( c ) {
|
|
|
|
setCurrentItem( c );
|
|
|
|
d->completeAt = e->text().length();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
d->completionTimer->stop();
|
|
|
|
TQString ct = currentText().left( d->completeAt ) + e->text();
|
|
|
|
c = completionIndex( ct, c );
|
|
|
|
if ( c == 0 && d->completeAt > 0 ) {
|
|
|
|
c = completionIndex( e->text(), listView()->firstChild() );
|
|
|
|
ct = e->text();
|
|
|
|
}
|
|
|
|
d->completeAt = 0;
|
|
|
|
if ( c ) {
|
|
|
|
setCurrentItem( c );
|
|
|
|
d->completeAt = ct.length();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
d->completionTimer->start( 400, TRUE );
|
|
|
|
} else {
|
|
|
|
e->ignore();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = currentItem();
|
|
|
|
if ( childCount() && c && !c->text(0).isNull() )
|
|
|
|
emit activated( c->text(0) );
|
|
|
|
emit activated( c );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString QComboView::currentText() const
|
|
|
|
{
|
|
|
|
if ( d->ed )
|
|
|
|
return d->ed->text();
|
|
|
|
else if ( d->current )
|
|
|
|
return currentItem()->text(0);
|
|
|
|
else
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!reimp
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::focusInEvent( TQFocusEvent * e )
|
|
|
|
{
|
|
|
|
TQWidget::focusInEvent( e );
|
|
|
|
d->completeNow = FALSE;
|
|
|
|
d->completeAt = 0;
|
|
|
|
|
|
|
|
emit focusGranted();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!reimp
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::focusOutEvent( TQFocusEvent * e )
|
|
|
|
{
|
|
|
|
TQWidget::focusOutEvent( e );
|
|
|
|
d->completeNow = FALSE;
|
|
|
|
d->completeAt = 0;
|
|
|
|
|
|
|
|
emit focusLost();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!reimp
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::wheelEvent( TQWheelEvent *e )
|
|
|
|
{
|
|
|
|
if ( d->poppedUp ) {
|
|
|
|
TQApplication::sendEvent( d->listView(), e );
|
|
|
|
} else {
|
|
|
|
if ( e->delta() > 0 ) {
|
|
|
|
TQListViewItem *c = currentItem();
|
|
|
|
if ( c && c->itemAbove() ) {
|
|
|
|
setCurrentItem( c->itemAbove() );
|
|
|
|
emit activated( currentItem() );
|
|
|
|
emit activated( currentText() );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
TQListViewItem *c = currentItem();
|
|
|
|
if ( c && c->itemBelow() ) {
|
|
|
|
setCurrentItem( c->itemBelow() );
|
|
|
|
emit activated( currentItem() );
|
|
|
|
emit activated( currentText() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
e->accept();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int childCount(TQListViewItem *it)
|
|
|
|
{
|
|
|
|
int count = 1;
|
|
|
|
TQListViewItem * myChild = it->firstChild();
|
|
|
|
while( myChild ) {
|
|
|
|
count += childCount(myChild);
|
|
|
|
myChild = myChild->nextSibling();
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
int childCount(TQListView *lv)
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
TQListViewItem * myChild = lv->firstChild();
|
|
|
|
while( myChild ) {
|
|
|
|
count += childCount(myChild);
|
|
|
|
// count += 1;
|
|
|
|
myChild = myChild->nextSibling();
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\internal
|
|
|
|
Calculates the listbox height needed to contain all items, or as
|
|
|
|
many as the list box is supposed to contain.
|
|
|
|
*/
|
|
|
|
static int listHeight( TQListView *l, int /*sl*/ )
|
|
|
|
{
|
|
|
|
/* if ( l->childCount() > 0 )
|
|
|
|
return TQMIN( l->childCount(), (uint)sl) * l->firstChild()->height();
|
|
|
|
else*/
|
|
|
|
|
|
|
|
int prefH = 0;
|
|
|
|
int ch = childCount(l);
|
|
|
|
ch = TQMIN(ch, 10);
|
|
|
|
if (l->firstChild())
|
|
|
|
{
|
|
|
|
prefH = ch * l->firstChild()->height();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
prefH = l->sizeHint().height();
|
|
|
|
|
|
|
|
if (l->header()->isVisible())
|
|
|
|
prefH += l->header()->sizeHint().height();
|
|
|
|
|
|
|
|
// return prefH < l->sizeHint().height() ? prefH : l->sizeHint().height();
|
|
|
|
|
|
|
|
return prefH+2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Pops up the combobox popup list.
|
|
|
|
|
|
|
|
If the list is empty, no items appear.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::popup()
|
|
|
|
{
|
|
|
|
if ( !childCount() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Send all listbox events to eventFilter():
|
|
|
|
TQListView* lb = d->listView();
|
|
|
|
lb->triggerUpdate( );
|
|
|
|
lb->installEventFilter( this );
|
|
|
|
lb->viewport()->installEventFilter( this );
|
|
|
|
d->mouseWasInsidePopup = FALSE;
|
|
|
|
// int w = lb->variableWidth() ? lb->sizeHint().width() : width();
|
|
|
|
int w = width();
|
|
|
|
int h = listHeight( lb, d->sizeLimit );
|
|
|
|
TQRect screen = TQApplication::desktop()->availableGeometry( const_cast<QComboView*>(this) );
|
|
|
|
|
|
|
|
int sx = screen.x(); // screen pos
|
|
|
|
int sy = screen.y();
|
|
|
|
int sw = screen.width(); // screen width
|
|
|
|
int sh = screen.height(); // screen height
|
|
|
|
TQPoint pos = mapToGlobal( TQPoint(0,height()) );
|
|
|
|
// ## Similar code is in TQPopupMenu
|
|
|
|
int x = pos.x();
|
|
|
|
int y = pos.y();
|
|
|
|
|
|
|
|
// the complete widget must be visible
|
|
|
|
if ( x + w > sx + sw )
|
|
|
|
x = sx+sw - w;
|
|
|
|
if ( x < sx )
|
|
|
|
x = sx;
|
|
|
|
if (y + h > sy+sh && y - h - height() >= 0 )
|
|
|
|
y = y - h - height();
|
|
|
|
TQRect rect =
|
|
|
|
style().querySubControlMetrics( TQStyle::CC_ComboBox, this,
|
|
|
|
TQStyle::SC_ComboBoxListBoxPopup,
|
|
|
|
TQStyleOption( x, y, w, h ) );
|
|
|
|
if ( rect.isNull() )
|
|
|
|
rect.setRect( x, y, w, h );
|
|
|
|
lb->setGeometry( rect );
|
|
|
|
|
|
|
|
lb->raise();
|
|
|
|
bool block = lb->signalsBlocked();
|
|
|
|
lb->blockSignals( TRUE );
|
|
|
|
TQListViewItem *currentLBItem = d->current ;
|
|
|
|
lb->setCurrentItem( currentLBItem );
|
|
|
|
// set the current item to also be the selected item if it isn't already
|
|
|
|
if ( currentLBItem && currentLBItem->isSelectable() && !currentLBItem->isSelected() )
|
|
|
|
lb->setSelected( currentLBItem, TRUE );
|
|
|
|
lb->blockSignals( block );
|
|
|
|
lb->setVScrollBarMode(TQScrollView::Auto);
|
|
|
|
|
|
|
|
//#ifndef TQT_NO_EFFECTS
|
|
|
|
/* if ( TQApplication::isEffectEnabled( UI_AnimateCombo ) ) {
|
|
|
|
if ( lb->y() < mapToGlobal(TQPoint(0,0)).y() )
|
|
|
|
qScrollEffect( lb, TQEffects::UpScroll );
|
|
|
|
else
|
|
|
|
qScrollEffect( lb );
|
|
|
|
} else*/
|
|
|
|
//#endif
|
|
|
|
lb->show();
|
|
|
|
d->poppedUp = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
reimp
|
|
|
|
*/
|
|
|
|
void QComboView::updateMask()
|
|
|
|
{
|
|
|
|
TQBitmap bm( size() );
|
|
|
|
bm.fill( color0 );
|
|
|
|
|
|
|
|
{
|
|
|
|
TQPainter p( &bm, this );
|
|
|
|
style().drawComplexControlMask(TQStyle::CC_ComboBox, &p, this, rect());
|
|
|
|
}
|
|
|
|
|
|
|
|
setMask( bm );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\internal
|
|
|
|
Pops down (removes) the combobox popup list box.
|
|
|
|
*/
|
|
|
|
void QComboView::popDownListView()
|
|
|
|
{
|
|
|
|
d->listView()->removeEventFilter( this );
|
|
|
|
d->listView()->viewport()->removeEventFilter( this );
|
|
|
|
d->listView()->hide();
|
|
|
|
d->listView()->setCurrentItem( d->current );
|
|
|
|
if ( d->arrowDown ) {
|
|
|
|
d->arrowDown = FALSE;
|
|
|
|
repaint( FALSE );
|
|
|
|
}
|
|
|
|
d->poppedUp = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\internal
|
|
|
|
Re-indexes the identifiers in the popup list.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::reIndex()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\internal
|
|
|
|
Repaints the combobox.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::currentChanged()
|
|
|
|
{
|
|
|
|
if ( d->autoresize )
|
|
|
|
adjustSize();
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! reimp
|
|
|
|
|
|
|
|
\internal
|
|
|
|
|
|
|
|
The event filter steals events from the popup or listbox when they
|
|
|
|
are popped up. It makes the popup stay up after a short click in
|
|
|
|
motif style. In windows style it toggles the arrow button of the
|
|
|
|
combobox field, and activates an item and takes down the listbox
|
|
|
|
when the mouse button is released.
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool QComboView::eventFilter( TQObject *object, TQEvent *event )
|
|
|
|
{
|
|
|
|
if ( !event )
|
|
|
|
return TRUE;
|
|
|
|
else if ( TQT_BASE_OBJECT(object) == TQT_BASE_OBJECT(d->ed) ) {
|
|
|
|
if ( event->type() == TQEvent::KeyPress ) {
|
|
|
|
bool isAccepted = ( (TQKeyEvent*)event )->isAccepted();
|
|
|
|
keyPressEvent( (TQKeyEvent *)event );
|
|
|
|
if ( ((TQKeyEvent *)event)->isAccepted() ) {
|
|
|
|
d->completeNow = FALSE;
|
|
|
|
return TRUE;
|
|
|
|
} else if ( ((TQKeyEvent *)event)->key() != Key_End ) {
|
|
|
|
d->completeNow = TRUE;
|
|
|
|
d->completeAt = d->ed->cursorPosition();
|
|
|
|
}
|
|
|
|
if ( isAccepted )
|
|
|
|
( (TQKeyEvent*)event )->accept();
|
|
|
|
else
|
|
|
|
( (TQKeyEvent*)event )->ignore();
|
|
|
|
} else if ( event->type() == TQEvent::KeyRelease ) {
|
|
|
|
d->completeNow = FALSE;
|
|
|
|
keyReleaseEvent( (TQKeyEvent *)event );
|
|
|
|
return ((TQKeyEvent *)event)->isAccepted();
|
|
|
|
} else if ( event->type() == TQEvent::FocusIn ) {
|
|
|
|
focusInEvent( (TQFocusEvent *)event );
|
|
|
|
} else if ( event->type() == TQEvent::FocusOut ) {
|
|
|
|
focusOutEvent( (TQFocusEvent *)event );
|
|
|
|
} else if ( d->useCompletion && d->completeNow ) {
|
|
|
|
if ( !d->ed->text().isNull() &&
|
|
|
|
d->ed->cursorPosition() > d->completeAt &&
|
|
|
|
d->ed->cursorPosition() == (int)d->ed->text().length() ) {
|
|
|
|
d->completeNow = FALSE;
|
|
|
|
TQString ct( d->ed->text() );
|
|
|
|
TQListViewItem *i = completionIndex( ct, currentItem() );
|
|
|
|
if ( i ) {
|
|
|
|
TQString it = i->text(0);
|
|
|
|
d->ed->validateAndSet( it, ct.length(),
|
|
|
|
ct.length(), it.length() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ( ( TQT_BASE_OBJECT(object) == TQT_BASE_OBJECT(d->listView()) ||
|
|
|
|
TQT_BASE_OBJECT(object) == TQT_BASE_OBJECT(d->listView()->viewport()) )) {
|
|
|
|
TQMouseEvent *e = (TQMouseEvent*)event;
|
|
|
|
switch( event->type() ) {
|
|
|
|
case TQEvent::MouseMove:
|
|
|
|
if ( !d->mouseWasInsidePopup ) {
|
|
|
|
// tqWarning("!d->mouseWasInsidePopup");
|
|
|
|
TQPoint pos = e->pos();
|
|
|
|
if ( d->listView()->rect().contains( pos ) )
|
|
|
|
d->mouseWasInsidePopup = TRUE;
|
|
|
|
// Check if arrow button should toggle
|
|
|
|
if ( d->arrowPressed ) {
|
|
|
|
TQPoint comboPos;
|
|
|
|
comboPos = mapFromGlobal( d->listView()->mapToGlobal(pos) );
|
|
|
|
TQRect arrowRect =
|
|
|
|
style().querySubControlMetrics( TQStyle::CC_ComboBox, this,
|
|
|
|
TQStyle::SC_ComboBoxArrow);
|
|
|
|
arrowRect = TQStyle::visualRect(arrowRect, this);
|
|
|
|
if ( arrowRect.contains( comboPos ) ) {
|
|
|
|
if ( !d->arrowDown ) {
|
|
|
|
d->arrowDown = TRUE;
|
|
|
|
repaint( FALSE );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ( d->arrowDown ) {
|
|
|
|
d->arrowDown = FALSE;
|
|
|
|
repaint( FALSE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ((e->state() & ( Qt::RightButton | Qt::LeftButton | Qt::MidButton ) ) == 0 &&
|
|
|
|
style().styleHint(TQStyle::SH_ComboBox_ListMouseTracking, this)) {
|
|
|
|
// tqWarning("event filter:: emu");
|
|
|
|
TQWidget *mouseW = TQApplication::widgetAt( e->globalPos(), TRUE );
|
|
|
|
// if ( mouseW == d->listView()->viewport() ) { //###
|
|
|
|
if ( mouseW == d->listView()->viewport() ) {
|
|
|
|
TQListViewItem *sel = d->listView()->itemAt(e->pos());
|
|
|
|
if (sel)
|
|
|
|
{
|
|
|
|
d->listView()->setCurrentItem(sel);
|
|
|
|
d->listView()->setSelected(sel, true);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case TQEvent::MouseButtonRelease:
|
|
|
|
if ( d->listView()->rect().contains( e->pos() ) ) {
|
|
|
|
TQMouseEvent tmp( TQEvent::MouseButtonDblClick,
|
|
|
|
e->pos(), e->button(), e->state() ) ;
|
|
|
|
// will hide popup
|
|
|
|
TQApplication::sendEvent( object, &tmp );
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
if ( d->mouseWasInsidePopup ) {
|
|
|
|
popDownListView();
|
|
|
|
} else {
|
|
|
|
d->arrowPressed = FALSE;
|
|
|
|
if ( d->arrowDown ) {
|
|
|
|
d->arrowDown = FALSE;
|
|
|
|
repaint( FALSE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQEvent::MouseButtonDblClick:
|
|
|
|
case TQEvent::MouseButtonPress:
|
|
|
|
if ( !d->listView()->rect().contains( e->pos() ) ) {
|
|
|
|
TQPoint globalPos = d->listView()->mapToGlobal(e->pos());
|
|
|
|
if ( TQApplication::widgetAt( globalPos, TRUE ) == this ) {
|
|
|
|
d->discardNextMousePress = TRUE;
|
|
|
|
// avoid popping up again
|
|
|
|
}
|
|
|
|
popDownListView();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQEvent::KeyPress:
|
|
|
|
switch( ((TQKeyEvent *)event)->key() ) {
|
|
|
|
case Key_Up:
|
|
|
|
case Key_Down:
|
|
|
|
if ( !(((TQKeyEvent *)event)->state() & AltButton) )
|
|
|
|
break;
|
|
|
|
case Key_F4:
|
|
|
|
case Key_Escape:
|
|
|
|
if ( d->poppedUp ) {
|
|
|
|
popDownListView();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Key_Enter:
|
|
|
|
case Key_Return:
|
|
|
|
// work around TQDialog's enter handling
|
|
|
|
return FALSE;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TQEvent::Hide:
|
|
|
|
popDownListView();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TQWidget::eventFilter( object, event );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns the index of the first item \e after \a startingAt of
|
|
|
|
which \a prefix is a case-insensitive prefix. Returns -1 if no
|
|
|
|
items start with \a prefix.
|
|
|
|
*/
|
|
|
|
|
|
|
|
TQListViewItem *QComboView::completionIndex( const TQString & prefix,
|
|
|
|
TQListViewItem *startingAt ) const
|
|
|
|
{
|
|
|
|
TQListViewItem *start = startingAt;
|
|
|
|
/* if ( start < 0 || start >= count() )
|
|
|
|
start = 0;
|
|
|
|
if ( start >= count() )
|
|
|
|
return -1;*/
|
|
|
|
if (!start)
|
|
|
|
start = listView()->firstChild();
|
|
|
|
if (!start)
|
|
|
|
return 0;
|
|
|
|
/* if (!start->itemBelow())
|
|
|
|
return 0;*/
|
|
|
|
TQString match = prefix.lower();
|
|
|
|
if ( match.length() < 1 )
|
|
|
|
return start;
|
|
|
|
|
|
|
|
TQString current;
|
|
|
|
TQListViewItem *i = start;
|
|
|
|
do {
|
|
|
|
current = i->text(0).lower();
|
|
|
|
if ( current.startsWith( match ) )
|
|
|
|
return i;
|
|
|
|
i = i->itemBelow();
|
|
|
|
if ( i )
|
|
|
|
i = listView()->firstChild();
|
|
|
|
} while ( i != start );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int QComboView::sizeLimit() const
|
|
|
|
{
|
|
|
|
return d ? d->sizeLimit : INT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QComboView::setSizeLimit( int lines )
|
|
|
|
{
|
|
|
|
d->sizeLimit = lines;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*int QComboView::maxCount() const
|
|
|
|
{
|
|
|
|
return d ? d->maxCount : INT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QComboView::setMaxCount( int count )
|
|
|
|
{
|
|
|
|
int l = this->count();
|
|
|
|
while( --l > count )
|
|
|
|
removeItem( l );
|
|
|
|
d->maxCount = count;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
QComboView::Policy QComboView::insertionPolicy() const
|
|
|
|
{
|
|
|
|
return d->p;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QComboView::setInsertionPolicy( Policy policy )
|
|
|
|
{
|
|
|
|
d->p = policy;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Internal slot to keep the line editor up to date.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::returnPressed()
|
|
|
|
{
|
|
|
|
TQString s( d->ed->text() );
|
|
|
|
|
|
|
|
if ( s.isEmpty() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQListViewItem *c = 0;
|
|
|
|
bool doInsert = TRUE;
|
|
|
|
if ( !d->duplicatesEnabled ) {
|
|
|
|
c = listView()->findItem(s, 0);
|
|
|
|
if ( c )
|
|
|
|
doInsert = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( doInsert ) {
|
|
|
|
if ( insertionPolicy() != NoInsertion ) {
|
|
|
|
/* int cnt = count();
|
|
|
|
while ( cnt >= d->maxCount ) {
|
|
|
|
removeItem( --cnt );
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ( insertionPolicy() ) {
|
|
|
|
case AtCurrent:
|
|
|
|
if ( s != currentItem()->text(0) )
|
|
|
|
currentItem()->setText(0, s);
|
|
|
|
emit activated( currentItem() );
|
|
|
|
emit activated( s );
|
|
|
|
return;
|
|
|
|
case NoInsertion:
|
|
|
|
emit activated( s );
|
|
|
|
return;
|
|
|
|
case AtTop:
|
|
|
|
c = 0;
|
|
|
|
return;
|
|
|
|
// break;
|
|
|
|
case AtBottom:
|
|
|
|
c = new TQListViewItem(listView(), listView()->lastItem(), s);
|
|
|
|
break;
|
|
|
|
case BeforeCurrent:
|
|
|
|
if (currentItem() && currentItem()->itemAbove())
|
|
|
|
c = new TQListViewItem(listView(), currentItem()->itemAbove(), s);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AfterCurrent:
|
|
|
|
if (currentItem() && currentItem()->itemBelow())
|
|
|
|
c = new TQListViewItem(listView(), currentItem()->itemBelow(), s);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c)
|
|
|
|
{
|
|
|
|
setCurrentItem( c );
|
|
|
|
emit activated( c );
|
|
|
|
emit activated( s );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*! reimp
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::setEnabled( bool enable )
|
|
|
|
{
|
|
|
|
TQWidget::setEnabled( enable );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Applies the validator \a v to the combobox so that only text which
|
|
|
|
is valid according to \a v is accepted.
|
|
|
|
|
|
|
|
This function does nothing if the combobox is not editable.
|
|
|
|
|
|
|
|
\sa validator() clearValidator() TQValidator
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::setValidator( const TQValidator * v )
|
|
|
|
{
|
|
|
|
if ( d && d->ed )
|
|
|
|
d->ed->setValidator( v );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns the validator which constrains editing for this combobox
|
|
|
|
if there is one; otherwise returns 0.
|
|
|
|
|
|
|
|
\sa setValidator() clearValidator() TQValidator
|
|
|
|
*/
|
|
|
|
|
|
|
|
const TQValidator * QComboView::validator() const
|
|
|
|
{
|
|
|
|
return d && d->ed ? d->ed->validator() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
This slot is equivalent to setValidator( 0 ).
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::clearValidator()
|
|
|
|
{
|
|
|
|
if ( d && d->ed )
|
|
|
|
d->ed->setValidator( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Sets the combobox to use \a newListBox instead of the current list
|
|
|
|
box or popup. As a side effect, it clears the combobox of its
|
|
|
|
current contents.
|
|
|
|
|
|
|
|
\warning QComboView assumes that newListBox->text(n) returns
|
|
|
|
non-null for 0 \<= n \< newListbox->count(). This assumption is
|
|
|
|
necessary because of the line edit in QComboView.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::setListView( TQListView * newListView )
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
|
|
|
|
delete d->listView();
|
|
|
|
|
|
|
|
newListView->reparent( this, WType_Popup, TQPoint(0,0), FALSE );
|
|
|
|
d->setListView( newListView );
|
|
|
|
d->listView()->setFont( font() );
|
|
|
|
d->listView()->setPalette( palette() );
|
|
|
|
/* d->listView()->setVScrollBarMode(TQScrollView::AlwaysOff);
|
|
|
|
d->listView()->setHScrollBarMode(TQScrollView::AlwaysOff);*/
|
|
|
|
d->listView()->setFrameStyle( TQFrame::Box | TQFrame::Plain );
|
|
|
|
d->listView()->setLineWidth( 1 );
|
|
|
|
/* d->listView()->setRootIsDecorated( true );
|
|
|
|
d->listView()->setAllColumnsShowFocus(true);*/
|
|
|
|
d->listView()->resize( 100, 10 );
|
|
|
|
|
|
|
|
if (d->listView()->firstChild())
|
|
|
|
d->current = d->listView()->firstChild();
|
|
|
|
|
|
|
|
// d->listView()->header()->hide();
|
|
|
|
|
|
|
|
|
|
|
|
/* d->listView()->setFont( font() );
|
|
|
|
d->listView()->setPalette( palette() );
|
|
|
|
d->listView()->setVScrollBarMode( TQScrollView::AlwaysOff );
|
|
|
|
d->listView()->setHScrollBarMode( TQScrollView::AlwaysOff );
|
|
|
|
d->listView()->setFrameStyle( TQFrame::Box | TQFrame::Plain );
|
|
|
|
d->listView()->setLineWidth( 1 );
|
|
|
|
d->listView()->setRootIsDecorated( true );
|
|
|
|
d->listView()->setAllColumnsShowFocus(true);
|
|
|
|
d->listView()->addColumn("");
|
|
|
|
d->listView()->resize( 100, 10 );
|
|
|
|
*/
|
|
|
|
|
|
|
|
connect( d->listView(), TQT_SIGNAL(returnPressed(TQListViewItem*)),
|
|
|
|
TQT_SLOT(internalActivate(TQListViewItem*)));
|
|
|
|
connect( d->listView(), TQT_SIGNAL(doubleClicked(TQListViewItem*)),
|
|
|
|
TQT_SLOT(internalActivate(TQListViewItem*)));
|
|
|
|
connect( d->listView(), TQT_SIGNAL(doubleClicked(TQListViewItem*)),
|
|
|
|
TQT_SLOT(checkState(TQListViewItem*)));
|
|
|
|
connect( d->listView(), TQT_SIGNAL(currentChanged(TQListViewItem*)),
|
|
|
|
TQT_SLOT(internalHighlight(TQListViewItem*)));
|
|
|
|
connect( d->listView(), TQT_SIGNAL(selectionChanged(TQListViewItem*)),
|
|
|
|
TQT_SLOT(internalHighlight(TQListViewItem*)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns the current list box, or 0 if there is no list box.
|
|
|
|
(QComboView can use TQPopupMenu instead of TQListBox.) Provided to
|
|
|
|
match setlistView().
|
|
|
|
|
|
|
|
\sa setlistView()
|
|
|
|
*/
|
|
|
|
|
|
|
|
TQListView * QComboView::listView() const
|
|
|
|
{
|
|
|
|
return d ? d->listView() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns the line edit, or 0 if there is no line edit.
|
|
|
|
|
|
|
|
Only editable listboxes have a line editor.
|
|
|
|
*/
|
|
|
|
TQLineEdit* QComboView::lineEdit() const
|
|
|
|
{
|
|
|
|
return d->ed;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Clears the line edit without changing the combobox's contents.
|
|
|
|
Does nothing if the combobox isn't editable.
|
|
|
|
|
|
|
|
This is particularly useful when using a combobox as a line edit
|
|
|
|
with history. For example you can connect the combobox's
|
|
|
|
activated() signal to clearEdit() in order to present the user
|
|
|
|
with a new, empty line as soon as Enter is pressed.
|
|
|
|
|
|
|
|
\sa setEditText()
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::clearEdit()
|
|
|
|
{
|
|
|
|
if ( d && d->ed )
|
|
|
|
d->ed->clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Sets the text in the line edit to \a newText without changing the
|
|
|
|
combobox's contents. Does nothing if the combobox isn't editable.
|
|
|
|
|
|
|
|
This is useful e.g. for providing a good starting point for the
|
|
|
|
user's editing and entering the change in the combobox only when
|
|
|
|
the user presses Enter.
|
|
|
|
|
|
|
|
\sa clearEdit() insertItem()
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::setEditText( const TQString &newText )
|
|
|
|
{
|
|
|
|
if ( d && d->ed ) {
|
|
|
|
d->updateLinedGeometry();
|
|
|
|
d->ed->setText( newText );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QComboView::setAutoCompletion( bool enable )
|
|
|
|
{
|
|
|
|
d->useCompletion = enable;
|
|
|
|
d->completeNow = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool QComboView::autoCompletion() const
|
|
|
|
{
|
|
|
|
return d->useCompletion;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!reimp
|
|
|
|
*/
|
|
|
|
void QComboView::styleChange( TQStyle& s )
|
|
|
|
{
|
|
|
|
d->sizeHint = TQSize(); // invalidate size hint...
|
|
|
|
if ( d->ed )
|
|
|
|
d->updateLinedGeometry();
|
|
|
|
TQWidget::styleChange( s );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QComboView::editable() const
|
|
|
|
{
|
|
|
|
return d->ed != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QComboView::setEditable( bool y )
|
|
|
|
{
|
|
|
|
if ( y == editable() )
|
|
|
|
return;
|
|
|
|
if ( y ) {
|
|
|
|
setUpListView();
|
|
|
|
setUpLineEdit();
|
|
|
|
d->ed->show();
|
|
|
|
if ( currentItem() )
|
|
|
|
setEditText( currentText() );
|
|
|
|
} else {
|
|
|
|
delete d->ed;
|
|
|
|
d->ed = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
setFocusPolicy( TQ_StrongFocus );
|
|
|
|
updateGeometry();
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void QComboView::setUpListView()
|
|
|
|
{
|
|
|
|
d->setListView( new TQListView( this, "in-combo", WType_Popup ) );
|
|
|
|
|
|
|
|
d->listView()->setFont( font() );
|
|
|
|
d->listView()->setPalette( palette() );
|
|
|
|
/* d->listView()->setVScrollBarMode( TQScrollView::AlwaysOff );
|
|
|
|
d->listView()->setHScrollBarMode( TQScrollView::AlwaysOff );*/
|
|
|
|
d->listView()->setFrameStyle( TQFrame::Box | TQFrame::Plain );
|
|
|
|
d->listView()->setLineWidth( 1 );
|
|
|
|
d->listView()->setRootIsDecorated( false );
|
|
|
|
d->listView()->setAllColumnsShowFocus(true);
|
|
|
|
d->listView()->addColumn("");
|
|
|
|
d->listView()->resize( 100, 10 );
|
|
|
|
d->listView()->setResizeMode(TQListView::LastColumn);
|
|
|
|
|
|
|
|
if (d->listView()->firstChild())
|
|
|
|
d->current = d->listView()->firstChild();
|
|
|
|
|
|
|
|
d->listView()->header()->hide();
|
|
|
|
|
|
|
|
connect( d->listView(), TQT_SIGNAL(returnPressed(TQListViewItem*)),
|
|
|
|
TQT_SLOT(internalActivate(TQListViewItem*)));
|
|
|
|
connect( d->listView(), TQT_SIGNAL(doubleClicked(TQListViewItem*)),
|
|
|
|
TQT_SLOT(internalActivate(TQListViewItem*)));
|
|
|
|
connect( d->listView(), TQT_SIGNAL(doubleClicked(TQListViewItem*)),
|
|
|
|
TQT_SLOT(checkState(TQListViewItem*)));
|
|
|
|
connect( d->listView(), TQT_SIGNAL(currentChanged(TQListViewItem*)),
|
|
|
|
TQT_SLOT(internalHighlight(TQListViewItem*)));
|
|
|
|
connect( d->listView(), TQT_SIGNAL(selectionChanged(TQListViewItem*)),
|
|
|
|
TQT_SLOT(internalHighlight(TQListViewItem*)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void QComboView::setUpLineEdit()
|
|
|
|
{
|
|
|
|
if ( !d->ed )
|
|
|
|
setLineEdit( new TQLineEdit( this, "combo edit" ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Sets the line edit to use \a edit instead of the current line edit.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QComboView::setLineEdit( TQLineEdit *edit )
|
|
|
|
{
|
|
|
|
if ( !edit ) {
|
|
|
|
#if defined(TQT_CHECK_NULL)
|
|
|
|
Q_ASSERT( edit != 0 );
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
edit->setText( currentText() );
|
|
|
|
if ( d->ed ) {
|
|
|
|
int start = 0, end = 0;
|
|
|
|
d->ed->getSelection( &start, &end );
|
|
|
|
edit->setSelection( start, end );
|
|
|
|
edit->setCursorPosition( d->ed->cursorPosition() );
|
|
|
|
edit->setEdited( d->ed->edited() );
|
|
|
|
delete d->ed;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->ed = edit;
|
|
|
|
|
|
|
|
if ( TQT_BASE_OBJECT(edit->parent()) != TQT_BASE_OBJECT(this) ) {
|
|
|
|
edit->reparent( this, TQPoint(0,0), FALSE );
|
|
|
|
edit->setFont( font() );
|
|
|
|
}
|
|
|
|
|
|
|
|
connect (edit, TQT_SIGNAL( textChanged( const TQString& ) ),
|
|
|
|
this, TQT_SIGNAL( textChanged( const TQString& ) ) );
|
|
|
|
connect( edit, TQT_SIGNAL(returnPressed()), TQT_SLOT(returnPressed()) );
|
|
|
|
|
|
|
|
edit->setFrame( FALSE );
|
|
|
|
d->updateLinedGeometry();
|
|
|
|
edit->installEventFilter( this );
|
|
|
|
setFocusProxy( edit );
|
|
|
|
setFocusPolicy( TQ_StrongFocus );
|
|
|
|
|
|
|
|
setUpListView();
|
|
|
|
|
|
|
|
if ( isVisible() )
|
|
|
|
edit->show();
|
|
|
|
|
|
|
|
updateGeometry();
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void QComboView::setCurrentText( const TQString& txt )
|
|
|
|
{
|
|
|
|
TQListViewItem *i;
|
|
|
|
i = listView()->findItem(txt, 0);
|
|
|
|
if ( i )
|
|
|
|
setCurrentItem( i );
|
|
|
|
else if ( d->ed )
|
|
|
|
d->ed->setText( txt );
|
|
|
|
else if (currentItem())
|
|
|
|
currentItem()->setText(0, txt);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QComboView::checkState( TQListViewItem * item)
|
|
|
|
{
|
|
|
|
item->setOpen(!item->isOpen());
|
|
|
|
}
|
|
|
|
|
|
|
|
void QComboView::setCurrentActiveItem( TQListViewItem * item )
|
|
|
|
{
|
|
|
|
if ( item == d->current && !d->ed ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->current = item;
|
|
|
|
d->completeAt = 0;
|
|
|
|
if ( d->ed ) {
|
|
|
|
d->ed->setText( item->text(0) );
|
|
|
|
d->ed->setCursorPosition(0);
|
|
|
|
// tqWarning("setCurrentActiveItem( %s )", item->text(0).latin1());
|
|
|
|
d->updateLinedGeometry();
|
|
|
|
}
|
|
|
|
if ( d->listView() ) {
|
|
|
|
d->listView()->setCurrentItem( item );
|
|
|
|
emit activated( item );
|
|
|
|
emit activated( item->text(0) );
|
|
|
|
} else {
|
|
|
|
internalHighlight( item );
|
|
|
|
internalActivate( item );
|
|
|
|
}
|
|
|
|
|
|
|
|
currentChanged();
|
|
|
|
|
|
|
|
d->listView()->ensureItemVisible(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "qcomboview.moc"
|
|
|
|
|
|
|
|
#endif // TQT_NO_COMBOBOX
|
|
|
|
|