/* This file is part of the KDE project
   Copyright (C) 2005 Cedric Pasteur <cedric.pasteur@free.fr>
   Copyright (C) 2004-2007 Jaroslaw Staniek <js@iidea.pl>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this program; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

#include "kexidbimagebox.h"

#include <tqapplication.h>
#include <tqpixmap.h>
#include <tqstyle.h>
#include <tqclipboard.h>
#include <tqtooltip.h>
#include <tqimage.h>
#include <tqbuffer.h>
#include <tqfiledialog.h>
#include <tqpainter.h>

#include <kdebug.h>
#include <tdepopupmenu.h>
#include <tdelocale.h>
#include <kiconloader.h>
#include <tdefiledialog.h>
#include <kimageio.h>
#include <kstandarddirs.h>
#include <kstaticdeleter.h>
#include <kimageeffect.h>
#include <tdestdaccel.h>
#include <tdemessagebox.h>
#include <kguiitem.h>

#include <widget/utils/kexidropdownbutton.h>
#include <widget/utils/kexicontextmenuutils.h>
#include <kexiutils/utils.h>
#include <kexidb/field.h>
#include <kexidb/utils.h>
#include <kexidb/queryschema.h>
#include <formeditor/widgetlibrary.h>

#ifdef TQ_WS_WIN
#include <win32_utils.h>
#include <tderecentdirs.h>
#endif

#include "kexidbutils.h"
#include "../kexiformpart.h"

static KStaticDeleter<TQPixmap> KexiDBImageBox_pmDeleter;
static TQPixmap* KexiDBImageBox_pm = 0;
static KStaticDeleter<TQPixmap> KexiDBImageBox_pmSmallDeleter;
static TQPixmap* KexiDBImageBox_pmSmall = 0;

KexiDBImageBox::KexiDBImageBox( bool designMode, TQWidget *parent, const char *name )
	: KexiFrame( parent, name, TQt::WNoAutoErase )
	, KexiFormDataItemInterface()
	, m_alignment(TQt::AlignAuto|TQt::AlignTop)
	, m_designMode(designMode)
	, m_readOnly(false)
	, m_scaledContents(false)
	, m_keepAspectRatio(true)
	, m_insideSetData(false)
	, m_setFocusOnButtonAfterClosingPopup(false)
	, m_lineWidthChanged(false)
	, m_paintEventEnabled(true)
	, m_dropDownButtonVisible(true)
	, m_insideSetPalette(false)
{
	installEventFilter(this);
	setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Preferred);

	//setup popup menu
	m_popupMenu = new KexiImageContextMenu(this);
	m_popupMenu->installEventFilter(this);

	if (m_designMode) {
		m_chooser = 0;
	}
	else {
		m_chooser = new KexiDropDownButton(this);
		m_chooser->setFocusPolicy(TQWidget::StrongFocus);
		m_chooser->setPopup(m_popupMenu);
		setFocusProxy(m_chooser);
		m_chooser->installEventFilter(this);
//		m_chooser->setPalette(tqApp->palette());
//		hlyr->addWidget(m_chooser);
	}

	setBackgroundMode(TQt::NoBackground);
	setFrameShape(TQFrame::Box);
	setFrameShadow(TQFrame::Plain);
	setFrameColor(TQt::black);
	
	m_paletteBackgroundColorChanged = false; //set this here, not before

	connect(m_popupMenu, TQ_SIGNAL(updateActionsAvailabilityRequested(bool&, bool&)), 
		this, TQ_SLOT(slotUpdateActionsAvailabilityRequested(bool&, bool&)));
	connect(m_popupMenu, TQ_SIGNAL(insertFromFileRequested(const KURL&)),
		this, TQ_SLOT(handleInsertFromFileAction(const KURL&)));
	connect(m_popupMenu, TQ_SIGNAL(saveAsRequested(const TQString&)),
		this, TQ_SLOT(handleSaveAsAction(const TQString&)));
	connect(m_popupMenu, TQ_SIGNAL(cutRequested()),
		this, TQ_SLOT(handleCutAction()));
	connect(m_popupMenu, TQ_SIGNAL(copyRequested()),
		this, TQ_SLOT(handleCopyAction()));
	connect(m_popupMenu, TQ_SIGNAL(pasteRequested()),
		this, TQ_SLOT(handlePasteAction()));
	connect(m_popupMenu, TQ_SIGNAL(clearRequested()),
		this, TQ_SLOT(clear()));
	connect(m_popupMenu, TQ_SIGNAL(showPropertiesRequested()),
		this, TQ_SLOT(handleShowPropertiesAction()));

//	connect(m_popupMenu, TQ_SIGNAL(aboutToHide()), this, TQ_SLOT(slotAboutToHidePopupMenu()));
//	if (m_chooser) {
		//we couldn't use m_chooser->setPopup() because of drawing problems
//		connect(m_chooser, TQ_SIGNAL(pressed()), this, TQ_SLOT(slotChooserPressed()));
//		connect(m_chooser, TQ_SIGNAL(released()), this, TQ_SLOT(slotChooserReleased()));
//		connect(m_chooser, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(slotToggled(bool)));
//	}

	setDataSource( TQString() ); //to initialize popup menu and actions availability
}

KexiDBImageBox::~KexiDBImageBox()
{
}

KexiImageContextMenu* KexiDBImageBox::contextMenu() const
{
	return m_popupMenu;
}

TQVariant KexiDBImageBox::value()
{
	if (dataSource().isEmpty()) {
		//not db-aware
		return TQVariant();
	}
	//db-aware mode
	return m_value; //todo
	//return TQVariant(); //todo
}

void KexiDBImageBox::setValueInternal( const TQVariant& add, bool removeOld, bool loadPixmap )
{
	if (isReadOnly())
		return;
	m_popupMenu->hide();
	if (removeOld) 
		m_value = add.toByteArray();
	else //do not add "m_origValue" to "add" as this is TQByteArray
		m_value = m_origValue.toByteArray();
	bool ok = !m_value.isEmpty();
	if (ok) {
		///unused (m_valueMimeType is not available unless the px is inserted) TQString type( KImageIO::typeForMime(m_valueMimeType) );
		///ok = KImageIO::canRead( type );
		ok = loadPixmap ? m_pixmap.loadFromData(m_value) : true; //, type.latin1());
		if (!ok) {
			//! @todo inform about error?
		}
	}
	if (!ok) {
		m_valueMimeType = TQString();
		m_pixmap = TQPixmap();
	}
	repaint();
}

void KexiDBImageBox::setInvalidState( const TQString& displayText )
{
	Q_UNUSED( displayText );

//	m_pixmapLabel->setPixmap(TQPixmap());
	if (!dataSource().isEmpty()) {
		m_value = TQByteArray();
	}
//	m_pixmap = TQPixmap();
//	m_originalFileName = TQString();

//! @todo m_pixmapLabel->setText( displayText );

	if (m_chooser)
		m_chooser->hide();
	setReadOnly(true);
}

bool KexiDBImageBox::valueIsNull()
{
	return m_value.isEmpty();
//	return !m_pixmapLabel->pixmap() || m_pixmapLabel->pixmap()->isNull();
}

bool KexiDBImageBox::valueIsEmpty()
{
	return false;
}

bool KexiDBImageBox::isReadOnly() const
{
	return m_readOnly;
}

void KexiDBImageBox::setReadOnly(bool set)
{
	m_readOnly = set;
}

TQPixmap KexiDBImageBox::pixmap() const
{
	if (dataSource().isEmpty()) {
		//not db-aware
		return m_data.pixmap();
	}
	//db-aware mode
	return m_pixmap;
}

uint KexiDBImageBox::pixmapId() const
{
	if (dataSource().isEmpty()) {// && !m_data.stored()) {
		//not db-aware
		return m_data.id();
	}
	return 0;
}

void KexiDBImageBox::setPixmapId(uint id)
{
	if (m_insideSetData) //avoid recursion
		return;
	setData(KexiBLOBBuffer::self()->objectForId( id, /*unstored*/false ));
	repaint();
}

uint KexiDBImageBox::storedPixmapId() const
{
	if (dataSource().isEmpty() && m_data.stored()) {
		//not db-aware
		return m_data.id();
	}
	return 0;
}

void KexiDBImageBox::setStoredPixmapId(uint id)
{
	setData(KexiBLOBBuffer::self()->objectForId( id, /*stored*/true ));
	repaint();
}

bool KexiDBImageBox::hasScaledContents() const
{
	return m_scaledContents;
//	return m_pixmapLabel->hasScaledContents();
}

/*void KexiDBImageBox::setPixmap(const TQByteArray& pixmap)
{
	setValueInternal(pixmap, true);
//	setBackgroundMode(pixmap.isNull() ? TQt::NoBackground : TQt::PaletteBackground);
}*/

void KexiDBImageBox::setScaledContents(bool set)
{
//todo	m_pixmapLabel->setScaledContents(set);
	m_scaledContents = set;
	repaint();
}

void KexiDBImageBox::setKeepAspectRatio(bool set)
{
	m_keepAspectRatio = set;
	if (m_scaledContents)
		repaint();
}

TQWidget* KexiDBImageBox::widget()
{
	//! @todo
//	return m_pixmapLabel;
	return this;
}

bool KexiDBImageBox::cursorAtStart()
{
	return true;
}

bool KexiDBImageBox::cursorAtEnd()
{
	return true;
}

TQByteArray KexiDBImageBox::data() const
{
	if (dataSource().isEmpty()) {
		//static mode
		return m_data.data();
	}
	else {
		//db-aware mode
		return m_value;
	}
}

void KexiDBImageBox::insertFromFile()
{
	m_popupMenu->insertFromFile();
}

void KexiDBImageBox::handleInsertFromFileAction(const KURL& url)
{
	if (!dataSource().isEmpty() && isReadOnly())
		return;

	if (dataSource().isEmpty()) {
		//static mode
		KexiBLOBBuffer::Handle h = KexiBLOBBuffer::self()->insertPixmap( url );
		if (!h)
			return;
		setData(h);
		repaint();
	}
	else {
		//db-aware
		TQString fileName( url.isLocalFile() ? url.path() : url.prettyURL() );

		//! @todo download the file if remote, then set fileName properly
		TQFile f(fileName);
		if (!f.open(IO_ReadOnly)) {
			//! @todo err msg
			return;
		}
		TQByteArray ba = f.readAll();
		if (f.status()!=IO_Ok) {
			//! @todo err msg
			f.close();
			return;
		}
		m_valueMimeType = KImageIO::mimeType( fileName ); 
		setValueInternal( ba, true );
	}

//! @todo emit signal for setting "dirty" flag within the design
	if (!dataSource().isEmpty()) {
		signalValueChanged();
	}
}

void KexiDBImageBox::handleAboutToSaveAsAction(TQString& origFilename, TQString& fileExtension, bool& dataIsEmpty)
{
	if (data().isEmpty()) {
		kdWarning() << "KexiDBImageBox::handleAboutToSaveAs(): no pixmap!" << endl;
		dataIsEmpty = false;
		return;
	}
	if (dataSource().isEmpty()) { //for static images filename and mimetype can be available
		origFilename = m_data.originalFileName();
		if (!origFilename.isEmpty())
			origFilename = TQString("/") + origFilename;
		if (!m_data.mimeType().isEmpty())
			fileExtension = KImageIO::typeForMime(m_data.mimeType()).lower();
	}
}

void KexiDBImageBox::handleSaveAsAction(const TQString& fileName)
{
	TQFile f(fileName);
	if (!f.open(IO_WriteOnly)) {
		//! @todo err msg
		return;
	}
	f.writeBlock( data() );
	if (f.status()!=IO_Ok) {
		//! @todo err msg
		f.close();
		return;
	}
	f.close();
}

void KexiDBImageBox::handleCutAction()
{
	if (!dataSource().isEmpty() && isReadOnly())
		return;
	handleCopyAction();
	clear();
}

void KexiDBImageBox::handleCopyAction()
{
	tqApp->clipboard()->setPixmap(pixmap(), TQClipboard::Clipboard);
}

void KexiDBImageBox::handlePasteAction()
{
	if (isReadOnly() || (!m_designMode && !hasFocus()))
		return;
	TQPixmap pm( tqApp->clipboard()->pixmap(TQClipboard::Clipboard) );
//	if (!pm.isNull())
//		setValueInternal(pm, true);
	if (dataSource().isEmpty()) {
		//static mode
		setData(KexiBLOBBuffer::self()->insertPixmap( pm ));
	}
	else {
		//db-aware mode
		m_pixmap = pm;
	TQByteArray ba;
	TQBuffer buffer( ba );
	buffer.open( IO_WriteOnly );
		if (m_pixmap.save( &buffer, "PNG" )) {// write pixmap into ba in PNG format
			setValueInternal( ba, true, false/* !loadPixmap */ );
		}
		else {
			setValueInternal( TQByteArray(), true );
		}
	}
	
	repaint();
	if (!dataSource().isEmpty()) {
//		emit pixmapChanged();
		signalValueChanged();
	}
}

void KexiDBImageBox::clear()
{
	if (dataSource().isEmpty()) {
		//static mode
		setData(KexiBLOBBuffer::Handle());
	}
	else {
		if (isReadOnly())
			return;
		//db-aware mode
		setValueInternal(TQByteArray(), true);
		//m_pixmap = TQPixmap();
	}

//	m_originalFileName = TQString();

	//! @todo emit signal for setting "dirty" flag within the design

//	m_pixmap = TQPixmap(); //will be loaded on demand
	repaint();
	if (!dataSource().isEmpty()) {
//		emit pixmapChanged();//valueChanged(data());
		signalValueChanged();
	}
}

void KexiDBImageBox::handleShowPropertiesAction()
{
	//! @todo
}

void KexiDBImageBox::slotUpdateActionsAvailabilityRequested(bool& valueIsNull, bool& valueIsReadOnly)
{
	valueIsNull = !(
		   (dataSource().isEmpty() && !pixmap().isNull()) /*static pixmap available*/
		|| (!dataSource().isEmpty() && !this->valueIsNull())  /*db-aware pixmap available*/
	);
	// read-only if static pixmap or db-aware pixmap for read-only widget:
	valueIsReadOnly = !m_designMode && dataSource().isEmpty() || !dataSource().isEmpty() && isReadOnly()
		|| m_designMode && !dataSource().isEmpty();
}

/*
void KexiDBImageBox::slotAboutToHidePopupMenu()
{
//	kexipluginsdbg << "##### slotAboutToHidePopupMenu() " << endl;
	m_clickTimer.start(50, true);
	if (m_chooser && m_chooser->isOn()) {
		m_chooser->toggle();
		if (m_setFocusOnButtonAfterClosingPopup) {
			m_setFocusOnButtonAfterClosingPopup = false;
			m_chooser->setFocus();
		}
	}
}*/

void KexiDBImageBox::contextMenuEvent( TQContextMenuEvent * e )
{
	if (popupMenuAvailable())
		m_popupMenu->exec( e->globalPos(), -1 );
}

/*void KexiDBImageBox::slotChooserPressed()
{
//	if (!m_clickTimer.isActive())
//		return;
//	m_chooser->setDown( false );
}

void KexiDBImageBox::slotChooserReleased()
{
}

void KexiDBImageBox::slotToggled(bool on)
{
	return;

//	kexipluginsdbg << "##### slotToggled() " << on << endl;
	if (m_clickTimer.isActive() || !on) {
		m_chooser->disableMousePress = true;
		return;
	}
	m_chooser->disableMousePress = false;
	TQRect screen = tqApp->desktop()->availableGeometry( m_chooser );
	TQPoint p;
	if ( TQApplication::reverseLayout() ) {
		if ( (mapToGlobal( m_chooser->rect().bottomLeft() ).y() + m_popupMenu->sizeHint().height()) <= screen.height() )
			p = m_chooser->mapToGlobal( m_chooser->rect().bottomRight() );
		else
			p = m_chooser->mapToGlobal( m_chooser->rect().topRight() - TQPoint( 0, m_popupMenu->sizeHint().height() ) );
		p.rx() -= m_popupMenu->sizeHint().width();
	}
	else {
		if ( (m_chooser->mapToGlobal( m_chooser->rect().bottomLeft() ).y() + m_popupMenu->sizeHint().height()) <= screen.height() )
			p = m_chooser->mapToGlobal( m_chooser->rect().bottomLeft() );
		else
			p = m_chooser->mapToGlobal( m_chooser->rect().topLeft() - TQPoint( 0, m_popupMenu->sizeHint().height() ) );
	}
	if (!m_popupMenu->isVisible() && on) {
		m_popupMenu->exec( p, -1 );
		m_popupMenu->setFocus();
	}
	//m_chooser->setDown( false );
}*/

void KexiDBImageBox::updateActionStrings()
{
	if (!m_popupMenu)
		return;
	if (m_designMode) {
/*		TQString titleString( i18n("Image Box") );
		if (!dataSource().isEmpty())
			titleString.prepend(dataSource() + " : ");
		m_popupMenu->changeTitle(m_popupMenu->idAt(0), m_popupMenu->titlePixmap(m_popupMenu->idAt(0)), titleString);*/
	}
	else {
		//update title in data view mode, based on the data source
		if (columnInfo()) {
			KexiImageContextMenu::updateTitle( m_popupMenu, columnInfo()->captionOrAliasOrName(),
				KexiFormPart::library()->iconName(className()) );
		}
	}

	if (m_chooser) {
		if (popupMenuAvailable() && dataSource().isEmpty()) { //this may work in the future (see @todo below)
			TQToolTip::add(m_chooser, i18n("Click to show actions for this image box"));
		} else {
			TQString beautifiedImageBoxName;
			if (m_designMode) {
				beautifiedImageBoxName = dataSource();
			}
			else {
				beautifiedImageBoxName = columnInfo() ? columnInfo()->captionOrAliasOrName() : TQString();
				/*! @todo look at makeFirstCharacterUpperCaseInCaptions setting [bool]
				 (see doc/dev/settings.txt) */
				beautifiedImageBoxName = beautifiedImageBoxName[0].upper() + beautifiedImageBoxName.mid(1);
			}
			TQToolTip::add(m_chooser, i18n("Click to show actions for \"%1\" image box").arg(beautifiedImageBoxName));
		}
	}
}

bool KexiDBImageBox::popupMenuAvailable()
{
/*! @todo add kexi-global setting which anyway, allows to show this button
          (read-only actions like copy/save as/print can be available) */
	//chooser button can be only visible when data source is specified
	return !dataSource().isEmpty();
}

void KexiDBImageBox::setDataSource( const TQString &ds )
{
	KexiFormDataItemInterface::setDataSource( ds );
	setData(KexiBLOBBuffer::Handle());
	updateActionStrings();
	KexiFrame::setFocusPolicy( focusPolicy() ); //set modified policy

	if (m_chooser) {
		m_chooser->setEnabled(popupMenuAvailable());
		if (m_dropDownButtonVisible && popupMenuAvailable()) {
			m_chooser->show();
		}
		else {
			m_chooser->hide();
		}
	}

	// update some properties s not changed by user
//! @todo get default line width from global style settings
	if (!m_lineWidthChanged) {
		KexiFrame::setLineWidth( ds.isEmpty() ? 0 : 1 );
	}
	if (!m_paletteBackgroundColorChanged && parentWidget()) {
		KexiFrame::setPaletteBackgroundColor( 
			dataSource().isEmpty() ? parentWidget()->paletteBackgroundColor() : palette().active().base() );
	}
}

TQSize KexiDBImageBox::sizeHint() const
{
	if (pixmap().isNull())
		return TQSize(80, 80);
	return pixmap().size();
}

int KexiDBImageBox::realLineWidth() const
{
	if (frameShape()==TQFrame::Box && (frameShadow()==TQFrame::Sunken || frameShadow()==TQFrame::Raised))
		return 2 * lineWidth();
	else
		return lineWidth();
}

void KexiDBImageBox::paintEvent( TQPaintEvent *pe )
{
	if (!m_paintEventEnabled)
		return;
	TQPainter p(this);
	p.setClipRect(pe->rect());
	const int m = realLineWidth() + margin();
	TQColor bg(eraseColor());
	if (m_designMode && pixmap().isNull()) {
		TQPixmap pm(size()-TQSize(m, m));
		TQPainter p2;
		p2.begin(&pm, this);
		p2.fillRect(0,0,width(),height(), bg);

		updatePixmap();
		TQPixmap *imagBoxPm;
		const bool tooLarge = (height()-m-m) <= KexiDBImageBox_pm->height();
		if (tooLarge || (width()-m-m) <= KexiDBImageBox_pm->width())
			imagBoxPm = KexiDBImageBox_pmSmall;
		else
			imagBoxPm = KexiDBImageBox_pm;
		TQImage img(imagBoxPm->convertToImage());
		img = KImageEffect::flatten(img, bg.dark(150),
			tqGray( bg.rgb() ) <= 20 ? TQColor(TQt::gray).dark(150) : bg.light(105));

		TQPixmap converted;
		converted.convertFromImage(img);
//		if (tooLarge)
//			p2.drawPixmap(2, 2, converted);
//		else
			p2.drawPixmap(2, height()-m-m-imagBoxPm->height()-2, converted);
		TQFont f(tqApp->font());
		p2.setFont(f);
		p2.setPen( KexiUtils::contrastColor( bg ) );
		p2.drawText(pm.rect(), TQt::AlignCenter,
			dataSource().isEmpty() 
				? TQString::fromLatin1(name())+"\n"+i18n("Unbound Image Box", "(unbound)") //i18n("No Image")
				: dataSource());
		p2.end();
		bitBlt(this, m, m, &pm);
	}
	else {
		TQSize internalSize(size());
		if (m_chooser && m_dropDownButtonVisible && !dataSource().isEmpty())
			internalSize.setWidth( internalSize.width() - m_chooser->width() );
		
		//clearing needed here because we may need to draw a pixmap with transparency
		p.fillRect(0,0,width(),height(), bg);

		KexiUtils::drawPixmap( p, m, TQRect(TQPoint(0,0), internalSize), pixmap(), m_alignment, 
			m_scaledContents, m_keepAspectRatio );
	}
	KexiFrame::drawFrame( &p );

	// if the widget is focused, draw focus indicator rect _if_ there is no chooser button
	if (!m_designMode && !dataSource().isEmpty() && hasFocus() && (!m_chooser || !m_chooser->isVisible())) {
		style().drawPrimitive(
			TQStyle::PE_FocusRect, &p, style().subRect(TQStyle::SR_PushButtonContents, this), 
			palette().active() );
	}
}

/*		virtual void KexiDBImageBox::paletteChange ( const TQPalette & oldPalette )
{
	TQFrame::paletteChange(oldPalette);
	if (oldPalette.active().background()!=palette().active().background()) {
		delete KexiDBImageBox_pm;
		KexiDBImageBox_pm = 0;
		repaint();
	}
}*/

void KexiDBImageBox::updatePixmap()
{
	if (! (m_designMode && pixmap().isNull()) )
		return;

	if (!KexiDBImageBox_pm) {
		TQString fname( locate("data", TQString("kexi/pics/imagebox.png")) );
		KexiDBImageBox_pmDeleter.setObject( KexiDBImageBox_pm, new TQPixmap(fname, "PNG") );
		TQImage img(KexiDBImageBox_pm->convertToImage());
		KexiDBImageBox_pmSmallDeleter.setObject( KexiDBImageBox_pmSmall, 
			new TQPixmap( img.smoothScale(img.width()/2, img.height()/2, TQImage::ScaleMin) ) );
	}
}

void KexiDBImageBox::setAlignment(int alignment)
{
	m_alignment = alignment;
	if (!m_scaledContents || m_keepAspectRatio)
		repaint();
}

void KexiDBImageBox::setData(const KexiBLOBBuffer::Handle& handle)
{
	if (m_insideSetData) //avoid recursion
		return;
	m_insideSetData = true;
	m_data = handle;
	emit idChanged(handle.id());
	m_insideSetData = false;
	update();
}

void KexiDBImageBox::resizeEvent( TQResizeEvent * e )
{
	KexiFrame::resizeEvent(e);
	if (m_chooser) {
		TQSize s( m_chooser->sizeHint() );
		TQSize margin( realLineWidth(), realLineWidth() );
		s.setHeight( height() - 2*margin.height() );
		s = s.boundedTo( size()-2*margin );
		m_chooser->resize( s );
		m_chooser->move( TQRect(TQPoint(0,0), e->size() - m_chooser->size() - margin + TQSize(1,1)).bottomRight() );
	}
}

/*
bool KexiDBImageBox::setProperty( const char * name, const TQVariant & value )
{
	const bool ret = TQLabel::setProperty(name, value);
	if (p_shadowEnabled) {
		if (0==qstrcmp("indent", name) || 0==qstrcmp("font", name) || 0==qstrcmp("margin", name)
			|| 0==qstrcmp("frameShadow", name) || 0==qstrcmp("frameShape", name)
			|| 0==qstrcmp("frameStyle", name) || 0==qstrcmp("midLineWidth", name)
			|| 0==qstrcmp("lineWidth", name)) {
			p_privateLabel->setProperty(name, value);
			updatePixmap();
		}
	}
	return ret;
}
*/

void KexiDBImageBox::setColumnInfo(KexiDB::QueryColumnInfo* cinfo)
{
	KexiFormDataItemInterface::setColumnInfo(cinfo);
	//updating strings and title is needed
	updateActionStrings();
}

bool KexiDBImageBox::keyPressed(TQKeyEvent *ke)
{
	// Esc key should close the popup
	if (ke->state() == TQt::NoButton && ke->key() == TQt::Key_Escape) {
		if (m_popupMenu->isVisible()) {
			m_setFocusOnButtonAfterClosingPopup = true;
			return true;
		}
	}
//	else if (ke->state() == TQt::ControlButton && TDEStdAccel::shortcut(TDEStdAccel::Copy).keyCodeTQt() == (ke->key()|TQt::CTRL)) {
//	}
	return false;
}

void KexiDBImageBox::setLineWidth( int width )
{
	m_lineWidthChanged = true;
	KexiFrame::setLineWidth(width);
}

void KexiDBImageBox::setPalette( const TQPalette &pal )
{
	KexiFrame::setPalette(pal);
	if (m_insideSetPalette)
		return;
	m_insideSetPalette = true;
	setPaletteBackgroundColor(pal.active().base());
	setPaletteForegroundColor(pal.active().foreground());
	m_insideSetPalette = false;
}

void KexiDBImageBox::setPaletteBackgroundColor( const TQColor & color )
{
	kexipluginsdbg << "KexiDBImageBox::setPaletteBackgroundColor(): " << TQString(color.name()) << endl;
	m_paletteBackgroundColorChanged = true;
	KexiFrame::setPaletteBackgroundColor(color);
	if (m_chooser)
		m_chooser->setPalette( tqApp->palette() );
}

bool KexiDBImageBox::dropDownButtonVisible() const
{
	return m_dropDownButtonVisible;
}

void KexiDBImageBox::setDropDownButtonVisible( bool set )
{
//! @todo use global default setting for this property
	if (m_dropDownButtonVisible == set)
		return;
	m_dropDownButtonVisible = set;
	if (m_chooser) {
		if (m_dropDownButtonVisible)
			m_chooser->show();
		else
			m_chooser->hide();
	}
}

bool KexiDBImageBox::subwidgetStretchRequired(KexiDBAutoField* autoField) const
{
	Q_UNUSED(autoField);
	return true;
}

bool KexiDBImageBox::eventFilter( TQObject * watched, TQEvent * e )
{
	if (watched==this || watched==m_chooser) { //we're watching chooser as well because it's a focus proxy even if invisible
		if (e->type()==TQEvent::FocusIn || e->type()==TQEvent::FocusOut || e->type()==TQEvent::MouseButtonPress) {
			update(); //to repaint focus rect
		}
	}
	// hide popup menu as soon as it loses focus
	if (watched==m_popupMenu && e->type()==TQEvent::FocusOut) {
		m_popupMenu->hide();
	}
	return KexiFrame::eventFilter(watched, e);
}

TQWidget::FocusPolicy KexiDBImageBox::focusPolicy() const
{
	if (dataSource().isEmpty())
		return TQWidget::NoFocus;
	return m_focusPolicyInternal;
}

TQWidget::FocusPolicy KexiDBImageBox::focusPolicyInternal() const
{
	return m_focusPolicyInternal;
}

void KexiDBImageBox::setFocusPolicy( TQWidget::FocusPolicy policy )
{
	m_focusPolicyInternal = policy;
	KexiFrame::setFocusPolicy( focusPolicy() ); //set modified policy
}

#include "kexidbimagebox.moc"
