kexi

kexidbimagebox.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2005 Cedric Pasteur <cedric.pasteur@free.fr>
3 Copyright (C) 2004-2007 Jaroslaw Staniek <js@iidea.pl>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include "kexidbimagebox.h"
22
23#include <tqapplication.h>
24#include <tqpixmap.h>
25#include <tqstyle.h>
26#include <tqclipboard.h>
27#include <tqtooltip.h>
28#include <tqimage.h>
29#include <tqbuffer.h>
30#include <tqfiledialog.h>
31#include <tqpainter.h>
32
33#include <kdebug.h>
34#include <tdepopupmenu.h>
35#include <tdelocale.h>
36#include <kiconloader.h>
37#include <tdefiledialog.h>
38#include <kimageio.h>
39#include <kstandarddirs.h>
40#include <kstaticdeleter.h>
41#include <kimageeffect.h>
42#include <tdestdaccel.h>
43#include <tdemessagebox.h>
44#include <kguiitem.h>
45
46#include <widget/utils/kexidropdownbutton.h>
47#include <widget/utils/kexicontextmenuutils.h>
48#include <kexiutils/utils.h>
49#include <kexidb/field.h>
50#include <kexidb/utils.h>
51#include <kexidb/queryschema.h>
52#include <formeditor/widgetlibrary.h>
53
54#ifdef TQ_WS_WIN
55#include <win32_utils.h>
56#include <tderecentdirs.h>
57#endif
58
59#include "kexidbutils.h"
60#include "../kexiformpart.h"
61
62static KStaticDeleter<TQPixmap> KexiDBImageBox_pmDeleter;
63static TQPixmap* KexiDBImageBox_pm = 0;
64static KStaticDeleter<TQPixmap> KexiDBImageBox_pmSmallDeleter;
65static TQPixmap* KexiDBImageBox_pmSmall = 0;
66
67KexiDBImageBox::KexiDBImageBox( bool designMode, TQWidget *parent, const char *name )
68 : KexiFrame( parent, name, TQt::WNoAutoErase )
70 , m_alignment(TQt::AlignAuto|TQt::AlignTop)
71 , m_designMode(designMode)
72 , m_readOnly(false)
73 , m_scaledContents(false)
74 , m_keepAspectRatio(true)
75 , m_insideSetData(false)
76 , m_setFocusOnButtonAfterClosingPopup(false)
77 , m_lineWidthChanged(false)
78 , m_paintEventEnabled(true)
79 , m_dropDownButtonVisible(true)
80 , m_insideSetPalette(false)
81{
82 installEventFilter(this);
83 setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Preferred);
84
85 //setup popup menu
86 m_popupMenu = new KexiImageContextMenu(this);
87 m_popupMenu->installEventFilter(this);
88
89 if (m_designMode) {
90 m_chooser = 0;
91 }
92 else {
93 m_chooser = new KexiDropDownButton(this);
94 m_chooser->setFocusPolicy(TQWidget::StrongFocus);
95 m_chooser->setPopup(m_popupMenu);
96 setFocusProxy(m_chooser);
97 m_chooser->installEventFilter(this);
98// m_chooser->setPalette(tqApp->palette());
99// hlyr->addWidget(m_chooser);
100 }
101
102 setBackgroundMode(TQt::NoBackground);
103 setFrameShape(TQFrame::Box);
104 setFrameShadow(TQFrame::Plain);
105 setFrameColor(TQt::black);
106
107 m_paletteBackgroundColorChanged = false; //set this here, not before
108
109 connect(m_popupMenu, TQ_SIGNAL(updateActionsAvailabilityRequested(bool&, bool&)),
110 this, TQ_SLOT(slotUpdateActionsAvailabilityRequested(bool&, bool&)));
111 connect(m_popupMenu, TQ_SIGNAL(insertFromFileRequested(const KURL&)),
112 this, TQ_SLOT(handleInsertFromFileAction(const KURL&)));
113 connect(m_popupMenu, TQ_SIGNAL(saveAsRequested(const TQString&)),
114 this, TQ_SLOT(handleSaveAsAction(const TQString&)));
115 connect(m_popupMenu, TQ_SIGNAL(cutRequested()),
116 this, TQ_SLOT(handleCutAction()));
117 connect(m_popupMenu, TQ_SIGNAL(copyRequested()),
118 this, TQ_SLOT(handleCopyAction()));
119 connect(m_popupMenu, TQ_SIGNAL(pasteRequested()),
120 this, TQ_SLOT(handlePasteAction()));
121 connect(m_popupMenu, TQ_SIGNAL(clearRequested()),
122 this, TQ_SLOT(clear()));
123 connect(m_popupMenu, TQ_SIGNAL(showPropertiesRequested()),
124 this, TQ_SLOT(handleShowPropertiesAction()));
125
126// connect(m_popupMenu, TQ_SIGNAL(aboutToHide()), this, TQ_SLOT(slotAboutToHidePopupMenu()));
127// if (m_chooser) {
128 //we couldn't use m_chooser->setPopup() because of drawing problems
129// connect(m_chooser, TQ_SIGNAL(pressed()), this, TQ_SLOT(slotChooserPressed()));
130// connect(m_chooser, TQ_SIGNAL(released()), this, TQ_SLOT(slotChooserReleased()));
131// connect(m_chooser, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(slotToggled(bool)));
132// }
133
134 setDataSource( TQString() ); //to initialize popup menu and actions availability
135}
136
137KexiDBImageBox::~KexiDBImageBox()
138{
139}
140
141KexiImageContextMenu* KexiDBImageBox::contextMenu() const
142{
143 return m_popupMenu;
144}
145
147{
148 if (dataSource().isEmpty()) {
149 //not db-aware
150 return TQVariant();
151 }
152 //db-aware mode
153 return m_value; //todo
154 //return TQVariant(); //todo
155}
156
157void KexiDBImageBox::setValueInternal( const TQVariant& add, bool removeOld, bool loadPixmap )
158{
159 if (isReadOnly())
160 return;
161 m_popupMenu->hide();
162 if (removeOld)
163 m_value = add.toByteArray();
164 else //do not add "m_origValue" to "add" as this is TQByteArray
165 m_value = m_origValue.toByteArray();
166 bool ok = !m_value.isEmpty();
167 if (ok) {
170 ok = loadPixmap ? m_pixmap.loadFromData(m_value) : true; //, type.latin1());
171 if (!ok) {
173 }
174 }
175 if (!ok) {
176 m_valueMimeType = TQString();
177 m_pixmap = TQPixmap();
178 }
179 repaint();
180}
181
182void KexiDBImageBox::setInvalidState( const TQString& displayText )
183{
184 Q_UNUSED( displayText );
185
186// m_pixmapLabel->setPixmap(TQPixmap());
187 if (!dataSource().isEmpty()) {
188 m_value = TQByteArray();
189 }
190// m_pixmap = TQPixmap();
191// m_originalFileName = TQString();
192
194
195 if (m_chooser)
196 m_chooser->hide();
197 setReadOnly(true);
198}
199
201{
202 return m_value.isEmpty();
203// return !m_pixmapLabel->pixmap() || m_pixmapLabel->pixmap()->isNull();
204}
205
207{
208 return false;
209}
210
212{
213 return m_readOnly;
214}
215
216void KexiDBImageBox::setReadOnly(bool set)
217{
218 m_readOnly = set;
219}
220
221TQPixmap KexiDBImageBox::pixmap() const
222{
223 if (dataSource().isEmpty()) {
224 //not db-aware
225 return m_data.pixmap();
226 }
227 //db-aware mode
228 return m_pixmap;
229}
230
231uint KexiDBImageBox::pixmapId() const
232{
233 if (dataSource().isEmpty()) {// && !m_data.stored()) {
234 //not db-aware
235 return m_data.id();
236 }
237 return 0;
238}
239
240void KexiDBImageBox::setPixmapId(uint id)
241{
242 if (m_insideSetData) //avoid recursion
243 return;
244 setData(KexiBLOBBuffer::self()->objectForId( id, /*unstored*/false ));
245 repaint();
246}
247
248uint KexiDBImageBox::storedPixmapId() const
249{
250 if (dataSource().isEmpty() && m_data.stored()) {
251 //not db-aware
252 return m_data.id();
253 }
254 return 0;
255}
256
257void KexiDBImageBox::setStoredPixmapId(uint id)
258{
259 setData(KexiBLOBBuffer::self()->objectForId( id, /*stored*/true ));
260 repaint();
261}
262
263bool KexiDBImageBox::hasScaledContents() const
264{
265 return m_scaledContents;
266// return m_pixmapLabel->hasScaledContents();
267}
268
269/*void KexiDBImageBox::setPixmap(const TQByteArray& pixmap)
270{
271 setValueInternal(pixmap, true);
272// setBackgroundMode(pixmap.isNull() ? TQt::NoBackground : TQt::PaletteBackground);
273}*/
274
276{
277//todo m_pixmapLabel->setScaledContents(set);
278 m_scaledContents = set;
279 repaint();
280}
281
282void KexiDBImageBox::setKeepAspectRatio(bool set)
283{
284 m_keepAspectRatio = set;
285 if (m_scaledContents)
286 repaint();
287}
288
290{
292// return m_pixmapLabel;
293 return this;
294}
295
297{
298 return true;
299}
300
302{
303 return true;
304}
305
306TQByteArray KexiDBImageBox::data() const
307{
308 if (dataSource().isEmpty()) {
309 //static mode
310 return m_data.data();
311 }
312 else {
313 //db-aware mode
314 return m_value;
315 }
316}
317
319{
320 m_popupMenu->insertFromFile();
321}
322
324{
325 if (!dataSource().isEmpty() && isReadOnly())
326 return;
327
328 if (dataSource().isEmpty()) {
329 //static mode
331 if (!h)
332 return;
333 setData(h);
334 repaint();
335 }
336 else {
337 //db-aware
338 TQString fileName( url.isLocalFile() ? url.path() : url.prettyURL() );
339
341 TQFile f(fileName);
342 if (!f.open(IO_ReadOnly)) {
344 return;
345 }
346 TQByteArray ba = f.readAll();
347 if (f.status()!=IO_Ok) {
349 f.close();
350 return;
351 }
352 m_valueMimeType = KImageIO::mimeType( fileName );
353 setValueInternal( ba, true );
354 }
355
357 if (!dataSource().isEmpty()) {
359 }
360}
361
362void KexiDBImageBox::handleAboutToSaveAsAction(TQString& origFilename, TQString& fileExtension, bool& dataIsEmpty)
363{
364 if (data().isEmpty()) {
365 kdWarning() << "KexiDBImageBox::handleAboutToSaveAs(): no pixmap!" << endl;
366 dataIsEmpty = false;
367 return;
368 }
369 if (dataSource().isEmpty()) { //for static images filename and mimetype can be available
370 origFilename = m_data.originalFileName();
371 if (!origFilename.isEmpty())
372 origFilename = TQString("/") + origFilename;
373 if (!m_data.mimeType().isEmpty())
374 fileExtension = KImageIO::typeForMime(m_data.mimeType()).lower();
375 }
376}
377
378void KexiDBImageBox::handleSaveAsAction(const TQString& fileName)
379{
380 TQFile f(fileName);
381 if (!f.open(IO_WriteOnly)) {
383 return;
384 }
385 f.writeBlock( data() );
386 if (f.status()!=IO_Ok) {
388 f.close();
389 return;
390 }
391 f.close();
392}
393
394void KexiDBImageBox::handleCutAction()
395{
396 if (!dataSource().isEmpty() && isReadOnly())
397 return;
398 handleCopyAction();
399 clear();
400}
401
402void KexiDBImageBox::handleCopyAction()
403{
404 tqApp->clipboard()->setPixmap(pixmap(), TQClipboard::Clipboard);
405}
406
407void KexiDBImageBox::handlePasteAction()
408{
409 if (isReadOnly() || (!m_designMode && !hasFocus()))
410 return;
411 TQPixmap pm( tqApp->clipboard()->pixmap(TQClipboard::Clipboard) );
412// if (!pm.isNull())
413// setValueInternal(pm, true);
414 if (dataSource().isEmpty()) {
415 //static mode
416 setData(KexiBLOBBuffer::self()->insertPixmap( pm ));
417 }
418 else {
419 //db-aware mode
420 m_pixmap = pm;
421 TQByteArray ba;
422 TQBuffer buffer( ba );
423 buffer.open( IO_WriteOnly );
424 if (m_pixmap.save( &buffer, "PNG" )) {// write pixmap into ba in PNG format
425 setValueInternal( ba, true, false/* !loadPixmap */ );
426 }
427 else {
428 setValueInternal( TQByteArray(), true );
429 }
430 }
431
432 repaint();
433 if (!dataSource().isEmpty()) {
434// emit pixmapChanged();
436 }
437}
438
440{
441 if (dataSource().isEmpty()) {
442 //static mode
443 setData(KexiBLOBBuffer::Handle());
444 }
445 else {
446 if (isReadOnly())
447 return;
448 //db-aware mode
449 setValueInternal(TQByteArray(), true);
450 //m_pixmap = TQPixmap();
451 }
452
453// m_originalFileName = TQString();
454
456
457// m_pixmap = TQPixmap(); //will be loaded on demand
458 repaint();
459 if (!dataSource().isEmpty()) {
460// emit pixmapChanged();//valueChanged(data());
462 }
463}
464
469
470void KexiDBImageBox::slotUpdateActionsAvailabilityRequested(bool& valueIsNull, bool& valueIsReadOnly)
471{
472 valueIsNull = !(
473 (dataSource().isEmpty() && !pixmap().isNull()) /*static pixmap available*/
474 || (!dataSource().isEmpty() && !this->valueIsNull()) /*db-aware pixmap available*/
475 );
476 // read-only if static pixmap or db-aware pixmap for read-only widget:
477 valueIsReadOnly = !m_designMode && dataSource().isEmpty() || !dataSource().isEmpty() && isReadOnly()
478 || m_designMode && !dataSource().isEmpty();
479}
480
481/*
482void KexiDBImageBox::slotAboutToHidePopupMenu()
483{
484// kexipluginsdbg << "##### slotAboutToHidePopupMenu() " << endl;
485 m_clickTimer.start(50, true);
486 if (m_chooser && m_chooser->isOn()) {
487 m_chooser->toggle();
488 if (m_setFocusOnButtonAfterClosingPopup) {
489 m_setFocusOnButtonAfterClosingPopup = false;
490 m_chooser->setFocus();
491 }
492 }
493}*/
494
495void KexiDBImageBox::contextMenuEvent( TQContextMenuEvent * e )
496{
497 if (popupMenuAvailable())
498 m_popupMenu->exec( e->globalPos(), -1 );
499}
500
501/*void KexiDBImageBox::slotChooserPressed()
502{
503// if (!m_clickTimer.isActive())
504// return;
505// m_chooser->setDown( false );
506}
507
508void KexiDBImageBox::slotChooserReleased()
509{
510}
511
512void KexiDBImageBox::slotToggled(bool on)
513{
514 return;
515
516// kexipluginsdbg << "##### slotToggled() " << on << endl;
517 if (m_clickTimer.isActive() || !on) {
518 m_chooser->disableMousePress = true;
519 return;
520 }
521 m_chooser->disableMousePress = false;
522 TQRect screen = tqApp->desktop()->availableGeometry( m_chooser );
523 TQPoint p;
524 if ( TQApplication::reverseLayout() ) {
525 if ( (mapToGlobal( m_chooser->rect().bottomLeft() ).y() + m_popupMenu->sizeHint().height()) <= screen.height() )
526 p = m_chooser->mapToGlobal( m_chooser->rect().bottomRight() );
527 else
528 p = m_chooser->mapToGlobal( m_chooser->rect().topRight() - TQPoint( 0, m_popupMenu->sizeHint().height() ) );
529 p.rx() -= m_popupMenu->sizeHint().width();
530 }
531 else {
532 if ( (m_chooser->mapToGlobal( m_chooser->rect().bottomLeft() ).y() + m_popupMenu->sizeHint().height()) <= screen.height() )
533 p = m_chooser->mapToGlobal( m_chooser->rect().bottomLeft() );
534 else
535 p = m_chooser->mapToGlobal( m_chooser->rect().topLeft() - TQPoint( 0, m_popupMenu->sizeHint().height() ) );
536 }
537 if (!m_popupMenu->isVisible() && on) {
538 m_popupMenu->exec( p, -1 );
539 m_popupMenu->setFocus();
540 }
541 //m_chooser->setDown( false );
542}*/
543
545{
546 if (!m_popupMenu)
547 return;
548 if (m_designMode) {
549/* TQString titleString( i18n("Image Box") );
550 if (!dataSource().isEmpty())
551 titleString.prepend(dataSource() + " : ");
552 m_popupMenu->changeTitle(m_popupMenu->idAt(0), m_popupMenu->titlePixmap(m_popupMenu->idAt(0)), titleString);*/
553 }
554 else {
555 //update title in data view mode, based on the data source
556 if (columnInfo()) {
557 KexiImageContextMenu::updateTitle( m_popupMenu, columnInfo()->captionOrAliasOrName(),
558 KexiFormPart::library()->iconName(className()) );
559 }
560 }
561
562 if (m_chooser) {
563 if (popupMenuAvailable() && dataSource().isEmpty()) { //this may work in the future (see @todo below)
564 TQToolTip::add(m_chooser, i18n("Click to show actions for this image box"));
565 } else {
566 TQString beautifiedImageBoxName;
567 if (m_designMode) {
568 beautifiedImageBoxName = dataSource();
569 }
570 else {
571 beautifiedImageBoxName = columnInfo() ? columnInfo()->captionOrAliasOrName() : TQString();
574 beautifiedImageBoxName = beautifiedImageBoxName[0].upper() + beautifiedImageBoxName.mid(1);
575 }
576 TQToolTip::add(m_chooser, i18n("Click to show actions for \"%1\" image box").arg(beautifiedImageBoxName));
577 }
578 }
579}
580
582{
585 //chooser button can be only visible when data source is specified
586 return !dataSource().isEmpty();
587}
588
589void KexiDBImageBox::setDataSource( const TQString &ds )
590{
592 setData(KexiBLOBBuffer::Handle());
594 KexiFrame::setFocusPolicy( focusPolicy() ); //set modified policy
595
596 if (m_chooser) {
597 m_chooser->setEnabled(popupMenuAvailable());
598 if (m_dropDownButtonVisible && popupMenuAvailable()) {
599 m_chooser->show();
600 }
601 else {
602 m_chooser->hide();
603 }
604 }
605
606 // update some properties s not changed by user
608 if (!m_lineWidthChanged) {
609 KexiFrame::setLineWidth( ds.isEmpty() ? 0 : 1 );
610 }
611 if (!m_paletteBackgroundColorChanged && parentWidget()) {
612 KexiFrame::setPaletteBackgroundColor(
613 dataSource().isEmpty() ? parentWidget()->paletteBackgroundColor() : palette().active().base() );
614 }
615}
616
617TQSize KexiDBImageBox::sizeHint() const
618{
619 if (pixmap().isNull())
620 return TQSize(80, 80);
621 return pixmap().size();
622}
623
625{
626 if (frameShape()==TQFrame::Box && (frameShadow()==TQFrame::Sunken || frameShadow()==TQFrame::Raised))
627 return 2 * lineWidth();
628 else
629 return lineWidth();
630}
631
632void KexiDBImageBox::paintEvent( TQPaintEvent *pe )
633{
635 return;
636 TQPainter p(this);
637 p.setClipRect(pe->rect());
638 const int m = realLineWidth() + margin();
639 TQColor bg(eraseColor());
640 if (m_designMode && pixmap().isNull()) {
641 TQPixmap pm(size()-TQSize(m, m));
642 TQPainter p2;
643 p2.begin(&pm, this);
644 p2.fillRect(0,0,width(),height(), bg);
645
646 updatePixmap();
647 TQPixmap *imagBoxPm;
648 const bool tooLarge = (height()-m-m) <= KexiDBImageBox_pm->height();
649 if (tooLarge || (width()-m-m) <= KexiDBImageBox_pm->width())
650 imagBoxPm = KexiDBImageBox_pmSmall;
651 else
652 imagBoxPm = KexiDBImageBox_pm;
653 TQImage img(imagBoxPm->convertToImage());
654 img = KImageEffect::flatten(img, bg.dark(150),
655 tqGray( bg.rgb() ) <= 20 ? TQColor(TQt::gray).dark(150) : bg.light(105));
656
657 TQPixmap converted;
658 converted.convertFromImage(img);
659// if (tooLarge)
660// p2.drawPixmap(2, 2, converted);
661// else
662 p2.drawPixmap(2, height()-m-m-imagBoxPm->height()-2, converted);
663 TQFont f(tqApp->font());
664 p2.setFont(f);
665 p2.setPen( KexiUtils::contrastColor( bg ) );
666 p2.drawText(pm.rect(), TQt::AlignCenter,
667 dataSource().isEmpty()
668 ? TQString::fromLatin1(name())+"\n"+i18n("Unbound Image Box", "(unbound)") //i18n("No Image")
669 : dataSource());
670 p2.end();
671 bitBlt(this, m, m, &pm);
672 }
673 else {
674 TQSize internalSize(size());
675 if (m_chooser && m_dropDownButtonVisible && !dataSource().isEmpty())
676 internalSize.setWidth( internalSize.width() - m_chooser->width() );
677
678 //clearing needed here because we may need to draw a pixmap with transparency
679 p.fillRect(0,0,width(),height(), bg);
680
681 KexiUtils::drawPixmap( p, m, TQRect(TQPoint(0,0), internalSize), pixmap(), m_alignment,
682 m_scaledContents, m_keepAspectRatio );
683 }
684 KexiFrame::drawFrame( &p );
685
686 // if the widget is focused, draw focus indicator rect _if_ there is no chooser button
687 if (!m_designMode && !dataSource().isEmpty() && hasFocus() && (!m_chooser || !m_chooser->isVisible())) {
688 style().drawPrimitive(
689 TQStyle::PE_FocusRect, &p, style().subRect(TQStyle::SR_PushButtonContents, this),
690 palette().active() );
691 }
692}
693
694/* virtual void KexiDBImageBox::paletteChange ( const TQPalette & oldPalette )
695{
696 TQFrame::paletteChange(oldPalette);
697 if (oldPalette.active().background()!=palette().active().background()) {
698 delete KexiDBImageBox_pm;
699 KexiDBImageBox_pm = 0;
700 repaint();
701 }
702}*/
703
704void KexiDBImageBox::updatePixmap()
705{
706 if (! (m_designMode && pixmap().isNull()) )
707 return;
708
709 if (!KexiDBImageBox_pm) {
710 TQString fname( locate("data", TQString("kexi/pics/imagebox.png")) );
711 KexiDBImageBox_pmDeleter.setObject( KexiDBImageBox_pm, new TQPixmap(fname, "PNG") );
712 TQImage img(KexiDBImageBox_pm->convertToImage());
713 KexiDBImageBox_pmSmallDeleter.setObject( KexiDBImageBox_pmSmall,
714 new TQPixmap( img.smoothScale(img.width()/2, img.height()/2, TQImage::ScaleMin) ) );
715 }
716}
717
718void KexiDBImageBox::setAlignment(int alignment)
719{
720 m_alignment = alignment;
721 if (!m_scaledContents || m_keepAspectRatio)
722 repaint();
723}
724
725void KexiDBImageBox::setData(const KexiBLOBBuffer::Handle& handle)
726{
727 if (m_insideSetData) //avoid recursion
728 return;
729 m_insideSetData = true;
730 m_data = handle;
731 emit idChanged(handle.id());
732 m_insideSetData = false;
733 update();
734}
735
736void KexiDBImageBox::resizeEvent( TQResizeEvent * e )
737{
738 KexiFrame::resizeEvent(e);
739 if (m_chooser) {
740 TQSize s( m_chooser->sizeHint() );
741 TQSize margin( realLineWidth(), realLineWidth() );
742 s.setHeight( height() - 2*margin.height() );
743 s = s.boundedTo( size()-2*margin );
744 m_chooser->resize( s );
745 m_chooser->move( TQRect(TQPoint(0,0), e->size() - m_chooser->size() - margin + TQSize(1,1)).bottomRight() );
746 }
747}
748
749/*
750bool KexiDBImageBox::setProperty( const char * name, const TQVariant & value )
751{
752 const bool ret = TQLabel::setProperty(name, value);
753 if (p_shadowEnabled) {
754 if (0==qstrcmp("indent", name) || 0==qstrcmp("font", name) || 0==qstrcmp("margin", name)
755 || 0==qstrcmp("frameShadow", name) || 0==qstrcmp("frameShape", name)
756 || 0==qstrcmp("frameStyle", name) || 0==qstrcmp("midLineWidth", name)
757 || 0==qstrcmp("lineWidth", name)) {
758 p_privateLabel->setProperty(name, value);
759 updatePixmap();
760 }
761 }
762 return ret;
763}
764*/
765
767{
769 //updating strings and title is needed
771}
772
773bool KexiDBImageBox::keyPressed(TQKeyEvent *ke)
774{
775 // Esc key should close the popup
776 if (ke->state() == TQt::NoButton && ke->key() == TQt::Key_Escape) {
777 if (m_popupMenu->isVisible()) {
778 m_setFocusOnButtonAfterClosingPopup = true;
779 return true;
780 }
781 }
782// else if (ke->state() == TQt::ControlButton && TDEStdAccel::shortcut(TDEStdAccel::Copy).keyCodeTQt() == (ke->key()|TQt::CTRL)) {
783// }
784 return false;
785}
786
788{
789 m_lineWidthChanged = true;
790 KexiFrame::setLineWidth(width);
791}
792
793void KexiDBImageBox::setPalette( const TQPalette &pal )
794{
795 KexiFrame::setPalette(pal);
796 if (m_insideSetPalette)
797 return;
798 m_insideSetPalette = true;
799 setPaletteBackgroundColor(pal.active().base());
800 setPaletteForegroundColor(pal.active().foreground());
801 m_insideSetPalette = false;
802}
803
804void KexiDBImageBox::setPaletteBackgroundColor( const TQColor & color )
805{
806 kexipluginsdbg << "KexiDBImageBox::setPaletteBackgroundColor(): " << TQString(color.name()) << endl;
807 m_paletteBackgroundColorChanged = true;
808 KexiFrame::setPaletteBackgroundColor(color);
809 if (m_chooser)
810 m_chooser->setPalette( tqApp->palette() );
811}
812
814{
815 return m_dropDownButtonVisible;
816}
817
819{
821 if (m_dropDownButtonVisible == set)
822 return;
823 m_dropDownButtonVisible = set;
824 if (m_chooser) {
825 if (m_dropDownButtonVisible)
826 m_chooser->show();
827 else
828 m_chooser->hide();
829 }
830}
831
832bool KexiDBImageBox::subwidgetStretchRequired(KexiDBAutoField* autoField) const
833{
834 Q_UNUSED(autoField);
835 return true;
836}
837
838bool KexiDBImageBox::eventFilter( TQObject * watched, TQEvent * e )
839{
840 if (watched==this || watched==m_chooser) { //we're watching chooser as well because it's a focus proxy even if invisible
841 if (e->type()==TQEvent::FocusIn || e->type()==TQEvent::FocusOut || e->type()==TQEvent::MouseButtonPress) {
842 update(); //to repaint focus rect
843 }
844 }
845 // hide popup menu as soon as it loses focus
846 if (watched==m_popupMenu && e->type()==TQEvent::FocusOut) {
847 m_popupMenu->hide();
848 }
849 return KexiFrame::eventFilter(watched, e);
850}
851
852TQWidget::FocusPolicy KexiDBImageBox::focusPolicy() const
853{
854 if (dataSource().isEmpty())
855 return TQWidget::NoFocus;
857}
858
859TQWidget::FocusPolicy KexiDBImageBox::focusPolicyInternal() const
860{
862}
863
864void KexiDBImageBox::setFocusPolicy( TQWidget::FocusPolicy policy )
865{
866 m_focusPolicyInternal = policy;
867 KexiFrame::setFocusPolicy( focusPolicy() ); //set modified policy
868}
869
870#include "kexidbimagebox.moc"
Object handle used by KexiBLOBBuffer.
Handle insertPixmap(const KURL &url)
static KexiBLOBBuffer * self()
Access to KexiBLOBBuffer singleton.
void idChanged(long id)
TQByteArray m_value
for db-aware mode
virtual bool valueIsEmpty()
virtual void setPalette(const TQPalette &pal)
TQWidget::FocusPolicy focusPolicy() const
int realLineWidth() const
TQWidget::FocusPolicy focusPolicyInternal() const
virtual bool isReadOnly() const
virtual bool cursorAtStart()
always true
int lineWidth() const
For overridden property.
virtual bool cursorAtEnd()
always true
TQByteArray data() const
TQString m_valueMimeType
for db-aware mode
virtual TQVariant value()
void updateActionStrings()
Updates i18n'd action strings after datasource change.
virtual void clear()
virtual TQWidget * widget()
void handleInsertFromFileAction(const KURL &url)
virtual bool subwidgetStretchRequired(KexiDBAutoField *autoField) const
Implemented for KexiSubwidgetInterface.
virtual void setInvalidState(const TQString &displayText)
void setDropDownButtonVisible(bool set)
virtual void setColumnInfo(KexiDB::QueryColumnInfo *cinfo)
void handleShowPropertiesAction()
virtual void setDataSource(const TQString &ds)
Sets the datasource to ds.
virtual void setValueInternal(const TQVariant &add, bool removeOld)
Sets value value for a widget.
virtual void setFocusPolicy(TQWidget::FocusPolicy policy)
virtual bool keyPressed(TQKeyEvent *ke)
void insertFromFile()
Forces execution of "insert from file" action.
bool m_paintEventEnabled
used to disable paintEvent()
TQWidget::FocusPolicy m_focusPolicyInternal
Used for focusPolicyInternal().
virtual void setPaletteBackgroundColor(const TQColor &color)
Reimplemented to override behaviour of "paletteBackgroundColor" property.
virtual void setLineWidth(int width)
Reimplemented to override behaviour of "lineWidth" property.
void setScaledContents(bool set)
void handleSaveAsAction(const TQString &fileName)
bool dropDownButtonVisible() const
virtual bool valueIsNull()
Helper class that assigns additional information for the column in a query.
Definition queryschema.h:49
TQString captionOrAliasOrName() const
Definition queryschema.h:65
A button for drop-down "Image" menu.
An interface for declaring form widgets to be data-aware.
virtual KexiDB::QueryColumnInfo * columnInfo() const
virtual void setColumnInfo(KexiDB::QueryColumnInfo *cinfo)
void setDataSource(const TQString &ds)
static KFormDesigner::WidgetLibrary * library()
Frame widget for Kexi forms.
Definition kexiframe.h:27
A context menu used for images within form and table views.
static bool updateTitle(TQPopupMenu *menu, const TQString &title, const TQString &iconName=TQString())
KEXIUTILS_EXPORT void drawPixmap(TQPainter &p, int lineWidth, const TQRect &rect, const TQPixmap &pixmap, int alignment, bool scaledContents, bool keepAspectRatio)
KEXIUTILS_EXPORT TQColor contrastColor(const TQColor &c)