kexi

kexidbimagebox.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Cedric Pasteur <cedric.pasteur@free.fr>
00003    Copyright (C) 2004-2007 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 "kexidbimagebox.h"
00022 
00023 #include <qapplication.h>
00024 #include <qpixmap.h>
00025 #include <qstyle.h>
00026 #include <qclipboard.h>
00027 #include <qtooltip.h>
00028 #include <qimage.h>
00029 #include <qbuffer.h>
00030 #include <qfiledialog.h>
00031 #include <qpainter.h>
00032 
00033 #include <kdebug.h>
00034 #include <kpopupmenu.h>
00035 #include <klocale.h>
00036 #include <kiconloader.h>
00037 #include <kfiledialog.h>
00038 #include <kimageio.h>
00039 #include <kstandarddirs.h>
00040 #include <kstaticdeleter.h>
00041 #include <kimageeffect.h>
00042 #include <kstdaccel.h>
00043 #include <kmessagebox.h>
00044 #include <kguiitem.h>
00045 
00046 #include <widget/utils/kexidropdownbutton.h>
00047 #include <widget/utils/kexicontextmenuutils.h>
00048 #include <kexiutils/utils.h>
00049 #include <kexidb/field.h>
00050 #include <kexidb/utils.h>
00051 #include <kexidb/queryschema.h>
00052 #include <formeditor/widgetlibrary.h>
00053 
00054 #ifdef Q_WS_WIN
00055 #include <win32_utils.h>
00056 #include <krecentdirs.h>
00057 #endif
00058 
00059 #include "kexidbutils.h"
00060 #include "../kexiformpart.h"
00061 
00062 static KStaticDeleter<QPixmap> KexiDBImageBox_pmDeleter;
00063 static QPixmap* KexiDBImageBox_pm = 0;
00064 static KStaticDeleter<QPixmap> KexiDBImageBox_pmSmallDeleter;
00065 static QPixmap* KexiDBImageBox_pmSmall = 0;
00066 
00067 KexiDBImageBox::KexiDBImageBox( bool designMode, QWidget *parent, const char *name )
00068     : KexiFrame( parent, name, Qt::WNoAutoErase )
00069     , KexiFormDataItemInterface()
00070     , m_alignment(Qt::AlignAuto|Qt::AlignTop)
00071     , m_designMode(designMode)
00072     , m_readOnly(false)
00073     , m_scaledContents(false)
00074     , m_keepAspectRatio(true)
00075     , m_insideSetData(false)
00076     , m_setFocusOnButtonAfterClosingPopup(false)
00077     , m_lineWidthChanged(false)
00078     , m_paintEventEnabled(true)
00079     , m_dropDownButtonVisible(true)
00080     , m_insideSetPalette(false)
00081 {
00082     installEventFilter(this);
00083     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
00084 
00085     //setup popup menu
00086     m_popupMenu = new KexiImageContextMenu(this);
00087     m_popupMenu->installEventFilter(this);
00088 
00089     if (m_designMode) {
00090         m_chooser = 0;
00091     }
00092     else {
00093         m_chooser = new KexiDropDownButton(this);
00094         m_chooser->setFocusPolicy(StrongFocus);
00095         m_chooser->setPopup(m_popupMenu);
00096         setFocusProxy(m_chooser);
00097         m_chooser->installEventFilter(this);
00098 //      m_chooser->setPalette(qApp->palette());
00099 //      hlyr->addWidget(m_chooser);
00100     }
00101 
00102     setBackgroundMode(Qt::NoBackground);
00103     setFrameShape(QFrame::Box);
00104     setFrameShadow(QFrame::Plain);
00105     setFrameColor(Qt::black);
00106     
00107     m_paletteBackgroundColorChanged = false; //set this here, not before
00108 
00109     connect(m_popupMenu, SIGNAL(updateActionsAvailabilityRequested(bool&, bool&)), 
00110         this, SLOT(slotUpdateActionsAvailabilityRequested(bool&, bool&)));
00111     connect(m_popupMenu, SIGNAL(insertFromFileRequested(const KURL&)),
00112         this, SLOT(handleInsertFromFileAction(const KURL&)));
00113     connect(m_popupMenu, SIGNAL(saveAsRequested(const QString&)),
00114         this, SLOT(handleSaveAsAction(const QString&)));
00115     connect(m_popupMenu, SIGNAL(cutRequested()),
00116         this, SLOT(handleCutAction()));
00117     connect(m_popupMenu, SIGNAL(copyRequested()),
00118         this, SLOT(handleCopyAction()));
00119     connect(m_popupMenu, SIGNAL(pasteRequested()),
00120         this, SLOT(handlePasteAction()));
00121     connect(m_popupMenu, SIGNAL(clearRequested()),
00122         this, SLOT(clear()));
00123     connect(m_popupMenu, SIGNAL(showPropertiesRequested()),
00124         this, SLOT(handleShowPropertiesAction()));
00125 
00126 //  connect(m_popupMenu, SIGNAL(aboutToHide()), this, SLOT(slotAboutToHidePopupMenu()));
00127 //  if (m_chooser) {
00128         //we couldn't use m_chooser->setPopup() because of drawing problems
00129 //      connect(m_chooser, SIGNAL(pressed()), this, SLOT(slotChooserPressed()));
00130 //      connect(m_chooser, SIGNAL(released()), this, SLOT(slotChooserReleased()));
00131 //      connect(m_chooser, SIGNAL(toggled(bool)), this, SLOT(slotToggled(bool)));
00132 //  }
00133 
00134     setDataSource( QString::null ); //to initialize popup menu and actions availability
00135 }
00136 
00137 KexiDBImageBox::~KexiDBImageBox()
00138 {
00139 }
00140 
00141 KexiImageContextMenu* KexiDBImageBox::contextMenu() const
00142 {
00143     return m_popupMenu;
00144 }
00145 
00146 QVariant KexiDBImageBox::value()
00147 {
00148     if (dataSource().isEmpty()) {
00149         //not db-aware
00150         return QVariant();
00151     }
00152     //db-aware mode
00153     return m_value; //todo
00154     //return QVariant(); //todo
00155 }
00156 
00157 void KexiDBImageBox::setValueInternal( const QVariant& add, bool removeOld, bool loadPixmap )
00158 {
00159     if (isReadOnly())
00160         return;
00161     m_popupMenu->hide();
00162     if (removeOld) 
00163         m_value = add.toByteArray();
00164     else //do not add "m_origValue" to "add" as this is QByteArray
00165         m_value = m_origValue.toByteArray();
00166     bool ok = !m_value.isEmpty();
00167     if (ok) {
00170         ok = loadPixmap ? m_pixmap.loadFromData(m_value) : true; //, type.latin1());
00171         if (!ok) {
00173         }
00174     }
00175     if (!ok) {
00176         m_valueMimeType = QString::null;
00177         m_pixmap = QPixmap();
00178     }
00179     repaint();
00180 }
00181 
00182 void KexiDBImageBox::setInvalidState( const QString& displayText )
00183 {
00184     Q_UNUSED( displayText );
00185 
00186 //  m_pixmapLabel->setPixmap(QPixmap());
00187     if (!dataSource().isEmpty()) {
00188         m_value = QByteArray();
00189     }
00190 //  m_pixmap = QPixmap();
00191 //  m_originalFileName = QString::null;
00192 
00194 
00195     if (m_chooser)
00196         m_chooser->hide();
00197     setReadOnly(true);
00198 }
00199 
00200 bool KexiDBImageBox::valueIsNull()
00201 {
00202     return m_value.isEmpty();
00203 //  return !m_pixmapLabel->pixmap() || m_pixmapLabel->pixmap()->isNull();
00204 }
00205 
00206 bool KexiDBImageBox::valueIsEmpty()
00207 {
00208     return false;
00209 }
00210 
00211 bool KexiDBImageBox::isReadOnly() const
00212 {
00213     return m_readOnly;
00214 }
00215 
00216 void KexiDBImageBox::setReadOnly(bool set)
00217 {
00218     m_readOnly = set;
00219 }
00220 
00221 QPixmap KexiDBImageBox::pixmap() const
00222 {
00223     if (dataSource().isEmpty()) {
00224         //not db-aware
00225         return m_data.pixmap();
00226     }
00227     //db-aware mode
00228     return m_pixmap;
00229 }
00230 
00231 uint KexiDBImageBox::pixmapId() const
00232 {
00233     if (dataSource().isEmpty()) {// && !m_data.stored()) {
00234         //not db-aware
00235         return m_data.id();
00236     }
00237     return 0;
00238 }
00239 
00240 void KexiDBImageBox::setPixmapId(uint id)
00241 {
00242     if (m_insideSetData) //avoid recursion
00243         return;
00244     setData(KexiBLOBBuffer::self()->objectForId( id, /*unstored*/false ));
00245     repaint();
00246 }
00247 
00248 uint KexiDBImageBox::storedPixmapId() const
00249 {
00250     if (dataSource().isEmpty() && m_data.stored()) {
00251         //not db-aware
00252         return m_data.id();
00253     }
00254     return 0;
00255 }
00256 
00257 void KexiDBImageBox::setStoredPixmapId(uint id)
00258 {
00259     setData(KexiBLOBBuffer::self()->objectForId( id, /*stored*/true ));
00260     repaint();
00261 }
00262 
00263 bool KexiDBImageBox::hasScaledContents() const
00264 {
00265     return m_scaledContents;
00266 //  return m_pixmapLabel->hasScaledContents();
00267 }
00268 
00269 /*void KexiDBImageBox::setPixmap(const QByteArray& pixmap)
00270 {
00271     setValueInternal(pixmap, true);
00272 //  setBackgroundMode(pixmap.isNull() ? Qt::NoBackground : Qt::PaletteBackground);
00273 }*/
00274 
00275 void KexiDBImageBox::setScaledContents(bool set)
00276 {
00277 //todo  m_pixmapLabel->setScaledContents(set);
00278     m_scaledContents = set;
00279     repaint();
00280 }
00281 
00282 void KexiDBImageBox::setKeepAspectRatio(bool set)
00283 {
00284     m_keepAspectRatio = set;
00285     if (m_scaledContents)
00286         repaint();
00287 }
00288 
00289 QWidget* KexiDBImageBox::widget()
00290 {
00292 //  return m_pixmapLabel;
00293     return this;
00294 }
00295 
00296 bool KexiDBImageBox::cursorAtStart()
00297 {
00298     return true;
00299 }
00300 
00301 bool KexiDBImageBox::cursorAtEnd()
00302 {
00303     return true;
00304 }
00305 
00306 QByteArray KexiDBImageBox::data() const
00307 {
00308     if (dataSource().isEmpty()) {
00309         //static mode
00310         return m_data.data();
00311     }
00312     else {
00313         //db-aware mode
00314         return m_value;
00315     }
00316 }
00317 
00318 void KexiDBImageBox::insertFromFile()
00319 {
00320     m_popupMenu->insertFromFile();
00321 }
00322 
00323 void KexiDBImageBox::handleInsertFromFileAction(const KURL& url)
00324 {
00325     if (!dataSource().isEmpty() && isReadOnly())
00326         return;
00327 
00328     if (dataSource().isEmpty()) {
00329         //static mode
00330         KexiBLOBBuffer::Handle h = KexiBLOBBuffer::self()->insertPixmap( url );
00331         if (!h)
00332             return;
00333         setData(h);
00334         repaint();
00335     }
00336     else {
00337         //db-aware
00338         QString fileName( url.isLocalFile() ? url.path() : url.prettyURL() );
00339 
00341         QFile f(fileName);
00342         if (!f.open(IO_ReadOnly)) {
00344             return;
00345         }
00346         QByteArray ba = f.readAll();
00347         if (f.status()!=IO_Ok) {
00349             f.close();
00350             return;
00351         }
00352         m_valueMimeType = KImageIO::mimeType( fileName ); 
00353         setValueInternal( ba, true );
00354     }
00355 
00357     if (!dataSource().isEmpty()) {
00358         signalValueChanged();
00359     }
00360 }
00361 
00362 void KexiDBImageBox::handleAboutToSaveAsAction(QString& origFilename, QString& fileExtension, bool& dataIsEmpty)
00363 {
00364     if (data().isEmpty()) {
00365         kdWarning() << "KexiDBImageBox::handleAboutToSaveAs(): no pixmap!" << endl;
00366         dataIsEmpty = false;
00367         return;
00368     }
00369     if (dataSource().isEmpty()) { //for static images filename and mimetype can be available
00370         origFilename = m_data.originalFileName();
00371         if (!origFilename.isEmpty())
00372             origFilename = QString("/") + origFilename;
00373         if (!m_data.mimeType().isEmpty())
00374             fileExtension = KImageIO::typeForMime(m_data.mimeType()).lower();
00375     }
00376 }
00377 
00378 void KexiDBImageBox::handleSaveAsAction(const QString& fileName)
00379 {
00380     QFile f(fileName);
00381     if (!f.open(IO_WriteOnly)) {
00383         return;
00384     }
00385     f.writeBlock( data() );
00386     if (f.status()!=IO_Ok) {
00388         f.close();
00389         return;
00390     }
00391     f.close();
00392 }
00393 
00394 void KexiDBImageBox::handleCutAction()
00395 {
00396     if (!dataSource().isEmpty() && isReadOnly())
00397         return;
00398     handleCopyAction();
00399     clear();
00400 }
00401 
00402 void KexiDBImageBox::handleCopyAction()
00403 {
00404     qApp->clipboard()->setPixmap(pixmap(), QClipboard::Clipboard);
00405 }
00406 
00407 void KexiDBImageBox::handlePasteAction()
00408 {
00409     if (isReadOnly() || (!m_designMode && !hasFocus()))
00410         return;
00411     QPixmap pm( qApp->clipboard()->pixmap(QClipboard::Clipboard) );
00412 //  if (!pm.isNull())
00413 //      setValueInternal(pm, true);
00414     if (dataSource().isEmpty()) {
00415         //static mode
00416         setData(KexiBLOBBuffer::self()->insertPixmap( pm ));
00417     }
00418     else {
00419         //db-aware mode
00420         m_pixmap = pm;
00421     QByteArray ba;
00422     QBuffer buffer( ba );
00423     buffer.open( IO_WriteOnly );
00424         if (m_pixmap.save( &buffer, "PNG" )) {// write pixmap into ba in PNG format
00425             setValueInternal( ba, true, false/* !loadPixmap */ );
00426         }
00427         else {
00428             setValueInternal( QByteArray(), true );
00429         }
00430     }
00431     
00432     repaint();
00433     if (!dataSource().isEmpty()) {
00434 //      emit pixmapChanged();
00435         signalValueChanged();
00436     }
00437 }
00438 
00439 void KexiDBImageBox::clear()
00440 {
00441     if (dataSource().isEmpty()) {
00442         //static mode
00443         setData(KexiBLOBBuffer::Handle());
00444     }
00445     else {
00446         if (isReadOnly())
00447             return;
00448         //db-aware mode
00449         setValueInternal(QByteArray(), true);
00450         //m_pixmap = QPixmap();
00451     }
00452 
00453 //  m_originalFileName = QString::null;
00454 
00456 
00457 //  m_pixmap = QPixmap(); //will be loaded on demand
00458     repaint();
00459     if (!dataSource().isEmpty()) {
00460 //      emit pixmapChanged();//valueChanged(data());
00461         signalValueChanged();
00462     }
00463 }
00464 
00465 void KexiDBImageBox::handleShowPropertiesAction()
00466 {
00468 }
00469 
00470 void KexiDBImageBox::slotUpdateActionsAvailabilityRequested(bool& valueIsNull, bool& valueIsReadOnly)
00471 {
00472     valueIsNull = !(
00473            (dataSource().isEmpty() && !pixmap().isNull()) /*static pixmap available*/
00474         || (!dataSource().isEmpty() && !this->valueIsNull())  /*db-aware pixmap available*/
00475     );
00476     // read-only if static pixmap or db-aware pixmap for read-only widget:
00477     valueIsReadOnly = !m_designMode && dataSource().isEmpty() || !dataSource().isEmpty() && isReadOnly()
00478         || m_designMode && !dataSource().isEmpty();
00479 }
00480 
00481 /*
00482 void KexiDBImageBox::slotAboutToHidePopupMenu()
00483 {
00484 //  kexipluginsdbg << "##### slotAboutToHidePopupMenu() " << endl;
00485     m_clickTimer.start(50, true);
00486     if (m_chooser && m_chooser->isOn()) {
00487         m_chooser->toggle();
00488         if (m_setFocusOnButtonAfterClosingPopup) {
00489             m_setFocusOnButtonAfterClosingPopup = false;
00490             m_chooser->setFocus();
00491         }
00492     }
00493 }*/
00494 
00495 void KexiDBImageBox::contextMenuEvent( QContextMenuEvent * e )
00496 {
00497     if (popupMenuAvailable())
00498         m_popupMenu->exec( e->globalPos(), -1 );
00499 }
00500 
00501 /*void KexiDBImageBox::slotChooserPressed()
00502 {
00503 //  if (!m_clickTimer.isActive())
00504 //      return;
00505 //  m_chooser->setDown( false );
00506 }
00507 
00508 void KexiDBImageBox::slotChooserReleased()
00509 {
00510 }
00511 
00512 void KexiDBImageBox::slotToggled(bool on)
00513 {
00514     return;
00515 
00516 //  kexipluginsdbg << "##### slotToggled() " << on << endl;
00517     if (m_clickTimer.isActive() || !on) {
00518         m_chooser->disableMousePress = true;
00519         return;
00520     }
00521     m_chooser->disableMousePress = false;
00522     QRect screen = qApp->desktop()->availableGeometry( m_chooser );
00523     QPoint p;
00524     if ( QApplication::reverseLayout() ) {
00525         if ( (mapToGlobal( m_chooser->rect().bottomLeft() ).y() + m_popupMenu->sizeHint().height()) <= screen.height() )
00526             p = m_chooser->mapToGlobal( m_chooser->rect().bottomRight() );
00527         else
00528             p = m_chooser->mapToGlobal( m_chooser->rect().topRight() - QPoint( 0, m_popupMenu->sizeHint().height() ) );
00529         p.rx() -= m_popupMenu->sizeHint().width();
00530     }
00531     else {
00532         if ( (m_chooser->mapToGlobal( m_chooser->rect().bottomLeft() ).y() + m_popupMenu->sizeHint().height()) <= screen.height() )
00533             p = m_chooser->mapToGlobal( m_chooser->rect().bottomLeft() );
00534         else
00535             p = m_chooser->mapToGlobal( m_chooser->rect().topLeft() - QPoint( 0, m_popupMenu->sizeHint().height() ) );
00536     }
00537     if (!m_popupMenu->isVisible() && on) {
00538         m_popupMenu->exec( p, -1 );
00539         m_popupMenu->setFocus();
00540     }
00541     //m_chooser->setDown( false );
00542 }*/
00543 
00544 void KexiDBImageBox::updateActionStrings()
00545 {
00546     if (!m_popupMenu)
00547         return;
00548     if (m_designMode) {
00549 /*      QString titleString( i18n("Image Box") );
00550         if (!dataSource().isEmpty())
00551             titleString.prepend(dataSource() + " : ");
00552         m_popupMenu->changeTitle(m_popupMenu->idAt(0), m_popupMenu->titlePixmap(m_popupMenu->idAt(0)), titleString);*/
00553     }
00554     else {
00555         //update title in data view mode, based on the data source
00556         if (columnInfo()) {
00557             KexiImageContextMenu::updateTitle( m_popupMenu, columnInfo()->captionOrAliasOrName(),
00558                 KexiFormPart::library()->iconName(className()) );
00559         }
00560     }
00561 
00562     if (m_chooser) {
00563         if (popupMenuAvailable() && dataSource().isEmpty()) { //this may work in the future (see @todo below)
00564             QToolTip::add(m_chooser, i18n("Click to show actions for this image box"));
00565         } else {
00566             QString beautifiedImageBoxName;
00567             if (m_designMode) {
00568                 beautifiedImageBoxName = dataSource();
00569             }
00570             else {
00571                 beautifiedImageBoxName = columnInfo() ? columnInfo()->captionOrAliasOrName() : QString::null;
00574                 beautifiedImageBoxName = beautifiedImageBoxName[0].upper() + beautifiedImageBoxName.mid(1);
00575             }
00576             QToolTip::add(m_chooser, i18n("Click to show actions for \"%1\" image box").arg(beautifiedImageBoxName));
00577         }
00578     }
00579 }
00580 
00581 bool KexiDBImageBox::popupMenuAvailable()
00582 {
00585     //chooser button can be only visible when data source is specified
00586     return !dataSource().isEmpty();
00587 }
00588 
00589 void KexiDBImageBox::setDataSource( const QString &ds )
00590 {
00591     KexiFormDataItemInterface::setDataSource( ds );
00592     setData(KexiBLOBBuffer::Handle());
00593     updateActionStrings();
00594     KexiFrame::setFocusPolicy( focusPolicy() ); //set modified policy
00595 
00596     if (m_chooser) {
00597         m_chooser->setEnabled(popupMenuAvailable());
00598         if (m_dropDownButtonVisible && popupMenuAvailable()) {
00599             m_chooser->show();
00600         }
00601         else {
00602             m_chooser->hide();
00603         }
00604     }
00605 
00606     // update some properties s not changed by user
00608     if (!m_lineWidthChanged) {
00609         KexiFrame::setLineWidth( ds.isEmpty() ? 0 : 1 );
00610     }
00611     if (!m_paletteBackgroundColorChanged && parentWidget()) {
00612         KexiFrame::setPaletteBackgroundColor( 
00613             dataSource().isEmpty() ? parentWidget()->paletteBackgroundColor() : palette().active().base() );
00614     }
00615 }
00616 
00617 QSize KexiDBImageBox::sizeHint() const
00618 {
00619     if (pixmap().isNull())
00620         return QSize(80, 80);
00621     return pixmap().size();
00622 }
00623 
00624 int KexiDBImageBox::realLineWidth() const
00625 {
00626     if (frameShape()==QFrame::Box && (frameShadow()==QFrame::Sunken || frameShadow()==QFrame::Raised))
00627         return 2 * lineWidth();
00628     else
00629         return lineWidth();
00630 }
00631 
00632 void KexiDBImageBox::paintEvent( QPaintEvent *pe )
00633 {
00634     if (!m_paintEventEnabled)
00635         return;
00636     QPainter p(this);
00637     p.setClipRect(pe->rect());
00638     const int m = realLineWidth() + margin();
00639     QColor bg(eraseColor());
00640     if (m_designMode && pixmap().isNull()) {
00641         QPixmap pm(size()-QSize(m, m));
00642         QPainter p2;
00643         p2.begin(&pm, this);
00644         p2.fillRect(0,0,width(),height(), bg);
00645 
00646         updatePixmap();
00647         QPixmap *imagBoxPm;
00648         const bool tooLarge = (height()-m-m) <= KexiDBImageBox_pm->height();
00649         if (tooLarge || (width()-m-m) <= KexiDBImageBox_pm->width())
00650             imagBoxPm = KexiDBImageBox_pmSmall;
00651         else
00652             imagBoxPm = KexiDBImageBox_pm;
00653         QImage img(imagBoxPm->convertToImage());
00654         img = KImageEffect::flatten(img, bg.dark(150),
00655             qGray( bg.rgb() ) <= 20 ? QColor(Qt::gray).dark(150) : bg.light(105));
00656 
00657         QPixmap converted;
00658         converted.convertFromImage(img);
00659 //      if (tooLarge)
00660 //          p2.drawPixmap(2, 2, converted);
00661 //      else
00662             p2.drawPixmap(2, height()-m-m-imagBoxPm->height()-2, converted);
00663         QFont f(qApp->font());
00664         p2.setFont(f);
00665         p2.setPen( KexiUtils::contrastColor( bg ) );
00666         p2.drawText(pm.rect(), Qt::AlignCenter,
00667             dataSource().isEmpty() 
00668                 ? QString::fromLatin1(name())+"\n"+i18n("Unbound Image Box", "(unbound)") //i18n("No Image")
00669                 : dataSource());
00670         p2.end();
00671         bitBlt(this, m, m, &pm);
00672     }
00673     else {
00674         QSize internalSize(size());
00675         if (m_chooser && m_dropDownButtonVisible && !dataSource().isEmpty())
00676             internalSize.setWidth( internalSize.width() - m_chooser->width() );
00677         
00678         //clearing needed here because we may need to draw a pixmap with transparency
00679         p.fillRect(0,0,width(),height(), bg);
00680 
00681         KexiUtils::drawPixmap( p, m, QRect(QPoint(0,0), internalSize), pixmap(), m_alignment, 
00682             m_scaledContents, m_keepAspectRatio );
00683     }
00684     KexiFrame::drawFrame( &p );
00685 
00686     // if the widget is focused, draw focus indicator rect _if_ there is no chooser button
00687     if (!m_designMode && !dataSource().isEmpty() && hasFocus() && (!m_chooser || !m_chooser->isVisible())) {
00688         style().drawPrimitive(
00689             QStyle::PE_FocusRect, &p, style().subRect(QStyle::SR_PushButtonContents, this), 
00690             palette().active() );
00691     }
00692 }
00693 
00694 /*      virtual void KexiDBImageBox::paletteChange ( const QPalette & oldPalette )
00695 {
00696     QFrame::paletteChange(oldPalette);
00697     if (oldPalette.active().background()!=palette().active().background()) {
00698         delete KexiDBImageBox_pm;
00699         KexiDBImageBox_pm = 0;
00700         repaint();
00701     }
00702 }*/
00703 
00704 void KexiDBImageBox::updatePixmap()
00705 {
00706     if (! (m_designMode && pixmap().isNull()) )
00707         return;
00708 
00709     if (!KexiDBImageBox_pm) {
00710         QString fname( locate("data", QString("kexi/pics/imagebox.png")) );
00711         KexiDBImageBox_pmDeleter.setObject( KexiDBImageBox_pm, new QPixmap(fname, "PNG") );
00712         QImage img(KexiDBImageBox_pm->convertToImage());
00713         KexiDBImageBox_pmSmallDeleter.setObject( KexiDBImageBox_pmSmall, 
00714             new QPixmap( img.smoothScale(img.width()/2, img.height()/2, QImage::ScaleMin) ) );
00715     }
00716 }
00717 
00718 void KexiDBImageBox::setAlignment(int alignment)
00719 {
00720     m_alignment = alignment;
00721     if (!m_scaledContents || m_keepAspectRatio)
00722         repaint();
00723 }
00724 
00725 void KexiDBImageBox::setData(const KexiBLOBBuffer::Handle& handle)
00726 {
00727     if (m_insideSetData) //avoid recursion
00728         return;
00729     m_insideSetData = true;
00730     m_data = handle;
00731     emit idChanged(handle.id());
00732     m_insideSetData = false;
00733     update();
00734 }
00735 
00736 void KexiDBImageBox::resizeEvent( QResizeEvent * e )
00737 {
00738     KexiFrame::resizeEvent(e);
00739     if (m_chooser) {
00740         QSize s( m_chooser->sizeHint() );
00741         QSize margin( realLineWidth(), realLineWidth() );
00742         s.setHeight( height() - 2*margin.height() );
00743         s = s.boundedTo( size()-2*margin );
00744         m_chooser->resize( s );
00745         m_chooser->move( QRect(QPoint(0,0), e->size() - m_chooser->size() - margin + QSize(1,1)).bottomRight() );
00746     }
00747 }
00748 
00749 /*
00750 bool KexiDBImageBox::setProperty( const char * name, const QVariant & value )
00751 {
00752     const bool ret = QLabel::setProperty(name, value);
00753     if (p_shadowEnabled) {
00754         if (0==qstrcmp("indent", name) || 0==qstrcmp("font", name) || 0==qstrcmp("margin", name)
00755             || 0==qstrcmp("frameShadow", name) || 0==qstrcmp("frameShape", name)
00756             || 0==qstrcmp("frameStyle", name) || 0==qstrcmp("midLineWidth", name)
00757             || 0==qstrcmp("lineWidth", name)) {
00758             p_privateLabel->setProperty(name, value);
00759             updatePixmap();
00760         }
00761     }
00762     return ret;
00763 }
00764 */
00765 
00766 void KexiDBImageBox::setColumnInfo(KexiDB::QueryColumnInfo* cinfo)
00767 {
00768     KexiFormDataItemInterface::setColumnInfo(cinfo);
00769     //updating strings and title is needed
00770     updateActionStrings();
00771 }
00772 
00773 bool KexiDBImageBox::keyPressed(QKeyEvent *ke)
00774 {
00775     // Esc key should close the popup
00776     if (ke->state() == Qt::NoButton && ke->key() == Qt::Key_Escape) {
00777         if (m_popupMenu->isVisible()) {
00778             m_setFocusOnButtonAfterClosingPopup = true;
00779             return true;
00780         }
00781     }
00782 //  else if (ke->state() == Qt::ControlButton && KStdAccel::shortcut(KStdAccel::Copy).keyCodeQt() == (ke->key()|Qt::CTRL)) {
00783 //  }
00784     return false;
00785 }
00786 
00787 void KexiDBImageBox::setLineWidth( int width )
00788 {
00789     m_lineWidthChanged = true;
00790     KexiFrame::setLineWidth(width);
00791 }
00792 
00793 void KexiDBImageBox::setPalette( const QPalette &pal )
00794 {
00795     KexiFrame::setPalette(pal);
00796     if (m_insideSetPalette)
00797         return;
00798     m_insideSetPalette = true;
00799     setPaletteBackgroundColor(pal.active().base());
00800     setPaletteForegroundColor(pal.active().foreground());
00801     m_insideSetPalette = false;
00802 }
00803 
00804 void KexiDBImageBox::setPaletteBackgroundColor( const QColor & color )
00805 {
00806     kexipluginsdbg << "KexiDBImageBox::setPaletteBackgroundColor(): " << color.name() << endl;
00807     m_paletteBackgroundColorChanged = true;
00808     KexiFrame::setPaletteBackgroundColor(color);
00809     if (m_chooser)
00810         m_chooser->setPalette( qApp->palette() );
00811 }
00812 
00813 bool KexiDBImageBox::dropDownButtonVisible() const
00814 {
00815     return m_dropDownButtonVisible;
00816 }
00817 
00818 void KexiDBImageBox::setDropDownButtonVisible( bool set )
00819 {
00821     if (m_dropDownButtonVisible == set)
00822         return;
00823     m_dropDownButtonVisible = set;
00824     if (m_chooser) {
00825         if (m_dropDownButtonVisible)
00826             m_chooser->show();
00827         else
00828             m_chooser->hide();
00829     }
00830 }
00831 
00832 bool KexiDBImageBox::subwidgetStretchRequired(KexiDBAutoField* autoField) const
00833 {
00834     Q_UNUSED(autoField);
00835     return true;
00836 }
00837 
00838 bool KexiDBImageBox::eventFilter( QObject * watched, QEvent * e )
00839 {
00840     if (watched==this || watched==m_chooser) { //we're watching chooser as well because it's a focus proxy even if invisible
00841         if (e->type()==QEvent::FocusIn || e->type()==QEvent::FocusOut || e->type()==QEvent::MouseButtonPress) {
00842             update(); //to repaint focus rect
00843         }
00844     }
00845     // hide popup menu as soon as it loses focus
00846     if (watched==m_popupMenu && e->type()==QEvent::FocusOut) {
00847         m_popupMenu->hide();
00848     }
00849     return KexiFrame::eventFilter(watched, e);
00850 }
00851 
00852 QWidget::FocusPolicy KexiDBImageBox::focusPolicy() const
00853 {
00854     if (dataSource().isEmpty())
00855         return NoFocus;
00856     return m_focusPolicyInternal;
00857 }
00858 
00859 QWidget::FocusPolicy KexiDBImageBox::focusPolicyInternal() const
00860 {
00861     return m_focusPolicyInternal;
00862 }
00863 
00864 void KexiDBImageBox::setFocusPolicy( FocusPolicy policy )
00865 {
00866     m_focusPolicyInternal = policy;
00867     KexiFrame::setFocusPolicy( focusPolicy() ); //set modified policy
00868 }
00869 
00870 #include "kexidbimagebox.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys