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.
koffice/kexi/widget/utils/kexirecordnavigator.cpp

512 lines
15 KiB

/* This file is part of the KDE project
Copyright (C) 2004 Lucijan Busch <lucijan@kde.org>
Copyright (C) 2003-2004 Jaroslaw Staniek <js@iidea.pl>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <tqtoolbutton.h>
#include <tqlayout.h>
#include <tqlabel.h>
#include <tqvalidator.h>
#include <tqtooltip.h>
#include <tqscrollview.h>
#include <klocale.h>
#include <kiconloader.h>
#include <klineedit.h>
#include <kguiitem.h>
#include <kstaticdeleter.h>
#include "kexirecordnavigator.h"
#include "kexirecordmarker.h"
//! @internal
class KexiRecordNavigatorPrivate
{
public:
KexiRecordNavigatorPrivate()
: handler(0)
, editingIndicatorLabel(0)
, editingIndicatorEnabled(false)
, editingIndicatorVisible(false)
{
}
KexiRecordNavigatorHandler *handler;
TQHBoxLayout *lyr;
TQLabel *editingIndicatorLabel;
bool editingIndicatorEnabled : 1;
bool editingIndicatorVisible : 1;
};
//--------------------------------------------------
KexiRecordNavigatorHandler::KexiRecordNavigatorHandler()
{
}
KexiRecordNavigatorHandler::~KexiRecordNavigatorHandler()
{
}
//--------------------------------------------------
KexiRecordNavigator::KexiRecordNavigator(TQWidget *parent, int leftMargin, const char *name)
: TQFrame(parent, name)
, m_view(0)
, m_isInsertingEnabled(true)
, d( new KexiRecordNavigatorPrivate() )
{
if (parent->inherits(TQSCROLLVIEW_OBJECT_NAME_STRING))
setParentView( dynamic_cast<TQScrollView*>(parent) );
setFrameStyle(TQFrame::NoFrame);
d->lyr = new TQHBoxLayout(this,0,0,"nav_lyr");
m_textLabel = new TQLabel(this);
d->lyr->addWidget( m_textLabel );
setLabelText(i18n("Row:"));
int bw = 6+SmallIcon("navigator_first").width(); //TQMIN( horizontalScrollBar()->height(), 20);
TQFont f = font();
f.setPixelSize((bw > 12) ? 12 : bw);
TQFontMetrics fm(f);
m_nav1DigitWidth = fm.width("8");
d->lyr->addWidget( m_navBtnFirst = new TQToolButton(this) );
m_navBtnFirst->setFixedWidth(bw);
m_navBtnFirst->setFocusPolicy(TQ_NoFocus);
m_navBtnFirst->setIconSet( SmallIconSet("navigator_first") );
TQToolTip::add(m_navBtnFirst, i18n("First row"));
d->lyr->addWidget( m_navBtnPrev = new TQToolButton(this) );
m_navBtnPrev->setFixedWidth(bw);
m_navBtnPrev->setFocusPolicy(TQ_NoFocus);
m_navBtnPrev->setIconSet( SmallIconSet("navigator_prev") );
m_navBtnPrev->setAutoRepeat(true);
TQToolTip::add(m_navBtnPrev, i18n("Previous row"));
d->lyr->addSpacing( 6 );
d->lyr->addWidget( m_navRecordNumber = new KLineEdit(this) );
m_navRecordNumber->setAlignment(AlignRight | AlignVCenter);
m_navRecordNumber->setFocusPolicy(TQ_ClickFocus);
m_navRecordNumber->installEventFilter(this);
// m_navRowNumber->setFixedWidth(fw);
m_navRecordNumberValidator = new TQIntValidator(1, INT_MAX, TQT_TQOBJECT(this));
m_navRecordNumber->setValidator(m_navRecordNumberValidator);
m_navRecordNumber->installEventFilter(this);
TQToolTip::add(m_navRecordNumber, i18n("Current row number"));
KLineEdit *lbl_of = new KLineEdit(i18n("of"), this);
lbl_of->setSizePolicy(TQSizePolicy::Fixed,TQSizePolicy::Preferred);
lbl_of->setMaximumWidth(fm.width(lbl_of->text())+8);
lbl_of->setReadOnly(true);
lbl_of->setLineWidth(0);
lbl_of->setFocusPolicy(TQ_NoFocus);
lbl_of->setAlignment(AlignCenter);
d->lyr->addWidget( lbl_of );
d->lyr->addWidget( m_navRecordCount = new KLineEdit(this) );
m_navRecordCount->setSizePolicy(TQSizePolicy::Fixed,TQSizePolicy::Preferred);
m_navRecordCount->setReadOnly(true);
m_navRecordCount->setLineWidth(0);
m_navRecordCount->setFocusPolicy(TQ_NoFocus);
m_navRecordCount->setAlignment(AlignLeft | AlignVCenter);
TQToolTip::add(m_navRecordCount, i18n("Number of rows"));
lbl_of->setFont(f);
m_navRecordNumber->setFont(f);
m_navRecordCount->setFont(f);
setFont(f);
d->lyr->addWidget( m_navBtnNext = new TQToolButton(this) );
m_navBtnNext->setFixedWidth(bw);
m_navBtnNext->setFocusPolicy(TQ_NoFocus);
m_navBtnNext->setIconSet( SmallIconSet("navigator_next") );
m_navBtnNext->setAutoRepeat(true);
TQToolTip::add(m_navBtnNext, i18n("Next row"));
d->lyr->addWidget( m_navBtnLast = new TQToolButton(this) );
m_navBtnLast->setFixedWidth(bw);
m_navBtnLast->setFocusPolicy(TQ_NoFocus);
m_navBtnLast->setIconSet( SmallIconSet("navigator_last") );
TQToolTip::add(m_navBtnLast, i18n("Last row"));
d->lyr->addSpacing( 6 );
d->lyr->addWidget( m_navBtnNew = new TQToolButton(this) );
m_navBtnNew->setFixedWidth(bw);
m_navBtnNew->setFocusPolicy(TQ_NoFocus);
m_navBtnNew->setIconSet( SmallIconSet("navigator_new") );
TQToolTip::add(m_navBtnNew, i18n("New row"));
m_navBtnNext->setEnabled(isInsertingEnabled());
d->lyr->addSpacing( 6 );
d->lyr->addStretch(10);
connect(m_navBtnPrev,TQT_SIGNAL(clicked()),this,TQT_SLOT(slotPrevButtonClicked()));
connect(m_navBtnNext,TQT_SIGNAL(clicked()),this,TQT_SLOT(slotNextButtonClicked()));
connect(m_navBtnLast,TQT_SIGNAL(clicked()),this,TQT_SLOT(slotLastButtonClicked()));
connect(m_navBtnFirst,TQT_SIGNAL(clicked()),this,TQT_SLOT(slotFirstButtonClicked()));
connect(m_navBtnNew,TQT_SIGNAL(clicked()),this,TQT_SLOT(slotNewButtonClicked()));
setRecordCount(0);
setCurrentRecordNumber(0);
updateGeometry(leftMargin);
}
KexiRecordNavigator::~KexiRecordNavigator()
{
delete d;
}
void KexiRecordNavigator::setInsertingEnabled(bool set)
{
if (m_isInsertingEnabled==set)
return;
m_isInsertingEnabled = set;
if (isEnabled())
m_navBtnNew->setEnabled( m_isInsertingEnabled );
}
void KexiRecordNavigator::setEnabled( bool set )
{
TQFrame::setEnabled(set);
if (set && !m_isInsertingEnabled)
m_navBtnNew->setEnabled( false );
}
bool KexiRecordNavigator::eventFilter( TQObject *o, TQEvent *e )
{
if (TQT_BASE_OBJECT(o)==TQT_BASE_OBJECT(m_navRecordNumber)) {
bool recordEntered = false;
bool ret;
if (e->type()==TQEvent::KeyPress) {
TQKeyEvent *ke = TQT_TQKEYEVENT(e);
switch (ke->key()) {
case TQt::Key_Escape: {
ke->accept();
m_navRecordNumber->undo();
if (m_view)
m_view->setFocus();
return true;
}
case TQt::Key_Enter:
case TQt::Key_Return:
case TQt::Key_Tab:
case TQt::Key_BackTab:
{
recordEntered=true;
ke->accept(); //to avoid pressing Enter later
ret = true;
}
default:;
}
}
else if (e->type()==TQEvent::FocusOut) {
if (TQT_TQFOCUSEVENT(e)->reason()!=TQFocusEvent::Tab
&& TQT_TQFOCUSEVENT(e)->reason()!=TQFocusEvent::Backtab
&& TQT_TQFOCUSEVENT(e)->reason()!=TQFocusEvent::Other)
recordEntered=true;
ret = false;
}
if (recordEntered) {
bool ok=true;
uint r = m_navRecordNumber->text().toUInt(&ok);
if (!ok || r<1)
r = (recordCount()>0)?1:0;
if (m_view && (hasFocus() || e->type()==TQEvent::KeyPress))
m_view->setFocus();
setCurrentRecordNumber(r);
emit recordNumberEntered(r);
if (d->handler)
d->handler->moveToRecordRequested(r-1);
return ret;
}
}
/*
bool ok=true;
int r = text.toInt(&ok);
if (!ok || r<1)
r = 1;
emit recordNumberEntered(r);*/
return false;
}
void KexiRecordNavigator::setCurrentRecordNumber(uint r)
{
uint recCnt = recordCount();
if (r>(recCnt+(m_isInsertingEnabled?1:0)))
r = recCnt+(m_isInsertingEnabled?1:0);
TQString n;
if (r>0)
n = TQString::number(r);
else
n = " ";
// if (d->navRecordNumber->text().length() != n.length()) {//resize
// d->navRecordNumber->setFixedWidth(
// d->nav1DigitWidth*TQMAX( TQMAX(n.length(),2)+1,d->navRecordCount->text().length()+1)+6
// );
// }
m_navRecordNumber->setText(n);
m_navRecordCount->deselect();
updateButtons(recCnt);
}
void KexiRecordNavigator::updateButtons(uint recCnt)
{
const uint r = currentRecordNumber();
if (isEnabled()) {
m_navBtnPrev->setEnabled(r > 1);
m_navBtnFirst->setEnabled(r > 1);
m_navBtnNext->setEnabled(r > 0
&& r < (recCnt +(m_isInsertingEnabled?(1+d->editingIndicatorVisible/*if we're editing, next btn is avail.*/):0) ) );
m_navBtnLast->setEnabled(r!=(recCnt+(m_isInsertingEnabled?1:0)) && (m_isInsertingEnabled || recCnt>0));
}
}
void KexiRecordNavigator::setRecordCount(uint count)
{
const TQString & n = TQString::number(count);
if (m_isInsertingEnabled && currentRecordNumber()==0) {
setCurrentRecordNumber(1);
}
if (m_navRecordCount->text().length() != n.length()) {//resize
m_navRecordCount->setFixedWidth(m_nav1DigitWidth*n.length()+6);
if (m_view && m_view->horizontalScrollBar()->isVisible()) {
//+width of the delta
resize(width()+(n.length()-m_navRecordCount->text().length())*m_nav1DigitWidth, height());
// horizontalScrollBar()->move(d->navPanel->x()+d->navPanel->width()+20,horizontalScrollBar()->y());
}
}
//update row number widget's width
const int w = m_nav1DigitWidth*TQMAX( TQMAX(n.length(),2)+1,m_navRecordNumber->text().length()+1)+6;
if (m_navRecordNumber->width()!=w) //resize
m_navRecordNumber->setFixedWidth(w);
m_navRecordCount->setText(n);
m_navRecordCount->deselect();
if (m_view)
m_view->updateScrollBars();
updateButtons(recordCount());
}
uint KexiRecordNavigator::currentRecordNumber() const
{
bool ok=true;
int r = m_navRecordNumber->text().toInt(&ok);
if (!ok || r<1)
r = 0;
return r;
}
uint KexiRecordNavigator::recordCount() const
{
bool ok=true;
int r = m_navRecordCount->text().toInt(&ok);
if (!ok || r<1)
r = 0;
return r;
}
void KexiRecordNavigator::setParentView(TQScrollView *view)
{
m_view = view;
}
void KexiRecordNavigator::updateGeometry(int leftMargin)
{
TQFrame::updateGeometry();
if (m_view) {
int navWidth;
if (m_view->horizontalScrollBar()->isVisible()) {
navWidth = sizeHint().width();
}
else {
navWidth = leftMargin + m_view->clipper()->width();
}
setGeometry(
m_view->frameWidth(),
m_view->height() - m_view->horizontalScrollBar()->sizeHint().height()-m_view->frameWidth(),
navWidth,
m_view->horizontalScrollBar()->sizeHint().height()
);
m_view->updateScrollBars();
}
}
void KexiRecordNavigator::setHBarGeometry( TQScrollBar & hbar, int x, int y, int w, int h )
{
hbar.setGeometry( x + width(), y, w - width(), h );
}
void KexiRecordNavigator::setLabelText(const TQString& text)
{
m_textLabel->setText(text.isEmpty() ? TQString() : (TQString::fromLatin1(" ")+text+" "));
}
void KexiRecordNavigator::setInsertingButtonVisible(bool set)
{
if (set)
m_navBtnNew->show();
else
m_navBtnNew->hide();
}
void KexiRecordNavigator::slotPrevButtonClicked()
{
emit prevButtonClicked();
if (d->handler)
d->handler->moveToPreviousRecordRequested();
}
void KexiRecordNavigator::slotNextButtonClicked()
{
emit nextButtonClicked();
if (d->handler)
d->handler->moveToNextRecordRequested();
}
void KexiRecordNavigator::slotLastButtonClicked()
{
emit lastButtonClicked();
if (d->handler)
d->handler->moveToLastRecordRequested();
}
void KexiRecordNavigator::slotFirstButtonClicked()
{
emit firstButtonClicked();
if (d->handler)
d->handler->moveToFirstRecordRequested();
}
void KexiRecordNavigator::slotNewButtonClicked()
{
emit newButtonClicked();
if (d->handler)
d->handler->addNewRecordRequested();
}
void KexiRecordNavigator::setRecordHandler(KexiRecordNavigatorHandler *handler)
{
d->handler = handler;
}
bool KexiRecordNavigator::editingIndicatorVisible() const
{
return d->editingIndicatorVisible;
}
bool KexiRecordNavigator::editingIndicatorEnabled() const
{
return d->editingIndicatorEnabled;
}
void KexiRecordNavigator::setEditingIndicatorEnabled(bool set)
{
d->editingIndicatorEnabled = set;
if (d->editingIndicatorEnabled) {
if (!d->editingIndicatorLabel) {
d->editingIndicatorLabel = new TQLabel(this);
d->editingIndicatorLabel->setAlignment(TQt::AlignCenter);
TQPixmap pix;
pix.convertFromImage( *KexiRecordMarker::penImage() );
d->editingIndicatorLabel->setFixedWidth( pix.width() + 2*2 );
d->lyr->insertWidget( 0, d->editingIndicatorLabel );
}
d->editingIndicatorLabel->show();
}
else {
if (d->editingIndicatorLabel) {
d->editingIndicatorLabel->hide();
}
}
}
void KexiRecordNavigator::showEditingIndicator(bool show)
{
d->editingIndicatorVisible = show;
updateButtons(recordCount()); //this will refresh 'next btn'
if (!d->editingIndicatorEnabled)
return;
if (d->editingIndicatorVisible) {
TQPixmap pix;
pix.convertFromImage( *KexiRecordMarker::penImage() );
d->editingIndicatorLabel->setPixmap( pix );
TQToolTip::add( d->editingIndicatorLabel, i18n("Editing indicator") );
}
else {
d->editingIndicatorLabel->setPixmap( TQPixmap() );
TQToolTip::remove( d->editingIndicatorLabel );
}
}
//------------------------------------------------
//! @internal
class KexiRecordNavigatorActionsInternal {
public:
KexiRecordNavigatorActionsInternal()
: moveToFirstRecord(i18n("First row"), "navigator_first", i18n("Go to first row"))
, moveToPreviousRecord(i18n("Previous row"), "navigator_prev", i18n("Go to previous row"))
, moveToNextRecord(i18n("Next row"), "navigator_next", i18n("Go to next row"))
, moveToLastRecord(i18n("Last row"), "navigator_last", i18n("Go to last row"))
, moveToNewRecord(i18n("New row"), "navigator_new", i18n("Go to new row"))
{
}
static void init();
KGuiItem moveToFirstRecord;
KGuiItem moveToPreviousRecord;
KGuiItem moveToNextRecord;
KGuiItem moveToLastRecord;
KGuiItem moveToNewRecord;
};
static KStaticDeleter<KexiRecordNavigatorActionsInternal> KexiRecordNavigatorActions_deleter;
KexiRecordNavigatorActionsInternal* KexiRecordNavigatorActions_internal = 0;
void KexiRecordNavigatorActionsInternal::init()
{
if (!KexiRecordNavigatorActions_internal)
KexiRecordNavigatorActions_deleter.setObject(KexiRecordNavigatorActions_internal,
new KexiRecordNavigatorActionsInternal());
}
const KGuiItem& KexiRecordNavigator::Actions::moveToFirstRecord()
{ KexiRecordNavigatorActionsInternal::init(); return KexiRecordNavigatorActions_internal->moveToFirstRecord; }
const KGuiItem& KexiRecordNavigator::Actions::moveToPreviousRecord()
{ KexiRecordNavigatorActionsInternal::init(); return KexiRecordNavigatorActions_internal->moveToPreviousRecord; }
const KGuiItem& KexiRecordNavigator::Actions::moveToNextRecord()
{ KexiRecordNavigatorActionsInternal::init(); return KexiRecordNavigatorActions_internal->moveToNextRecord; }
const KGuiItem& KexiRecordNavigator::Actions::moveToLastRecord()
{ KexiRecordNavigatorActionsInternal::init(); return KexiRecordNavigatorActions_internal->moveToLastRecord; }
const KGuiItem& KexiRecordNavigator::Actions::moveToNewRecord()
{ KexiRecordNavigatorActionsInternal::init(); return KexiRecordNavigatorActions_internal->moveToNewRecord; }
#include "kexirecordnavigator.moc"