kexi

kexirecordnavigator.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004 Lucijan Busch <lucijan@kde.org>
00003    Copyright (C) 2003-2004 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this program; see the file COPYING.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include <qtoolbutton.h>
00022 #include <qlayout.h>
00023 #include <qlabel.h>
00024 #include <qvalidator.h>
00025 #include <qtooltip.h>
00026 #include <qscrollview.h>
00027 
00028 #include <klocale.h>
00029 #include <kiconloader.h>
00030 #include <klineedit.h>
00031 
00032 #include "kexirecordnavigator.h"
00033 #include "kexirecordmarker.h"
00034 
00036 class KexiRecordNavigatorPrivate
00037 {
00038     public:
00039         KexiRecordNavigatorPrivate()
00040          : handler(0)
00041          , editingIndicatorLabel(0)
00042          , editingIndicatorEnabled(false)
00043          , editingIndicatorVisible(false)
00044         {
00045         }
00046         KexiRecordNavigatorHandler *handler;
00047         QHBoxLayout *lyr;
00048 
00049         QLabel *editingIndicatorLabel;
00050         bool editingIndicatorEnabled : 1;
00051         bool editingIndicatorVisible : 1;
00052 };
00053 
00054 //--------------------------------------------------
00055 
00056 KexiRecordNavigatorHandler::KexiRecordNavigatorHandler()
00057 {
00058 }
00059 
00060 KexiRecordNavigatorHandler::~KexiRecordNavigatorHandler()
00061 {
00062 }
00063 
00064 //--------------------------------------------------
00065 
00066 KexiRecordNavigator::KexiRecordNavigator(QWidget *parent, int leftMargin, const char *name)
00067  : QFrame(parent, name)
00068  , m_view(0)
00069  , m_isInsertingEnabled(true)
00070  , d( new KexiRecordNavigatorPrivate() )
00071 {
00072     if (parent->inherits("QScrollView"))
00073         setParentView( dynamic_cast<QScrollView*>(parent) );
00074     setFrameStyle(QFrame::NoFrame);
00075     d->lyr = new QHBoxLayout(this,0,0,"nav_lyr");
00076 
00077     m_textLabel = new QLabel(this);
00078     d->lyr->addWidget( m_textLabel  );
00079     setLabelText(i18n("Row:"));
00080         
00081     int bw = 6+SmallIcon("navigator_first").width(); //QMIN( horizontalScrollBar()->height(), 20);
00082     QFont f = font();
00083     f.setPixelSize((bw > 12) ? 12 : bw);
00084     QFontMetrics fm(f);
00085     m_nav1DigitWidth = fm.width("8");
00086 
00087     d->lyr->addWidget( m_navBtnFirst = new QToolButton(this) );
00088     m_navBtnFirst->setFixedWidth(bw);
00089     m_navBtnFirst->setFocusPolicy(NoFocus);
00090     m_navBtnFirst->setIconSet( SmallIconSet("navigator_first") );
00091     QToolTip::add(m_navBtnFirst, i18n("First row"));
00092     
00093     d->lyr->addWidget( m_navBtnPrev = new QToolButton(this) );
00094     m_navBtnPrev->setFixedWidth(bw);
00095     m_navBtnPrev->setFocusPolicy(NoFocus);
00096     m_navBtnPrev->setIconSet( SmallIconSet("navigator_prev") );
00097     m_navBtnPrev->setAutoRepeat(true);
00098     QToolTip::add(m_navBtnPrev, i18n("Previous row"));
00099     
00100     d->lyr->addSpacing( 6 );
00101     
00102     d->lyr->addWidget( m_navRecordNumber = new KLineEdit(this) );
00103     m_navRecordNumber->setAlignment(AlignRight | AlignVCenter);
00104     m_navRecordNumber->setFocusPolicy(ClickFocus);
00105     m_navRecordNumber->installEventFilter(this);
00106 //  m_navRowNumber->setFixedWidth(fw);
00107     m_navRecordNumberValidator = new QIntValidator(1, INT_MAX, this);
00108     m_navRecordNumber->setValidator(m_navRecordNumberValidator);
00109     m_navRecordNumber->installEventFilter(this);
00110     QToolTip::add(m_navRecordNumber, i18n("Current row number"));
00111     
00112     KLineEdit *lbl_of = new KLineEdit(i18n("of"), this);
00113     lbl_of->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Preferred);
00114     lbl_of->setMaximumWidth(fm.width(lbl_of->text())+8);
00115     lbl_of->setReadOnly(true);
00116     lbl_of->setLineWidth(0);
00117     lbl_of->setFocusPolicy(NoFocus);
00118     lbl_of->setAlignment(AlignCenter);
00119     d->lyr->addWidget( lbl_of );
00120     
00121     d->lyr->addWidget( m_navRecordCount = new KLineEdit(this) );
00122     m_navRecordCount->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Preferred);
00123     m_navRecordCount->setReadOnly(true);
00124     m_navRecordCount->setLineWidth(0);
00125     m_navRecordCount->setFocusPolicy(NoFocus);
00126     m_navRecordCount->setAlignment(AlignLeft | AlignVCenter);
00127     QToolTip::add(m_navRecordCount, i18n("Number of rows"));
00128 
00129     lbl_of->setFont(f);
00130     m_navRecordNumber->setFont(f);
00131     m_navRecordCount->setFont(f);
00132     setFont(f);
00133 
00134     d->lyr->addWidget( m_navBtnNext = new QToolButton(this) );
00135     m_navBtnNext->setFixedWidth(bw);
00136     m_navBtnNext->setFocusPolicy(NoFocus);
00137     m_navBtnNext->setIconSet( SmallIconSet("navigator_next") );
00138     m_navBtnNext->setAutoRepeat(true);
00139     QToolTip::add(m_navBtnNext, i18n("Next row"));
00140     
00141     d->lyr->addWidget( m_navBtnLast = new QToolButton(this) );
00142     m_navBtnLast->setFixedWidth(bw);
00143     m_navBtnLast->setFocusPolicy(NoFocus);
00144     m_navBtnLast->setIconSet( SmallIconSet("navigator_last") );
00145     QToolTip::add(m_navBtnLast, i18n("Last row"));
00146     
00147     d->lyr->addSpacing( 6 );
00148     d->lyr->addWidget( m_navBtnNew = new QToolButton(this) );
00149     m_navBtnNew->setFixedWidth(bw);
00150     m_navBtnNew->setFocusPolicy(NoFocus);
00151     m_navBtnNew->setIconSet( SmallIconSet("navigator_new") );
00152     QToolTip::add(m_navBtnNew, i18n("New row"));
00153     m_navBtnNext->setEnabled(isInsertingEnabled());
00154     
00155     d->lyr->addSpacing( 6 );
00156     d->lyr->addStretch(10);
00157 
00158     connect(m_navBtnPrev,SIGNAL(clicked()),this,SLOT(slotPrevButtonClicked()));
00159     connect(m_navBtnNext,SIGNAL(clicked()),this,SLOT(slotNextButtonClicked()));
00160     connect(m_navBtnLast,SIGNAL(clicked()),this,SLOT(slotLastButtonClicked()));
00161     connect(m_navBtnFirst,SIGNAL(clicked()),this,SLOT(slotFirstButtonClicked()));
00162     connect(m_navBtnNew,SIGNAL(clicked()),this,SLOT(slotNewButtonClicked()));
00163 
00164     setRecordCount(0);
00165     setCurrentRecordNumber(0);
00166 
00167     updateGeometry(leftMargin);
00168 }
00169 
00170 KexiRecordNavigator::~KexiRecordNavigator()
00171 {
00172     delete d;
00173 }
00174 
00175 void KexiRecordNavigator::setInsertingEnabled(bool set)
00176 {
00177     if (m_isInsertingEnabled==set)
00178         return;
00179     m_isInsertingEnabled = set;
00180     if (isEnabled())
00181         m_navBtnNew->setEnabled( m_isInsertingEnabled );
00182 }
00183 
00184 void KexiRecordNavigator::setEnabled( bool set )
00185 {
00186     QFrame::setEnabled(set);
00187     if (set && !m_isInsertingEnabled)
00188         m_navBtnNew->setEnabled( false );
00189 }
00190 
00191 bool KexiRecordNavigator::eventFilter( QObject *o, QEvent *e )
00192 {
00193     if (o==m_navRecordNumber) {
00194         bool recordEntered = false;
00195         bool ret;
00196         if (e->type()==QEvent::KeyPress) {
00197             QKeyEvent *ke = static_cast<QKeyEvent*>(e);
00198             switch (ke->key()) {
00199             case Qt::Key_Escape: {
00200                 ke->accept();
00201                 m_navRecordNumber->undo();
00202                 if (m_view)
00203                     m_view->setFocus();
00204                 return true;
00205             }
00206             case Qt::Key_Enter:
00207             case Qt::Key_Return:
00208             case Qt::Key_Tab:
00209             case Qt::Key_BackTab: 
00210             {
00211                 recordEntered=true;
00212                 ke->accept(); //to avoid pressing Enter later
00213                 ret = true;
00214             }
00215             default:;
00216             }
00217         }
00218         else if (e->type()==QEvent::FocusOut) {
00219             if (static_cast<QFocusEvent*>(e)->reason()!=QFocusEvent::Tab
00220                 && static_cast<QFocusEvent*>(e)->reason()!=QFocusEvent::Backtab
00221                 && static_cast<QFocusEvent*>(e)->reason()!=QFocusEvent::Other)
00222                 recordEntered=true;
00223             ret = false;
00224         }
00225 
00226         if (recordEntered) {
00227             bool ok=true;
00228             uint r = m_navRecordNumber->text().toUInt(&ok);
00229             if (!ok || r<1)
00230                 r = (recordCount()>0)?1:0;
00231             if (m_view && (hasFocus() || e->type()==QEvent::KeyPress))
00232                 m_view->setFocus();
00233             setCurrentRecordNumber(r);
00234             emit recordNumberEntered(r);
00235             if (d->handler)
00236                 d->handler->moveToRecordRequested(r-1);
00237             return ret;
00238         }
00239     }
00240 /*
00241     bool ok=true;
00242     int r = text.toInt(&ok);
00243     if (!ok || r<1)
00244         r = 1;
00245     emit recordNumberEntered(r);*/
00246     return false;
00247 }
00248 
00249 void KexiRecordNavigator::setCurrentRecordNumber(uint r)
00250 {
00251     uint recCnt = recordCount();
00252     if (r>(recCnt+(m_isInsertingEnabled?1:0)))
00253         r = recCnt+(m_isInsertingEnabled?1:0);
00254     QString n;
00255     if (r>0)
00256         n = QString::number(r);
00257     else
00258         n = " ";
00259 //  if (d->navRecordNumber->text().length() != n.length()) {//resize
00260 //      d->navRecordNumber->setFixedWidth(
00261 //          d->nav1DigitWidth*QMAX( QMAX(n.length(),2)+1,d->navRecordCount->text().length()+1)+6 
00262 //      );
00263 //  }
00264 
00265     m_navRecordNumber->setText(n);
00266     m_navRecordCount->deselect();
00267     updateButtons(recCnt);
00268 }
00269 
00270 void KexiRecordNavigator::updateButtons(uint recCnt)
00271 {
00272     const uint r = currentRecordNumber();
00273     if (isEnabled()) {
00274         m_navBtnPrev->setEnabled(r > 1);
00275         m_navBtnFirst->setEnabled(r > 1);
00276         m_navBtnNext->setEnabled(r > 0 
00277             && r < (recCnt +(m_isInsertingEnabled?(1+d->editingIndicatorVisible/*if we're editing, next btn is avail.*/):0) ) );
00278         m_navBtnLast->setEnabled(r!=(recCnt+(m_isInsertingEnabled?1:0)) && (m_isInsertingEnabled || recCnt>0));
00279     }
00280 }
00281 
00282 void KexiRecordNavigator::setRecordCount(uint count)
00283 {
00284     const QString & n = QString::number(count);
00285     if (m_isInsertingEnabled && currentRecordNumber()==0) {
00286         setCurrentRecordNumber(1);
00287     }
00288     if (m_navRecordCount->text().length() != n.length()) {//resize
00289         m_navRecordCount->setFixedWidth(m_nav1DigitWidth*n.length()+6);
00290         
00291         if (m_view && m_view->horizontalScrollBar()->isVisible()) {
00292             //+width of the delta
00293             resize(width()+(n.length()-m_navRecordCount->text().length())*m_nav1DigitWidth, height());
00294 //          horizontalScrollBar()->move(d->navPanel->x()+d->navPanel->width()+20,horizontalScrollBar()->y());
00295         }
00296     }
00297     //update row number widget's width
00298     const int w = m_nav1DigitWidth*QMAX( QMAX(n.length(),2)+1,m_navRecordNumber->text().length()+1)+6;
00299     if (m_navRecordNumber->width()!=w) //resize
00300         m_navRecordNumber->setFixedWidth(w);
00301 
00302     m_navRecordCount->setText(n);
00303     m_navRecordCount->deselect();
00304     if (m_view)
00305         m_view->updateScrollBars();
00306     updateButtons(recordCount());
00307 }
00308 
00309 uint KexiRecordNavigator::currentRecordNumber() const
00310 {
00311     bool ok=true;
00312     int r = m_navRecordNumber->text().toInt(&ok);
00313     if (!ok || r<1)
00314         r = 0;
00315     return r;
00316 }
00317 
00318 uint KexiRecordNavigator::recordCount() const
00319 {
00320     bool ok=true;
00321     int r = m_navRecordCount->text().toInt(&ok);
00322     if (!ok || r<1)
00323         r = 0;
00324     return r;
00325 }
00326 
00327 void KexiRecordNavigator::setParentView(QScrollView *view)
00328 {
00329     m_view = view;
00330 }
00331 
00332 void KexiRecordNavigator::updateGeometry(int leftMargin)
00333 {
00334     QFrame::updateGeometry();
00335     if (m_view) {
00336         int navWidth;
00337         if (m_view->horizontalScrollBar()->isVisible()) {
00338             navWidth = sizeHint().width();
00339         }
00340         else {
00341             navWidth = leftMargin + m_view->clipper()->width();
00342         }
00343         
00344         setGeometry(
00345             m_view->frameWidth(),
00346             m_view->height() - m_view->horizontalScrollBar()->sizeHint().height()-m_view->frameWidth(),
00347             navWidth,
00348             m_view->horizontalScrollBar()->sizeHint().height()
00349         );
00350 
00351         m_view->updateScrollBars();
00352     }
00353 }
00354 
00355 void KexiRecordNavigator::setHBarGeometry( QScrollBar & hbar, int x, int y, int w, int h )
00356 {
00357     hbar.setGeometry( x + width(), y, w - width(), h );
00358 }
00359 
00360 void KexiRecordNavigator::setLabelText(const QString& text)
00361 {
00362     m_textLabel->setText(text.isEmpty() ? QString::null : (QString::fromLatin1(" ")+text+" "));
00363 }
00364 
00365 void KexiRecordNavigator::setInsertingButtonVisible(bool set)
00366 {
00367     if (set)
00368         m_navBtnNew->show();
00369     else
00370         m_navBtnNew->hide();
00371 }
00372 
00373 void KexiRecordNavigator::slotPrevButtonClicked()
00374 {
00375     emit prevButtonClicked();
00376     if (d->handler)
00377         d->handler->moveToPreviousRecordRequested();
00378 }
00379 
00380 void KexiRecordNavigator::slotNextButtonClicked()
00381 {
00382     emit nextButtonClicked();
00383     if (d->handler)
00384         d->handler->moveToNextRecordRequested();
00385 }
00386 
00387 void KexiRecordNavigator::slotLastButtonClicked()
00388 {
00389     emit lastButtonClicked();
00390     if (d->handler)
00391         d->handler->moveToLastRecordRequested();
00392 }
00393 
00394 void KexiRecordNavigator::slotFirstButtonClicked()
00395 {
00396     emit firstButtonClicked();
00397     if (d->handler)
00398         d->handler->moveToFirstRecordRequested();
00399 }
00400 
00401 void KexiRecordNavigator::slotNewButtonClicked()
00402 {
00403     emit newButtonClicked();
00404     if (d->handler)
00405         d->handler->addNewRecordRequested();
00406 }
00407 
00408 
00409 void KexiRecordNavigator::setRecordHandler(KexiRecordNavigatorHandler *handler)
00410 {
00411     d->handler = handler;
00412 }
00413 
00414 bool KexiRecordNavigator::editingIndicatorVisible() const
00415 {
00416     return d->editingIndicatorVisible;
00417 }
00418 
00419 bool KexiRecordNavigator::editingIndicatorEnabled() const
00420 {
00421     return d->editingIndicatorEnabled;
00422 }
00423 
00424 void KexiRecordNavigator::setEditingIndicatorEnabled(bool set)
00425 {
00426     d->editingIndicatorEnabled = set;
00427     if (d->editingIndicatorEnabled) {
00428         if (!d->editingIndicatorLabel) {
00429             d->editingIndicatorLabel = new QLabel(this);
00430             d->editingIndicatorLabel->setAlignment(Qt::AlignCenter);
00431             QPixmap pix;
00432             pix.convertFromImage( *KexiRecordMarker::penImage() );
00433             d->editingIndicatorLabel->setFixedWidth( pix.width() + 2*2 );
00434             d->lyr->insertWidget( 0, d->editingIndicatorLabel );
00435         }
00436         d->editingIndicatorLabel->show();
00437     }
00438     else {
00439         if (d->editingIndicatorLabel) {
00440             d->editingIndicatorLabel->hide();
00441         }
00442     }
00443 }
00444 
00445 void KexiRecordNavigator::showEditingIndicator(bool show)
00446 {
00447     d->editingIndicatorVisible = show;
00448     updateButtons(recordCount()); //this will refresh 'next btn'
00449     if (!d->editingIndicatorEnabled)
00450         return;
00451     if (d->editingIndicatorVisible) {
00452         QPixmap pix;
00453         pix.convertFromImage( *KexiRecordMarker::penImage() );
00454         d->editingIndicatorLabel->setPixmap( pix );
00455         QToolTip::add( d->editingIndicatorLabel, i18n("Editing indicator") );
00456     }
00457     else {
00458         d->editingIndicatorLabel->setPixmap( QPixmap() );
00459         QToolTip::remove( d->editingIndicatorLabel );
00460     }
00461 }
00462 
00463 #include "kexirecordnavigator.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys