00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kexiblobtableedit.h"
00022
00023 #include <stdlib.h>
00024
00025 #include <qdatastream.h>
00026 #include <qfile.h>
00027 #include <qpopupmenu.h>
00028 #include <qtextedit.h>
00029 #include <qlayout.h>
00030 #include <qstatusbar.h>
00031 #include <qlabel.h>
00032 #include <qpixmap.h>
00033 #include <qimage.h>
00034 #include <qpainter.h>
00035 #include <qtooltip.h>
00036 #include <qapplication.h>
00037 #include <qclipboard.h>
00038 #include <qbuffer.h>
00039
00040 #include <kdebug.h>
00041 #include <ktempfile.h>
00042 #include <kmimetype.h>
00043 #include <kmimemagic.h>
00044 #include <kuserprofile.h>
00045 #include <kservice.h>
00046 #include <kprocess.h>
00047 #include <kopenwith.h>
00048 #include <kurl.h>
00049 #include <karrowbutton.h>
00050 #include <klocale.h>
00051 #include <kfiledialog.h>
00052 #include <kio/job.h>
00053 #include <kglobal.h>
00054 #include <kiconloader.h>
00055 #include <kpopupmenu.h>
00056 #include <kstdaccel.h>
00057
00058 #include <kexiutils/utils.h>
00059 #include <widget/utils/kexidropdownbutton.h>
00060 #include <widget/utils/kexiimagecontextmenu.h>
00061
00063 class KexiBlobTableEdit::Private
00064 {
00065 public:
00066 Private()
00067 : popup(0)
00068 , readOnly(false)
00069 , setValueInternalEnabled(true)
00070 {
00071 }
00072
00073 QByteArray value;
00074 KexiDropDownButton *button;
00075 QSize totalSize;
00076 KexiImageContextMenu *popup;
00077 bool readOnly : 1;
00078 bool setValueInternalEnabled : 1;
00079 };
00080
00081
00082
00083 KexiBlobTableEdit::KexiBlobTableEdit(KexiTableViewColumn &column, QWidget *parent)
00084 : KexiTableEdit(column, parent)
00085 , d ( new Private() )
00086 {
00087 setName("KexiBlobTableEdit");
00088
00089
00090 m_hasFocusableWidget = false;
00091 d->button = new KexiDropDownButton( parentWidget() );
00092 d->button->hide();
00093 QToolTip::add(d->button, i18n("Click to show available actions for this cell"));
00094
00095 d->popup = new KexiImageContextMenu(this);
00096 if (column.columnInfo)
00097 KexiImageContextMenu::updateTitle( d->popup, column.columnInfo->captionOrAliasOrName(),
00099 "pixmaplabel" );
00100 d->button->setPopup( d->popup );
00101
00102
00103
00104
00105 connect(d->popup, SIGNAL(updateActionsAvailabilityRequested(bool&, bool&)),
00106 this, SLOT(slotUpdateActionsAvailabilityRequested(bool&, bool&)));
00107
00108 connect(d->popup, SIGNAL(insertFromFileRequested(const KURL&)),
00109 this, SLOT(handleInsertFromFileAction(const KURL&)));
00110 connect(d->popup, SIGNAL(saveAsRequested(const QString&)),
00111 this, SLOT(handleSaveAsAction(const QString&)));
00112 connect(d->popup, SIGNAL(cutRequested()),
00113 this, SLOT(handleCutAction()));
00114 connect(d->popup, SIGNAL(copyRequested()),
00115 this, SLOT(handleCopyAction()));
00116 connect(d->popup, SIGNAL(pasteRequested()),
00117 this, SLOT(handlePasteAction()));
00118 connect(d->popup, SIGNAL(clearRequested()),
00119 this, SLOT(clear()));
00120 connect(d->popup, SIGNAL(showPropertiesRequested()),
00121 this, SLOT(handleShowPropertiesAction()));
00122 }
00123
00124 KexiBlobTableEdit::~KexiBlobTableEdit()
00125 {
00126 delete d;
00127 #if 0
00128 kdDebug() << "KexiBlobTableEdit: Cleaning up..." << endl;
00129 if (m_tempFile) {
00130 m_tempFile->unlink();
00131
00132 }
00133 delete m_proc;
00134 m_proc = 0;
00135 kdDebug() << "KexiBlobTableEdit: Ready." << endl;
00136 #endif
00137 }
00138
00140 void KexiBlobTableEdit::setValueInternal(const QVariant& add, bool removeOld)
00141 {
00142 if (!d->setValueInternalEnabled)
00143 return;
00144 if (removeOld)
00145 d->value = add.toByteArray();
00146 else
00147 d->value = m_origValue.toByteArray();
00148
00149 #if 0 //todo?
00150 QByteArray val = m_origValue.toByteArray();
00151 kdDebug() << "KexiBlobTableEdit: Size of BLOB: " << val.size() << endl;
00152 m_tempFile = new KTempFile();
00153 m_tempFile->setAutoDelete(true);
00154 kdDebug() << "KexiBlobTableEdit: Creating temporary file: " << m_tempFile->name() << endl;
00155 m_tempFile->dataStream()->writeRawBytes(val.data(), val.size());
00156 m_tempFile->close();
00157 delete m_tempFile;
00158 m_tempFile = 0;
00159
00160 KMimeMagicResult* mmr = KMimeMagic::self()->findFileType(m_tempFile->name());
00161 kdDebug() << "KexiBlobTableEdit: Mimetype = " << mmr->mimeType() << endl;
00162
00163 setViewWidget( new QWidget(this) );
00164 #endif
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 }
00207
00208 bool KexiBlobTableEdit::valueIsNull()
00209 {
00210
00211 d->value.size();
00212 return d->value.isEmpty();
00213 }
00214
00215 bool KexiBlobTableEdit::valueIsEmpty()
00216 {
00217
00218 return d->value.isEmpty();
00219 }
00220
00221 QVariant
00222 KexiBlobTableEdit::value()
00223 {
00224 return d->value;
00225 #if 0
00226
00227
00228
00229 if(m_content && m_content->isModified())
00230 {
00231 return QVariant(m_content->text());
00232 }
00233 QByteArray value;
00234 QFile f( m_tempFile->name() );
00235 f.open(IO_ReadOnly);
00236 QDataStream stream(&f);
00237 char* data = (char*) malloc(f.size());
00238 value.resize(f.size());
00239 stream.readRawBytes(data, f.size());
00240 value.duplicate(data, f.size());
00241 free(data);
00242 kdDebug() << "KexiBlobTableEdit: Size of BLOB: " << value.size() << endl;
00243 return QVariant(value);
00244 #endif
00245 }
00246
00247 void KexiBlobTableEdit::paintFocusBorders( QPainter *p, QVariant &, int x, int y, int w, int h )
00248 {
00249
00250 if (!d->readOnly && w > d->button->width())
00251 w -= d->button->width();
00252 p->drawRect(x, y, w, h);
00253 }
00254
00255 void
00256 KexiBlobTableEdit::setupContents( QPainter *p, bool focused, const QVariant& val,
00257 QString &txt, int &align, int &x, int &y_offset, int &w, int &h )
00258 {
00259 Q_UNUSED(focused);
00260 Q_UNUSED(txt);
00261 Q_UNUSED(align);
00262
00264 QPixmap pixmap;
00265 x = 0;
00266 w -= 1;
00267 h -= 1;
00268 if (p && val.canCast(QVariant::ByteArray) && pixmap.loadFromData(val.toByteArray())) {
00269 KexiUtils::drawPixmap( *p, 0, QRect(x, y_offset, w, h),
00270 pixmap, Qt::AlignCenter, true, true);
00271 }
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 bool KexiBlobTableEdit::cursorAtStart()
00400 {
00401 return true;
00402 }
00403
00404 bool KexiBlobTableEdit::cursorAtEnd()
00405 {
00406 return true;
00407 }
00408
00409 void KexiBlobTableEdit::handleInsertFromFileAction(const KURL& url)
00410 {
00411 if (isReadOnly())
00412 return;
00413
00414 QString fileName( url.isLocalFile() ? url.path() : url.prettyURL() );
00415
00417 QFile f(fileName);
00418 if (!f.open(IO_ReadOnly)) {
00420 return;
00421 }
00422 QByteArray ba = f.readAll();
00423 if (f.status()!=IO_Ok) {
00425 f.close();
00426 return;
00427 }
00428 f.close();
00429
00430 setValueInternal( ba, true );
00431 signalEditRequested();
00432
00433 }
00434
00435 void KexiBlobTableEdit::handleAboutToSaveAsAction(QString& origFilename, QString& fileExtension, bool& dataIsEmpty)
00436 {
00437 Q_UNUSED(origFilename);
00438 Q_UNUSED(fileExtension);
00439 dataIsEmpty = valueIsEmpty();
00441 }
00442
00443 void KexiBlobTableEdit::handleSaveAsAction(const QString& fileName)
00444 {
00445 QFile f(fileName);
00446 if (!f.open(IO_WriteOnly)) {
00448 return;
00449 }
00450 f.writeBlock( d->value );
00451 if (f.status()!=IO_Ok) {
00453 f.close();
00454 return;
00455 }
00456 f.close();
00457 }
00458
00459 void KexiBlobTableEdit::handleCutAction()
00460 {
00461 if (isReadOnly())
00462 return;
00463 handleCopyAction();
00464 clear();
00465 }
00466
00467 void KexiBlobTableEdit::handleCopyAction()
00468 {
00469 executeCopyAction(d->value);
00470 }
00471
00472 void KexiBlobTableEdit::executeCopyAction(const QByteArray& data)
00473 {
00474 QPixmap pixmap;
00475 if (!pixmap.loadFromData(data))
00476 return;
00477 qApp->clipboard()->setPixmap(pixmap, QClipboard::Clipboard);
00478 }
00479
00480 void KexiBlobTableEdit::handlePasteAction()
00481 {
00482 if (isReadOnly())
00483 return;
00484 QPixmap pm( qApp->clipboard()->pixmap(QClipboard::Clipboard) );
00485 QByteArray ba;
00486 QBuffer buffer( ba );
00487 buffer.open( IO_WriteOnly );
00488 if (pm.save( &buffer, "PNG" )) {
00489 setValueInternal( ba, true );
00490 }
00491 else {
00492 setValueInternal( QByteArray(), true );
00493 }
00494 signalEditRequested();
00495
00496 repaintRelatedCell();
00497 }
00498
00499 void KexiBlobTableEdit::clear()
00500 {
00501 setValueInternal( QByteArray(), true );
00502 signalEditRequested();
00503
00504 repaintRelatedCell();
00505 }
00506
00507 void KexiBlobTableEdit::handleShowPropertiesAction()
00508 {
00510 }
00511
00512 void KexiBlobTableEdit::showFocus( const QRect& r, bool readOnly )
00513 {
00514 d->readOnly = readOnly;
00515
00516 updateFocus( r );
00517
00518 if (d->readOnly)
00519 d->button->hide();
00520 else
00521 d->button->show();
00522 }
00523
00524 void KexiBlobTableEdit::resize(int w, int h)
00525 {
00526 d->totalSize = QSize(w,h);
00527 const int addWidth = d->readOnly ? 0 : d->button->width();
00528 QWidget::resize(w - addWidth, h);
00529 if (!d->readOnly)
00530 d->button->resize( h, h );
00531 m_rightMarginWhenFocused = m_rightMargin + addWidth;
00532 QRect r( pos().x(), pos().y(), w+1, h+1 );
00533 r.moveBy(m_scrollView->contentsX(),m_scrollView->contentsY());
00534 updateFocus( r );
00535
00536
00537
00538 }
00539
00540 void KexiBlobTableEdit::updateFocus( const QRect& r )
00541 {
00542 if (!d->readOnly) {
00543 if (d->button->width() > r.width())
00544 moveChild(d->button, r.right() + 1, r.top());
00545 else
00546 moveChild(d->button, r.right() - d->button->width(), r.top() );
00547 }
00548 }
00549
00550 void KexiBlobTableEdit::hideFocus()
00551 {
00552 d->button->hide();
00553 }
00554
00555 QSize KexiBlobTableEdit::totalSize() const
00556 {
00557 return d->totalSize;
00558 }
00559
00560 void KexiBlobTableEdit::slotUpdateActionsAvailabilityRequested(bool& valueIsNull, bool& valueIsReadOnly)
00561 {
00562 emit editRequested();
00563 valueIsNull = this->valueIsNull();
00564 valueIsReadOnly = d->readOnly || isReadOnly();
00565 }
00566
00567 void KexiBlobTableEdit::signalEditRequested()
00568 {
00569 d->setValueInternalEnabled = false;
00570 emit editRequested();
00571 d->setValueInternalEnabled = true;
00572 }
00573
00574 bool KexiBlobTableEdit::handleKeyPress( QKeyEvent* ke, bool editorActive )
00575 {
00576 Q_UNUSED(editorActive);
00577
00578 const int k = ke->key();
00579 KKey kkey(ke);
00580 if (!d->readOnly) {
00581 if ((ke->state()==Qt::NoButton && k==Qt::Key_F4)
00582 || (ke->state()==Qt::AltButton && k==Qt::Key_Down)) {
00583 d->button->animateClick();
00584 QMouseEvent me( QEvent::MouseButtonPress, QPoint(2,2), Qt::LeftButton, Qt::NoButton );
00585 QApplication::sendEvent( d->button, &me );
00586 }
00587 else if ((ke->state()==NoButton && (k==Qt::Key_F2 || k==Qt::Key_Space || k==Qt::Key_Enter || k==Qt::Key_Return))) {
00588 d->popup->insertFromFile();
00589 }
00590 }
00591 else
00592 return false;
00593 return true;
00594 }
00595
00596 bool KexiBlobTableEdit::handleDoubleClick()
00597 {
00598 d->popup->insertFromFile();
00599 return true;
00600 }
00601
00602 void KexiBlobTableEdit::handleCopyAction(const QVariant& value, const QVariant& visibleValue)
00603 {
00604 Q_UNUSED(visibleValue);
00605 executeCopyAction(value.toByteArray());
00606 }
00607
00608 void KexiBlobTableEdit::handleAction(const QString& actionName)
00609 {
00610 if (actionName=="edit_paste") {
00611 d->popup->paste();
00612 }
00613 else if (actionName=="edit_cut") {
00614 emit editRequested();
00615 d->popup->cut();
00616 }
00617 }
00618
00619 KEXI_CELLEDITOR_FACTORY_ITEM_IMPL(KexiBlobEditorFactoryItem, KexiBlobTableEdit)
00620
00621
00622
00623
00624
00625 class KexiKIconTableEdit::Private
00626 {
00627 public:
00628 Private()
00629 : pixmapCache(17, 17, false)
00630 {
00631 }
00633 QVariant currentValue;
00634
00635 QCache<QPixmap> pixmapCache;
00636 };
00637
00638 KexiKIconTableEdit::KexiKIconTableEdit(KexiTableViewColumn &column, QWidget *parent)
00639 : KexiTableEdit(column, parent)
00640 , d( new Private() )
00641 {
00642 setName("KexiKIconTableEdit");
00643 init();
00644 }
00645
00646 KexiKIconTableEdit::~KexiKIconTableEdit()
00647 {
00648 delete d;
00649 }
00650
00651 void KexiKIconTableEdit::init()
00652 {
00653 m_hasFocusableWidget = false;
00654 d->pixmapCache.setAutoDelete(true);
00655 }
00656
00657 void KexiKIconTableEdit::setValueInternal(const QVariant& , bool )
00658 {
00659 d->currentValue = m_origValue;
00660 }
00661
00662 bool KexiKIconTableEdit::valueIsNull()
00663 {
00664 return d->currentValue.isNull();
00665 }
00666
00667 bool KexiKIconTableEdit::valueIsEmpty()
00668 {
00669 return d->currentValue.isNull();
00670 }
00671
00672 QVariant KexiKIconTableEdit::value()
00673 {
00674 return d->currentValue;
00675 }
00676
00677 void KexiKIconTableEdit::clear()
00678 {
00679 d->currentValue = QVariant();
00680 }
00681
00682 bool KexiKIconTableEdit::cursorAtStart()
00683 {
00684 return true;
00685 }
00686
00687 bool KexiKIconTableEdit::cursorAtEnd()
00688 {
00689 return true;
00690 }
00691
00692 void KexiKIconTableEdit::setupContents( QPainter *p, bool , const QVariant& val,
00693 QString &, int &, int &, int &y_offset, int &w, int &h )
00694 {
00695 Q_UNUSED( y_offset );
00696
00697 #if 0
00698 #ifdef Q_WS_WIN
00699 y_offset = -1;
00700 #else
00701 y_offset = 0;
00702 #endif
00703 int s = QMAX(h - 5, 12);
00704 s = QMIN( h-3, s );
00705 s = QMIN( w-3, s );
00706 QRect r( QMAX( w/2 - s/2, 0 ) , h/2 - s/2 , s, s);
00707 p->setPen(QPen(colorGroup().text(), 1));
00708 p->drawRect(r);
00709 if (val.asBool()) {
00710 p->drawLine(r.x(), r.y(), r.right(), r.bottom());
00711 p->drawLine(r.x(), r.bottom(), r.right(), r.y());
00712 }
00713 #endif
00714
00715 QString key = val.toString();
00716 QPixmap *pix = 0;
00717 if (!key.isEmpty() && !(pix = d->pixmapCache[ key ])) {
00718
00719 QPixmap pm = KGlobal::iconLoader()->loadIcon( key, KIcon::Small,
00720 0, KIcon::DefaultState, 0L, true );
00721 if (!pm.isNull()) {
00722 pix = new QPixmap(pm);
00723 d->pixmapCache.insert(key, pix);
00724 }
00725 }
00726
00727 if (p && pix) {
00728 p->drawPixmap( (w-pix->width())/2, (h-pix->height())/2, *pix );
00729 }
00730 }
00731
00732 void KexiKIconTableEdit::handleCopyAction(const QVariant& value, const QVariant& visibleValue)
00733 {
00734 Q_UNUSED(value);
00735 Q_UNUSED(visibleValue);
00736 }
00737
00738 KEXI_CELLEDITOR_FACTORY_ITEM_IMPL(KexiKIconTableEditorFactoryItem, KexiKIconTableEdit)
00739
00740 #include "kexiblobtableedit.moc"