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.
512 lines
15 KiB
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"
|