You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kmymoney/kmymoney2/widgets/kmymoneycompletion.cpp

305 lines
9.6 KiB

/***************************************************************************
kmymoneycompletion.cpp - description
-------------------
begin : Mon Apr 26 2004
copyright : (C) 2000-2004 by Michael Edwardes
email : mte@users.sourceforge.net
Javier Campos Morales <javi_c@users.sourceforge.net>
Felix Rodriguez <frodriguez@users.sourceforge.net>
John C <thetacoturtle@users.sourceforge.net>
Thomas Baumgart <ipwizard@users.sourceforge.net>
Kevin Tambascio <ktambascio@users.sourceforge.net>
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
// ----------------------------------------------------------------------------
// QT Includes
#include <tqapplication.h>
// ----------------------------------------------------------------------------
// KDE Includes
#include <klistview.h>
// ----------------------------------------------------------------------------
// Project Includes
#include "kmymoneycompletion.h"
#include <kmymoney/kmymoneyselector.h>
#include <kmymoney/kmymoneylistviewitem.h>
#include "./kmymoneycombo.h"
const int kMyMoneyCompletion::MAX_ITEMS = 16;
kMyMoneyCompletion::kMyMoneyCompletion(TQWidget *parent, const char *name ) :
TQVBox(parent, name, WType_Popup)
{
m_selector = new KMyMoneySelector(this);
m_selector->listView()->setFocusProxy(this);
m_parent = parent;
setFocusProxy((parent) ? parent : (TQWidget*) TQ_NoFocus);
setFrameStyle(TQFrame::PopupPanel | TQFrame::Raised);
connectSignals(m_selector, m_selector->listView());
}
void kMyMoneyCompletion::connectSignals(TQWidget* widget, KListView* lv)
{
m_widget = widget;
m_lv = lv;
connect(lv, TQT_SIGNAL(executed(TQListViewItem*,const TQPoint&,int)), this, TQT_SLOT(slotItemSelected(TQListViewItem*,const TQPoint&,int)));
}
kMyMoneyCompletion::~kMyMoneyCompletion()
{
}
void kMyMoneyCompletion::adjustSize(void)
{
TQListViewItemIterator it(m_lv, TQListViewItemIterator::Visible);
int count = 0;
while(it.current()) {
++count;
++it;
}
adjustSize(count);
}
void kMyMoneyCompletion::adjustSize(const int count)
{
int w = m_widget->sizeHint().width();
if(m_parent && w < m_parent->width())
w = m_parent->width();
TQFontMetrics fm(font());
if(w < fm.maxWidth()*15)
w = fm.maxWidth()*15;
int h = 0;
TQListViewItemIterator it(m_lv, TQListViewItemIterator::Visible);
TQListViewItem* item = it.current();
if(item)
h = item->height() * (count > MAX_ITEMS ? MAX_ITEMS : count);
// the offset of 4 in the next statement avoids the
// display of a scroll bar if count < MAX_ITEMS.
resize(w, h+4);
if(m_parent) {
// the code of this basic block is taken from KCompletionBox::show()
// and modified to our local needs
// this is probably better, once kde switches to requiring qt3.1
// TQRect screenSize = TQApplication::desktop()->availableGeometry(d->m_parent);
// for now use this since it's qt3.0.x-safe
TQRect screenSize = TQApplication::desktop()->screenGeometry(TQApplication::desktop()->screenNumber(m_parent));
TQPoint orig = m_parent->mapToGlobal( TQPoint(0, m_parent->height()) );
int x = orig.x();
int y = orig.y();
if ( x + width() > screenSize.right() )
x = screenSize.right() - width();
// check for the maximum height here to avoid flipping
// of the completion box from top to bottom of the
// edit widget. The offset (y) is certainly based
// on the actual height.
if(item) {
if ((y + item->height()*MAX_ITEMS) > screenSize.bottom() )
y = y - height() - m_parent->height();
}
move( x, y);
}
}
void kMyMoneyCompletion::show(bool presetSelected)
{
if(!m_id.isEmpty() && presetSelected)
m_selector->setSelected(m_id);
adjustSize();
if(m_parent) {
m_parent->installEventFilter(this);
// make sure to install the filter for the combobox lineedit as well
// We have do this here because TQObject::installEventFilter() is not
// declared virtual and we have no chance to override it in KMyMoneyCombo
KMyMoneyCombo* c = dynamic_cast<KMyMoneyCombo*>(m_parent);
if(c && c->lineEdit()) {
c->lineEdit()->installEventFilter(this);
}
}
TQVBox::show();
}
void kMyMoneyCompletion::hide(void)
{
if(m_parent) {
m_parent->removeEventFilter(this);
// make sure to uninstall the filter for the combobox lineedit as well
// We have do this here because TQObject::installEventFilter() is not
// declared virtual and we have no chance to override it in KMyMoneyCombo
KMyMoneyCombo* c = dynamic_cast<KMyMoneyCombo*>(m_parent);
if(c && c->lineEdit()) {
c->lineEdit()->removeEventFilter(this);
}
}
TQVBox::hide();
}
bool kMyMoneyCompletion::eventFilter(TQObject* o, TQEvent* e)
{
int type = e->type();
KMyMoneyCombo *c = dynamic_cast<KMyMoneyCombo*>(m_parent);
TQListViewItem* item;
if(TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(m_parent) || (c && TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(c->lineEdit()))) {
if(isVisible()) {
if(type == TQEvent::KeyPress) {
TQKeyEvent* ev = TQT_TQKEYEVENT (e);
TQKeyEvent evt(TQEvent::KeyPress,
Key_Down, 0, ev->state(), TQString(),
ev->isAutoRepeat(), ev->count());
TQKeyEvent evbt(TQEvent::KeyPress,
Key_Up, 0, ev->state(), TQString(),
ev->isAutoRepeat(), ev->count());
switch(ev->key()) {
case Key_Tab:
case Key_BackTab:
slotItemSelected(m_lv->currentItem(), TQPoint(0,0), 0);
break;
case Key_Down:
case Key_Next:
item = m_lv->currentItem();
while(item) {
item = item->itemBelow();
if(item && selector()->match(m_lastCompletion, item))
break;
}
if(item) {
m_lv->setCurrentItem(item);
selector()->ensureItemVisible(item);
}
ev->accept();
return true;
case Key_Up:
case Key_Prior:
item = m_lv->currentItem();
while(item) {
item = item->itemAbove();
if(item && selector()->match(m_lastCompletion, item))
break;
}
if(item) {
m_lv->setCurrentItem(item);
// make sure, we always see a possible (non-selectable) group item
if(item->itemAbove())
item = item->itemAbove();
selector()->ensureItemVisible(item);
}
ev->accept();
return true;
case Key_Escape:
hide();
ev->accept();
return true;
case Key_Enter:
case Key_Return:
slotItemSelected(m_lv->currentItem(), TQPoint(0,0), 0);
ev->accept();
return true;
case Key_Home:
case Key_End:
if(ev->state() & ControlButton) {
item = m_lv->currentItem();
if(ev->key() == Key_Home) {
while(item && item->itemAbove()) {
item = item->itemAbove();
}
while(item && !selector()->match(m_lastCompletion, item)) {
item = item->itemBelow();
}
} else {
while(item && item->itemBelow()) {
item = item->itemBelow();
}
while(item && !selector()->match(m_lastCompletion, item)) {
item = item->itemAbove();
}
}
if(item) {
m_lv->setCurrentItem(item);
// make sure, we always see a possible (non-selectable) group item
if(item->itemAbove())
item = item->itemAbove();
selector()->ensureItemVisible(item);
}
ev->accept();
return true;
}
break;
default:
break;
}
}
}
}
return TQVBox::eventFilter(o, e);
}
void kMyMoneyCompletion::slotMakeCompletion(const TQString& txt)
{
int cnt = selector()->slotMakeCompletion(txt.stripWhiteSpace());
if(m_parent && m_parent->isVisible() && !isVisible() && cnt)
show(false);
else {
if(cnt != 0) {
adjustSize();
} else {
hide();
}
}
}
void kMyMoneyCompletion::slotItemSelected(TQListViewItem *item, const TQPoint&, int)
{
KMyMoneyListViewItem* it_v = static_cast<KMyMoneyListViewItem*>(item);
if(it_v && it_v->isSelectable()) {
TQString id = it_v->id();
// hide the widget, so we can debug the slots that are connect
// to the signal we emit very soon
hide();
m_id = id;
emit itemSelected(id);
}
}
void kMyMoneyCompletion::setSelected(const TQString& id)
{
m_id = id;
m_selector->setSelected(id, true);
}
#include "kmymoneycompletion.moc"