summaryrefslogtreecommitdiffstats
path: root/kexi/widget/utils/kexirecordnavigator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kexi/widget/utils/kexirecordnavigator.cpp')
-rw-r--r--kexi/widget/utils/kexirecordnavigator.cpp511
1 files changed, 511 insertions, 0 deletions
diff --git a/kexi/widget/utils/kexirecordnavigator.cpp b/kexi/widget/utils/kexirecordnavigator.cpp
new file mode 100644
index 00000000..f0dff087
--- /dev/null
+++ b/kexi/widget/utils/kexirecordnavigator.cpp
@@ -0,0 +1,511 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Lucijan Busch <[email protected]>
+ Copyright (C) 2003-2004 Jaroslaw Staniek <[email protected]>
+
+ 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 <qtoolbutton.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qvalidator.h>
+#include <qtooltip.h>
+#include <qscrollview.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;
+ QHBoxLayout *lyr;
+
+ QLabel *editingIndicatorLabel;
+ bool editingIndicatorEnabled : 1;
+ bool editingIndicatorVisible : 1;
+};
+
+//--------------------------------------------------
+
+KexiRecordNavigatorHandler::KexiRecordNavigatorHandler()
+{
+}
+
+KexiRecordNavigatorHandler::~KexiRecordNavigatorHandler()
+{
+}
+
+//--------------------------------------------------
+
+KexiRecordNavigator::KexiRecordNavigator(QWidget *parent, int leftMargin, const char *name)
+ : QFrame(parent, name)
+ , m_view(0)
+ , m_isInsertingEnabled(true)
+ , d( new KexiRecordNavigatorPrivate() )
+{
+ if (parent->inherits("QScrollView"))
+ setParentView( dynamic_cast<QScrollView*>(parent) );
+ setFrameStyle(QFrame::NoFrame);
+ d->lyr = new QHBoxLayout(this,0,0,"nav_lyr");
+
+ m_textLabel = new QLabel(this);
+ d->lyr->addWidget( m_textLabel );
+ setLabelText(i18n("Row:"));
+
+ int bw = 6+SmallIcon("navigator_first").width(); //QMIN( horizontalScrollBar()->height(), 20);
+ QFont f = font();
+ f.setPixelSize((bw > 12) ? 12 : bw);
+ QFontMetrics fm(f);
+ m_nav1DigitWidth = fm.width("8");
+
+ d->lyr->addWidget( m_navBtnFirst = new QToolButton(this) );
+ m_navBtnFirst->setFixedWidth(bw);
+ m_navBtnFirst->setFocusPolicy(NoFocus);
+ m_navBtnFirst->setIconSet( SmallIconSet("navigator_first") );
+ QToolTip::add(m_navBtnFirst, i18n("First row"));
+
+ d->lyr->addWidget( m_navBtnPrev = new QToolButton(this) );
+ m_navBtnPrev->setFixedWidth(bw);
+ m_navBtnPrev->setFocusPolicy(NoFocus);
+ m_navBtnPrev->setIconSet( SmallIconSet("navigator_prev") );
+ m_navBtnPrev->setAutoRepeat(true);
+ QToolTip::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(ClickFocus);
+ m_navRecordNumber->installEventFilter(this);
+// m_navRowNumber->setFixedWidth(fw);
+ m_navRecordNumberValidator = new QIntValidator(1, INT_MAX, this);
+ m_navRecordNumber->setValidator(m_navRecordNumberValidator);
+ m_navRecordNumber->installEventFilter(this);
+ QToolTip::add(m_navRecordNumber, i18n("Current row number"));
+
+ KLineEdit *lbl_of = new KLineEdit(i18n("of"), this);
+ lbl_of->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Preferred);
+ lbl_of->setMaximumWidth(fm.width(lbl_of->text())+8);
+ lbl_of->setReadOnly(true);
+ lbl_of->setLineWidth(0);
+ lbl_of->setFocusPolicy(NoFocus);
+ lbl_of->setAlignment(AlignCenter);
+ d->lyr->addWidget( lbl_of );
+
+ d->lyr->addWidget( m_navRecordCount = new KLineEdit(this) );
+ m_navRecordCount->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Preferred);
+ m_navRecordCount->setReadOnly(true);
+ m_navRecordCount->setLineWidth(0);
+ m_navRecordCount->setFocusPolicy(NoFocus);
+ m_navRecordCount->setAlignment(AlignLeft | AlignVCenter);
+ QToolTip::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 QToolButton(this) );
+ m_navBtnNext->setFixedWidth(bw);
+ m_navBtnNext->setFocusPolicy(NoFocus);
+ m_navBtnNext->setIconSet( SmallIconSet("navigator_next") );
+ m_navBtnNext->setAutoRepeat(true);
+ QToolTip::add(m_navBtnNext, i18n("Next row"));
+
+ d->lyr->addWidget( m_navBtnLast = new QToolButton(this) );
+ m_navBtnLast->setFixedWidth(bw);
+ m_navBtnLast->setFocusPolicy(NoFocus);
+ m_navBtnLast->setIconSet( SmallIconSet("navigator_last") );
+ QToolTip::add(m_navBtnLast, i18n("Last row"));
+
+ d->lyr->addSpacing( 6 );
+ d->lyr->addWidget( m_navBtnNew = new QToolButton(this) );
+ m_navBtnNew->setFixedWidth(bw);
+ m_navBtnNew->setFocusPolicy(NoFocus);
+ m_navBtnNew->setIconSet( SmallIconSet("navigator_new") );
+ QToolTip::add(m_navBtnNew, i18n("New row"));
+ m_navBtnNext->setEnabled(isInsertingEnabled());
+
+ d->lyr->addSpacing( 6 );
+ d->lyr->addStretch(10);
+
+ connect(m_navBtnPrev,SIGNAL(clicked()),this,SLOT(slotPrevButtonClicked()));
+ connect(m_navBtnNext,SIGNAL(clicked()),this,SLOT(slotNextButtonClicked()));
+ connect(m_navBtnLast,SIGNAL(clicked()),this,SLOT(slotLastButtonClicked()));
+ connect(m_navBtnFirst,SIGNAL(clicked()),this,SLOT(slotFirstButtonClicked()));
+ connect(m_navBtnNew,SIGNAL(clicked()),this,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 )
+{
+ QFrame::setEnabled(set);
+ if (set && !m_isInsertingEnabled)
+ m_navBtnNew->setEnabled( false );
+}
+
+bool KexiRecordNavigator::eventFilter( QObject *o, QEvent *e )
+{
+ if (o==m_navRecordNumber) {
+ bool recordEntered = false;
+ bool ret;
+ if (e->type()==QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ switch (ke->key()) {
+ case Qt::Key_Escape: {
+ ke->accept();
+ m_navRecordNumber->undo();
+ if (m_view)
+ m_view->setFocus();
+ return true;
+ }
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ case Qt::Key_Tab:
+ case Qt::Key_BackTab:
+ {
+ recordEntered=true;
+ ke->accept(); //to avoid pressing Enter later
+ ret = true;
+ }
+ default:;
+ }
+ }
+ else if (e->type()==QEvent::FocusOut) {
+ if (static_cast<QFocusEvent*>(e)->reason()!=QFocusEvent::Tab
+ && static_cast<QFocusEvent*>(e)->reason()!=QFocusEvent::Backtab
+ && static_cast<QFocusEvent*>(e)->reason()!=QFocusEvent::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()==QEvent::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);
+ QString n;
+ if (r>0)
+ n = QString::number(r);
+ else
+ n = " ";
+// if (d->navRecordNumber->text().length() != n.length()) {//resize
+// d->navRecordNumber->setFixedWidth(
+// d->nav1DigitWidth*QMAX( QMAX(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 QString & n = QString::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*QMAX( QMAX(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(QScrollView *view)
+{
+ m_view = view;
+}
+
+void KexiRecordNavigator::updateGeometry(int leftMargin)
+{
+ QFrame::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( QScrollBar & hbar, int x, int y, int w, int h )
+{
+ hbar.setGeometry( x + width(), y, w - width(), h );
+}
+
+void KexiRecordNavigator::setLabelText(const QString& text)
+{
+ m_textLabel->setText(text.isEmpty() ? QString::null : (QString::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 QLabel(this);
+ d->editingIndicatorLabel->setAlignment(Qt::AlignCenter);
+ QPixmap 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) {
+ QPixmap pix;
+ pix.convertFromImage( *KexiRecordMarker::penImage() );
+ d->editingIndicatorLabel->setPixmap( pix );
+ QToolTip::add( d->editingIndicatorLabel, i18n("Editing indicator") );
+ }
+ else {
+ d->editingIndicatorLabel->setPixmap( QPixmap() );
+ QToolTip::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"