00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 #include <kguiitem.h>
00032 #include <kstaticdeleter.h>
00033
00034 #include "kexirecordnavigator.h"
00035 #include "kexirecordmarker.h"
00036
00038 class KexiRecordNavigatorPrivate
00039 {
00040 public:
00041 KexiRecordNavigatorPrivate()
00042 : handler(0)
00043 , editingIndicatorLabel(0)
00044 , editingIndicatorEnabled(false)
00045 , editingIndicatorVisible(false)
00046 {
00047 }
00048 KexiRecordNavigatorHandler *handler;
00049 QHBoxLayout *lyr;
00050
00051 QLabel *editingIndicatorLabel;
00052 bool editingIndicatorEnabled : 1;
00053 bool editingIndicatorVisible : 1;
00054 };
00055
00056
00057
00058 KexiRecordNavigatorHandler::KexiRecordNavigatorHandler()
00059 {
00060 }
00061
00062 KexiRecordNavigatorHandler::~KexiRecordNavigatorHandler()
00063 {
00064 }
00065
00066
00067
00068 KexiRecordNavigator::KexiRecordNavigator(QWidget *parent, int leftMargin, const char *name)
00069 : QFrame(parent, name)
00070 , m_view(0)
00071 , m_isInsertingEnabled(true)
00072 , d( new KexiRecordNavigatorPrivate() )
00073 {
00074 if (parent->inherits("QScrollView"))
00075 setParentView( dynamic_cast<QScrollView*>(parent) );
00076 setFrameStyle(QFrame::NoFrame);
00077 d->lyr = new QHBoxLayout(this,0,0,"nav_lyr");
00078
00079 m_textLabel = new QLabel(this);
00080 d->lyr->addWidget( m_textLabel );
00081 setLabelText(i18n("Row:"));
00082
00083 int bw = 6+SmallIcon("navigator_first").width();
00084 QFont f = font();
00085 f.setPixelSize((bw > 12) ? 12 : bw);
00086 QFontMetrics fm(f);
00087 m_nav1DigitWidth = fm.width("8");
00088
00089 d->lyr->addWidget( m_navBtnFirst = new QToolButton(this) );
00090 m_navBtnFirst->setFixedWidth(bw);
00091 m_navBtnFirst->setFocusPolicy(NoFocus);
00092 m_navBtnFirst->setIconSet( SmallIconSet("navigator_first") );
00093 QToolTip::add(m_navBtnFirst, i18n("First row"));
00094
00095 d->lyr->addWidget( m_navBtnPrev = new QToolButton(this) );
00096 m_navBtnPrev->setFixedWidth(bw);
00097 m_navBtnPrev->setFocusPolicy(NoFocus);
00098 m_navBtnPrev->setIconSet( SmallIconSet("navigator_prev") );
00099 m_navBtnPrev->setAutoRepeat(true);
00100 QToolTip::add(m_navBtnPrev, i18n("Previous row"));
00101
00102 d->lyr->addSpacing( 6 );
00103
00104 d->lyr->addWidget( m_navRecordNumber = new KLineEdit(this) );
00105 m_navRecordNumber->setAlignment(AlignRight | AlignVCenter);
00106 m_navRecordNumber->setFocusPolicy(ClickFocus);
00107 m_navRecordNumber->installEventFilter(this);
00108
00109 m_navRecordNumberValidator = new QIntValidator(1, INT_MAX, this);
00110 m_navRecordNumber->setValidator(m_navRecordNumberValidator);
00111 m_navRecordNumber->installEventFilter(this);
00112 QToolTip::add(m_navRecordNumber, i18n("Current row number"));
00113
00114 KLineEdit *lbl_of = new KLineEdit(i18n("of"), this);
00115 lbl_of->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Preferred);
00116 lbl_of->setMaximumWidth(fm.width(lbl_of->text())+8);
00117 lbl_of->setReadOnly(true);
00118 lbl_of->setLineWidth(0);
00119 lbl_of->setFocusPolicy(NoFocus);
00120 lbl_of->setAlignment(AlignCenter);
00121 d->lyr->addWidget( lbl_of );
00122
00123 d->lyr->addWidget( m_navRecordCount = new KLineEdit(this) );
00124 m_navRecordCount->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Preferred);
00125 m_navRecordCount->setReadOnly(true);
00126 m_navRecordCount->setLineWidth(0);
00127 m_navRecordCount->setFocusPolicy(NoFocus);
00128 m_navRecordCount->setAlignment(AlignLeft | AlignVCenter);
00129 QToolTip::add(m_navRecordCount, i18n("Number of rows"));
00130
00131 lbl_of->setFont(f);
00132 m_navRecordNumber->setFont(f);
00133 m_navRecordCount->setFont(f);
00134 setFont(f);
00135
00136 d->lyr->addWidget( m_navBtnNext = new QToolButton(this) );
00137 m_navBtnNext->setFixedWidth(bw);
00138 m_navBtnNext->setFocusPolicy(NoFocus);
00139 m_navBtnNext->setIconSet( SmallIconSet("navigator_next") );
00140 m_navBtnNext->setAutoRepeat(true);
00141 QToolTip::add(m_navBtnNext, i18n("Next row"));
00142
00143 d->lyr->addWidget( m_navBtnLast = new QToolButton(this) );
00144 m_navBtnLast->setFixedWidth(bw);
00145 m_navBtnLast->setFocusPolicy(NoFocus);
00146 m_navBtnLast->setIconSet( SmallIconSet("navigator_last") );
00147 QToolTip::add(m_navBtnLast, i18n("Last row"));
00148
00149 d->lyr->addSpacing( 6 );
00150 d->lyr->addWidget( m_navBtnNew = new QToolButton(this) );
00151 m_navBtnNew->setFixedWidth(bw);
00152 m_navBtnNew->setFocusPolicy(NoFocus);
00153 m_navBtnNew->setIconSet( SmallIconSet("navigator_new") );
00154 QToolTip::add(m_navBtnNew, i18n("New row"));
00155 m_navBtnNext->setEnabled(isInsertingEnabled());
00156
00157 d->lyr->addSpacing( 6 );
00158 d->lyr->addStretch(10);
00159
00160 connect(m_navBtnPrev,SIGNAL(clicked()),this,SLOT(slotPrevButtonClicked()));
00161 connect(m_navBtnNext,SIGNAL(clicked()),this,SLOT(slotNextButtonClicked()));
00162 connect(m_navBtnLast,SIGNAL(clicked()),this,SLOT(slotLastButtonClicked()));
00163 connect(m_navBtnFirst,SIGNAL(clicked()),this,SLOT(slotFirstButtonClicked()));
00164 connect(m_navBtnNew,SIGNAL(clicked()),this,SLOT(slotNewButtonClicked()));
00165
00166 setRecordCount(0);
00167 setCurrentRecordNumber(0);
00168
00169 updateGeometry(leftMargin);
00170 }
00171
00172 KexiRecordNavigator::~KexiRecordNavigator()
00173 {
00174 delete d;
00175 }
00176
00177 void KexiRecordNavigator::setInsertingEnabled(bool set)
00178 {
00179 if (m_isInsertingEnabled==set)
00180 return;
00181 m_isInsertingEnabled = set;
00182 if (isEnabled())
00183 m_navBtnNew->setEnabled( m_isInsertingEnabled );
00184 }
00185
00186 void KexiRecordNavigator::setEnabled( bool set )
00187 {
00188 QFrame::setEnabled(set);
00189 if (set && !m_isInsertingEnabled)
00190 m_navBtnNew->setEnabled( false );
00191 }
00192
00193 bool KexiRecordNavigator::eventFilter( QObject *o, QEvent *e )
00194 {
00195 if (o==m_navRecordNumber) {
00196 bool recordEntered = false;
00197 bool ret;
00198 if (e->type()==QEvent::KeyPress) {
00199 QKeyEvent *ke = static_cast<QKeyEvent*>(e);
00200 switch (ke->key()) {
00201 case Qt::Key_Escape: {
00202 ke->accept();
00203 m_navRecordNumber->undo();
00204 if (m_view)
00205 m_view->setFocus();
00206 return true;
00207 }
00208 case Qt::Key_Enter:
00209 case Qt::Key_Return:
00210 case Qt::Key_Tab:
00211 case Qt::Key_BackTab:
00212 {
00213 recordEntered=true;
00214 ke->accept();
00215 ret = true;
00216 }
00217 default:;
00218 }
00219 }
00220 else if (e->type()==QEvent::FocusOut) {
00221 if (static_cast<QFocusEvent*>(e)->reason()!=QFocusEvent::Tab
00222 && static_cast<QFocusEvent*>(e)->reason()!=QFocusEvent::Backtab
00223 && static_cast<QFocusEvent*>(e)->reason()!=QFocusEvent::Other)
00224 recordEntered=true;
00225 ret = false;
00226 }
00227
00228 if (recordEntered) {
00229 bool ok=true;
00230 uint r = m_navRecordNumber->text().toUInt(&ok);
00231 if (!ok || r<1)
00232 r = (recordCount()>0)?1:0;
00233 if (m_view && (hasFocus() || e->type()==QEvent::KeyPress))
00234 m_view->setFocus();
00235 setCurrentRecordNumber(r);
00236 emit recordNumberEntered(r);
00237 if (d->handler)
00238 d->handler->moveToRecordRequested(r-1);
00239 return ret;
00240 }
00241 }
00242
00243
00244
00245
00246
00247
00248 return false;
00249 }
00250
00251 void KexiRecordNavigator::setCurrentRecordNumber(uint r)
00252 {
00253 uint recCnt = recordCount();
00254 if (r>(recCnt+(m_isInsertingEnabled?1:0)))
00255 r = recCnt+(m_isInsertingEnabled?1:0);
00256 QString n;
00257 if (r>0)
00258 n = QString::number(r);
00259 else
00260 n = " ";
00261
00262
00263
00264
00265
00266
00267 m_navRecordNumber->setText(n);
00268 m_navRecordCount->deselect();
00269 updateButtons(recCnt);
00270 }
00271
00272 void KexiRecordNavigator::updateButtons(uint recCnt)
00273 {
00274 const uint r = currentRecordNumber();
00275 if (isEnabled()) {
00276 m_navBtnPrev->setEnabled(r > 1);
00277 m_navBtnFirst->setEnabled(r > 1);
00278 m_navBtnNext->setEnabled(r > 0
00279 && r < (recCnt +(m_isInsertingEnabled?(1+d->editingIndicatorVisible):0) ) );
00280 m_navBtnLast->setEnabled(r!=(recCnt+(m_isInsertingEnabled?1:0)) && (m_isInsertingEnabled || recCnt>0));
00281 }
00282 }
00283
00284 void KexiRecordNavigator::setRecordCount(uint count)
00285 {
00286 const QString & n = QString::number(count);
00287 if (m_isInsertingEnabled && currentRecordNumber()==0) {
00288 setCurrentRecordNumber(1);
00289 }
00290 if (m_navRecordCount->text().length() != n.length()) {
00291 m_navRecordCount->setFixedWidth(m_nav1DigitWidth*n.length()+6);
00292
00293 if (m_view && m_view->horizontalScrollBar()->isVisible()) {
00294
00295 resize(width()+(n.length()-m_navRecordCount->text().length())*m_nav1DigitWidth, height());
00296
00297 }
00298 }
00299
00300 const int w = m_nav1DigitWidth*QMAX( QMAX(n.length(),2)+1,m_navRecordNumber->text().length()+1)+6;
00301 if (m_navRecordNumber->width()!=w)
00302 m_navRecordNumber->setFixedWidth(w);
00303
00304 m_navRecordCount->setText(n);
00305 m_navRecordCount->deselect();
00306 if (m_view)
00307 m_view->updateScrollBars();
00308 updateButtons(recordCount());
00309 }
00310
00311 uint KexiRecordNavigator::currentRecordNumber() const
00312 {
00313 bool ok=true;
00314 int r = m_navRecordNumber->text().toInt(&ok);
00315 if (!ok || r<1)
00316 r = 0;
00317 return r;
00318 }
00319
00320 uint KexiRecordNavigator::recordCount() const
00321 {
00322 bool ok=true;
00323 int r = m_navRecordCount->text().toInt(&ok);
00324 if (!ok || r<1)
00325 r = 0;
00326 return r;
00327 }
00328
00329 void KexiRecordNavigator::setParentView(QScrollView *view)
00330 {
00331 m_view = view;
00332 }
00333
00334 void KexiRecordNavigator::updateGeometry(int leftMargin)
00335 {
00336 QFrame::updateGeometry();
00337 if (m_view) {
00338 int navWidth;
00339 if (m_view->horizontalScrollBar()->isVisible()) {
00340 navWidth = sizeHint().width();
00341 }
00342 else {
00343 navWidth = leftMargin + m_view->clipper()->width();
00344 }
00345
00346 setGeometry(
00347 m_view->frameWidth(),
00348 m_view->height() - m_view->horizontalScrollBar()->sizeHint().height()-m_view->frameWidth(),
00349 navWidth,
00350 m_view->horizontalScrollBar()->sizeHint().height()
00351 );
00352
00353 m_view->updateScrollBars();
00354 }
00355 }
00356
00357 void KexiRecordNavigator::setHBarGeometry( QScrollBar & hbar, int x, int y, int w, int h )
00358 {
00359 hbar.setGeometry( x + width(), y, w - width(), h );
00360 }
00361
00362 void KexiRecordNavigator::setLabelText(const QString& text)
00363 {
00364 m_textLabel->setText(text.isEmpty() ? QString::null : (QString::fromLatin1(" ")+text+" "));
00365 }
00366
00367 void KexiRecordNavigator::setInsertingButtonVisible(bool set)
00368 {
00369 if (set)
00370 m_navBtnNew->show();
00371 else
00372 m_navBtnNew->hide();
00373 }
00374
00375 void KexiRecordNavigator::slotPrevButtonClicked()
00376 {
00377 emit prevButtonClicked();
00378 if (d->handler)
00379 d->handler->moveToPreviousRecordRequested();
00380 }
00381
00382 void KexiRecordNavigator::slotNextButtonClicked()
00383 {
00384 emit nextButtonClicked();
00385 if (d->handler)
00386 d->handler->moveToNextRecordRequested();
00387 }
00388
00389 void KexiRecordNavigator::slotLastButtonClicked()
00390 {
00391 emit lastButtonClicked();
00392 if (d->handler)
00393 d->handler->moveToLastRecordRequested();
00394 }
00395
00396 void KexiRecordNavigator::slotFirstButtonClicked()
00397 {
00398 emit firstButtonClicked();
00399 if (d->handler)
00400 d->handler->moveToFirstRecordRequested();
00401 }
00402
00403 void KexiRecordNavigator::slotNewButtonClicked()
00404 {
00405 emit newButtonClicked();
00406 if (d->handler)
00407 d->handler->addNewRecordRequested();
00408 }
00409
00410
00411 void KexiRecordNavigator::setRecordHandler(KexiRecordNavigatorHandler *handler)
00412 {
00413 d->handler = handler;
00414 }
00415
00416 bool KexiRecordNavigator::editingIndicatorVisible() const
00417 {
00418 return d->editingIndicatorVisible;
00419 }
00420
00421 bool KexiRecordNavigator::editingIndicatorEnabled() const
00422 {
00423 return d->editingIndicatorEnabled;
00424 }
00425
00426 void KexiRecordNavigator::setEditingIndicatorEnabled(bool set)
00427 {
00428 d->editingIndicatorEnabled = set;
00429 if (d->editingIndicatorEnabled) {
00430 if (!d->editingIndicatorLabel) {
00431 d->editingIndicatorLabel = new QLabel(this);
00432 d->editingIndicatorLabel->setAlignment(Qt::AlignCenter);
00433 QPixmap pix;
00434 pix.convertFromImage( *KexiRecordMarker::penImage() );
00435 d->editingIndicatorLabel->setFixedWidth( pix.width() + 2*2 );
00436 d->lyr->insertWidget( 0, d->editingIndicatorLabel );
00437 }
00438 d->editingIndicatorLabel->show();
00439 }
00440 else {
00441 if (d->editingIndicatorLabel) {
00442 d->editingIndicatorLabel->hide();
00443 }
00444 }
00445 }
00446
00447 void KexiRecordNavigator::showEditingIndicator(bool show)
00448 {
00449 d->editingIndicatorVisible = show;
00450 updateButtons(recordCount());
00451 if (!d->editingIndicatorEnabled)
00452 return;
00453 if (d->editingIndicatorVisible) {
00454 QPixmap pix;
00455 pix.convertFromImage( *KexiRecordMarker::penImage() );
00456 d->editingIndicatorLabel->setPixmap( pix );
00457 QToolTip::add( d->editingIndicatorLabel, i18n("Editing indicator") );
00458 }
00459 else {
00460 d->editingIndicatorLabel->setPixmap( QPixmap() );
00461 QToolTip::remove( d->editingIndicatorLabel );
00462 }
00463 }
00464
00465
00466
00468 class KexiRecordNavigatorActionsInternal {
00469 public:
00470 KexiRecordNavigatorActionsInternal()
00471 : moveToFirstRecord(i18n("First row"), "navigator_first", i18n("Go to first row"))
00472 , moveToPreviousRecord(i18n("Previous row"), "navigator_prev", i18n("Go to previous row"))
00473 , moveToNextRecord(i18n("Next row"), "navigator_next", i18n("Go to next row"))
00474 , moveToLastRecord(i18n("Last row"), "navigator_last", i18n("Go to last row"))
00475 , moveToNewRecord(i18n("New row"), "navigator_new", i18n("Go to new row"))
00476 {
00477 }
00478 static void init();
00479 KGuiItem moveToFirstRecord;
00480 KGuiItem moveToPreviousRecord;
00481 KGuiItem moveToNextRecord;
00482 KGuiItem moveToLastRecord;
00483 KGuiItem moveToNewRecord;
00484 };
00485
00486 static KStaticDeleter<KexiRecordNavigatorActionsInternal> KexiRecordNavigatorActions_deleter;
00487 KexiRecordNavigatorActionsInternal* KexiRecordNavigatorActions_internal = 0;
00488
00489 void KexiRecordNavigatorActionsInternal::init()
00490 {
00491 if (!KexiRecordNavigatorActions_internal)
00492 KexiRecordNavigatorActions_deleter.setObject(KexiRecordNavigatorActions_internal,
00493 new KexiRecordNavigatorActionsInternal());
00494 }
00495
00496 const KGuiItem& KexiRecordNavigator::Actions::moveToFirstRecord()
00497 { KexiRecordNavigatorActionsInternal::init(); return KexiRecordNavigatorActions_internal->moveToFirstRecord; }
00498
00499 const KGuiItem& KexiRecordNavigator::Actions::moveToPreviousRecord()
00500 { KexiRecordNavigatorActionsInternal::init(); return KexiRecordNavigatorActions_internal->moveToPreviousRecord; }
00501
00502 const KGuiItem& KexiRecordNavigator::Actions::moveToNextRecord()
00503 { KexiRecordNavigatorActionsInternal::init(); return KexiRecordNavigatorActions_internal->moveToNextRecord; }
00504
00505 const KGuiItem& KexiRecordNavigator::Actions::moveToLastRecord()
00506 { KexiRecordNavigatorActionsInternal::init(); return KexiRecordNavigatorActions_internal->moveToLastRecord; }
00507
00508 const KGuiItem& KexiRecordNavigator::Actions::moveToNewRecord()
00509 { KexiRecordNavigatorActionsInternal::init(); return KexiRecordNavigatorActions_internal->moveToNewRecord; }
00510
00511 #include "kexirecordnavigator.moc"