21#include "kexidblabel.h"
25#include <tqdrawutil.h>
26#include <tqapplication.h>
30#include <kimageeffect.h>
32#include <kexidb/field.h>
33#include <kexiutils/utils.h>
35#define SHADOW_OFFSET_X 3
36#define SHADOW_OFFSET_Y 3
37#define SHADOW_FACTOR 16.0
38#define SHADOW_OPACITY 50.0
39#define SHADOW_AXIS_FACTOR 2.0
40#define SHADOW_DIAGONAL_FACTOR 1.0
41#define SHADOW_THICKNESS 1
44class KexiDBInternalLabel :
public TQLabel {
48 virtual ~KexiDBInternalLabel();
53 TQImage makeShadow(
const TQImage& textImage,
const TQColor &bgColor,
const TQRect& boundingRect );
54 TQRect getBounding(
const TQImage &image,
const TQRect& startRect );
56 KPixmap getShadowPixmap();
62KexiDBInternalLabel::KexiDBInternalLabel(
KexiDBLabel* parent )
64 , m_parentLabel(parent)
66 int a = alignment() | TQt::WordBreak;
67 a &= (0xffffff ^ TQt::AlignVertical_Mask);
73void KexiDBInternalLabel::updateFrame()
75 setIndent(m_parentLabel->indent());
76 setMargin(m_parentLabel->margin());
77 setFont(m_parentLabel->font());
79 setFrameShadow(m_parentLabel->frameShadow());
80 setFrameShape(m_parentLabel->frameShape());
81 setFrameStyle(m_parentLabel->frameStyle());
82 setMidLineWidth(m_parentLabel->midLineWidth());
83 setLineWidth(m_parentLabel->lineWidth());
86KexiDBInternalLabel::~KexiDBInternalLabel()
96TQImage KexiDBInternalLabel::makeShadow(
const TQImage& textImage,
97 const TQColor &bgColor,
const TQRect& boundingRect )
100 TQString origText( text() );
103 const int w = textImage.width();
104 const int h = textImage.height();
107 const int bgRed = bgColor.red();
108 const int bgGreen = bgColor.green();
109 const int bgBlue = bgColor.blue();
111 const int startX = boundingRect.x() + SHADOW_THICKNESS;
112 const int startY = boundingRect.y() + SHADOW_THICKNESS;
113 const int effectWidth = boundingRect.bottomRight().x() - SHADOW_THICKNESS;
114 const int effectHeight = boundingRect.bottomRight().y() - SHADOW_THICKNESS;
122 TQImage img = textImage.convertDepth( 32 );
127 if ( ( result.width() != w ) || ( result.height() != h ) ) {
128 result.create( w, h, 32 );
132 double realOpacity = SHADOW_OPACITY + TQMIN(50.0/
double(256.0-tqGray(bgColor.rgb())), 50.0);
135 if (colorGroup().background()==TQt::red)
137 result.fill( (
int)realOpacity );
138 result.setAlphaBuffer(
true );
140 for (
int i = startX; i < effectWidth; i++ ) {
141 for (
int j = startY; j < effectHeight; j++ ) {
148 if ( ( i < 1 ) || ( j < 1 ) || ( i > img.width() - 2 ) || ( j > img.height() - 2 ) )
151 alphaShadow = ( tqGray( img.pixel( i - 1, j - 1 ) ) * SHADOW_DIAGONAL_FACTOR +
152 tqGray( img.pixel( i - 1, j ) ) * SHADOW_AXIS_FACTOR +
153 tqGray( img.pixel( i - 1, j + 1 ) ) * SHADOW_DIAGONAL_FACTOR +
154 tqGray( img.pixel( i , j - 1 ) ) * SHADOW_AXIS_FACTOR +
156 tqGray( img.pixel( i , j + 1 ) ) * SHADOW_AXIS_FACTOR +
157 tqGray( img.pixel( i + 1, j - 1 ) ) * SHADOW_DIAGONAL_FACTOR +
158 tqGray( img.pixel( i + 1, j ) ) * SHADOW_AXIS_FACTOR +
159 tqGray( img.pixel( i + 1, j + 1 ) ) * SHADOW_DIAGONAL_FACTOR ) / SHADOW_FACTOR;
163 result.setPixel( i, j, tqRgba( bgRed, bgGreen , bgBlue,
164 (
int ) (( alphaShadow > realOpacity ) ? realOpacity : alphaShadow)
176KPixmap KexiDBInternalLabel::getShadowPixmap() {
180 const TQColor textColor = colorGroup().foreground();
185 KPixmap finalPixmap, tempPixmap;
186 TQImage shadowImage, tempImage;
189 m_shadowRect = TQRect();
191 tempPixmap.resize( size() );
192 tempPixmap.fill( TQt::black );
193 tempPixmap.setMask( tempPixmap.createHeuristicMask(
true ) );
198 setPaletteForegroundColor( TQt::white );
203 painter.begin( &tempPixmap );
204 painter.setFont( font() );
205 drawContents( &painter );
207 setPaletteForegroundColor( textColor );
213 shadowImage = tempPixmap;
214 tempPixmap.setMask( TQBitmap() );
220 m_shadowRect = getBounding( shadowImage, m_shadowRect );
228 m_shadowRect.setX( TQMAX( m_shadowRect.x() - ( m_shadowRect.width() / 4 ), 0 ) );
229 m_shadowRect.setY( TQMAX( m_shadowRect.y() - ( m_shadowRect.height() / 4 ), 0 ) );
230 m_shadowRect.setBottomRight( TQPoint(
231 TQMIN( m_shadowRect.x() + ( m_shadowRect.width() * 3 / 2 ), shadowImage.width() ),
232 TQMIN( m_shadowRect.y() + ( m_shadowRect.height() * 3 / 2 ), shadowImage.height() ) ) );
234 shadowImage = makeShadow( shadowImage,
235 tqGray( colorGroup().background().rgb() ) < 127 ? TQt::white : TQt::black,
237 if (shadowImage.isNull())
243 m_shadowRect = getBounding( shadowImage, m_shadowRect );
248 finalPixmap.resize( size() );
249 painter.begin( &finalPixmap );
250 painter.fillRect( 0, 0, finalPixmap.width(), finalPixmap.height(),
252 isEnabled() ? TQPalette::Active : TQPalette::Disabled,
253 TQColorGroup::Background ) );
260 tempPixmap.resize( m_shadowRect.size() );
261 if (!finalPixmap.isNull()) {
262 bitBlt( &tempPixmap, 0, 0, &finalPixmap,
263 m_shadowRect.x() + SHADOW_OFFSET_X,
264 m_shadowRect.y() + SHADOW_OFFSET_Y,
265 m_shadowRect.width(),
266 m_shadowRect.height() );
272 finalPixmap = tempPixmap;
281 tempImage = shadowImage.copy( m_shadowRect );
282 tempPixmap.convertFromImage( tempImage );
286 if (!tempPixmap.isNull()) {
287 bitBlt( &finalPixmap, 0, 0, &tempPixmap );
294 m_shadowRect.moveBy( SHADOW_OFFSET_X, SHADOW_OFFSET_Y );
299TQRect KexiDBInternalLabel::getBounding(
const TQImage &image,
const TQRect& startRect ) {
303 const int startX = startRect.x();
304 const int startY = startRect.y();
308 const int width = TQMIN( ( startRect.bottomRight().x() > 0
309 ? startRect.bottomRight().x() : TQCOORD_MAX ),
311 const int height = TQMIN( ( startRect.bottomRight().y() > 0
312 ? startRect.bottomRight().y() : TQCOORD_MAX ),
322 TQRgb trans = image.pixel( 0, 0 );
324 for (
int y = startY; y < height; y++ ) {
325 for (
int x = startX; x < width; x++ ) {
326 if ( image.pixel( x, y ) != trans ) {
334 for (
int x = startX; x < width; x++ ) {
335 for (
int y = startY; y < height; y++ ) {
336 if ( image.pixel( x, y ) != trans ) {
344 for (
int y = height - 1; y > topLeft.y(); y-- ) {
345 for (
int x = width - 1; x > topLeft.x(); x-- ) {
346 if ( image.pixel( x, y ) != trans ) {
347 bottomRight.setY( y + 1 );
354 for (
int x = width - 1; x > topLeft.x(); x-- ) {
355 for (
int y = height - 1; y > topLeft.y(); y-- ) {
356 if ( image.pixel( x, y ) != trans ) {
357 bottomRight.setX( x + 1 );
367 bottomRight.x() - topLeft.x(),
368 bottomRight.y() - topLeft.y() );
374class KexiDBLabel::Private
380 , pixmapDirty( true )
381 , shadowEnabled( false )
382 , resizeEvent( false )
386 KPixmap shadowPixmap;
387 TQPoint shadowPosition;
388 KexiDBInternalLabel* internalLabel;
391 bool pixmapDirty : 1;
392 bool shadowEnabled : 1;
393 bool resizeEvent : 1;
398KexiDBLabel::KexiDBLabel( TQWidget *parent,
const char *name, WFlags f )
399 : TQLabel( parent, name, f )
407KexiDBLabel::KexiDBLabel(
const TQString& text, TQWidget *parent,
const char *name, WFlags f )
408 : TQLabel( parent, name, f )
417KexiDBLabel::~KexiDBLabel()
422void KexiDBLabel::init()
424 m_hasFocusableWidget =
false;
425 d->internalLabel =
new KexiDBInternalLabel(
this );
426 d->internalLabel->hide();
427 d->frameColor = palette().active().foreground();
429 setAlignment( d->internalLabel->alignment() );
432void KexiDBLabel::updatePixmapLater() {
433 if (d->resizeEvent) {
435 d->timer =
new TQTimer(
this,
"KexiDBLabelTimer");
436 connect(d->timer, TQ_SIGNAL(timeout()),
this, TQ_SLOT(
updatePixmap()));
438 d->timer->start(100,
true);
439 d->resizeEvent =
false;
442 if (d->timer && d->timer->isActive())
453 d->internalLabel->setText( text() );
454 d->internalLabel->setFixedSize( size() );
455 d->internalLabel->setPalette( palette() );
456 d->internalLabel->setAlignment( alignment() );
458 KPixmap shadowPixmap = d->internalLabel->getShadowPixmap();
459 if (shadowPixmap.isNull())
461 d->shadowPixmap = shadowPixmap;
462 d->shadowPosition = d->internalLabel->m_shadowRect.topLeft();
463 d->pixmapDirty =
false;
470 if ( d->shadowEnabled ) {
474 if ( d->pixmapDirty ) {
485 if ( !d->pixmapDirty && e->rect().contains( d->shadowPosition ) && !d->shadowPixmap.isNull()) {
486 TQRect clipRect = TQRect(
487 TQMAX( e->rect().x() - d->shadowPosition.x(), 0 ),
488 TQMAX( e->rect().y() - d->shadowPosition.y(), 0 ),
489 TQMIN( e->rect().width() + d->shadowPosition.x(), d->shadowPixmap.width() ),
490 TQMIN( e->rect().height() + d->shadowPosition.y(), d->shadowPixmap.height() ) );
491 p.drawPixmap( d->internalLabel->m_shadowRect.topLeft(), d->shadowPixmap, clipRect );
495 TQLabel::paintEvent( e );
500 setText(add.toString());
502 setText( m_origValue.toString() + add.toString() );
511 setText( displayText );
516 return text().isNull();
521 return text().isEmpty();
556 const bool ret = TQLabel::setProperty(name,
value);
557 if (d->shadowEnabled) {
558 if (0==qstrcmp(
"indent", name) || 0==qstrcmp(
"font", name) || 0==qstrcmp(
"margin", name)
559 || 0==qstrcmp(
"frameShadow", name) || 0==qstrcmp(
"frameShape", name)
560 || 0==qstrcmp(
"frameStyle", name) || 0==qstrcmp(
"midLineWidth", name)
561 || 0==qstrcmp(
"lineWidth", name)) {
562 d->internalLabel->setProperty(name,
value);
576 d->shadowEnabled = state;
577 d->pixmapDirty =
true;
579 d->internalLabel->updateFrame();
583void KexiDBLabel::resizeEvent( TQResizeEvent* e ) {
585 d->resizeEvent =
true;
586 d->pixmapDirty =
true;
587 TQLabel::resizeEvent( e );
590void KexiDBLabel::fontChange(
const TQFont& font ) {
591 d->pixmapDirty =
true;
592 d->internalLabel->setFont( font );
593 TQLabel::fontChange( font );
596void KexiDBLabel::styleChange( TQStyle& style ) {
597 d->pixmapDirty =
true;
598 TQLabel::styleChange( style );
601void KexiDBLabel::enabledChange(
bool enabled ) {
602 d->pixmapDirty =
true;
603 d->internalLabel->setEnabled( enabled );
604 TQLabel::enabledChange( enabled );
607void KexiDBLabel::paletteChange(
const TQPalette& oldPal ) {
609 d->pixmapDirty =
true;
610 d->internalLabel->setPalette( palette() );
623void KexiDBLabel::frameChanged() {
624 d->pixmapDirty =
true;
625 d->internalLabel->updateFrame();
626 TQFrame::frameChanged();
629void KexiDBLabel::showEvent( TQShowEvent* e ) {
630 d->pixmapDirty =
true;
631 TQLabel::showEvent( e );
634void KexiDBLabel::setText(
const TQString& text ) {
635 d->pixmapDirty =
true;
636 TQLabel::setText( text );
642bool KexiDBLabel::shadowEnabled()
const
644 return d->shadowEnabled;
647#define ClassName KexiDBLabel
648#define SuperClassName TQLabel
649#include "kexiframeutils_p.cpp"
650#include "kexidblabel.moc"
An extended, data-aware, read-only text label.
virtual void setInvalidState(const TQString &displayText)
virtual bool isReadOnly() const
always true
virtual void clear()
clears item's data, so the data will contain NULL data
virtual TQWidget * widget()
virtual void setValueInternal(const TQVariant &add, bool removeOld)
Sets value value for a widget.
virtual bool valueIsEmpty()
virtual bool setProperty(const char *name, const TQVariant &value)
used to catch setIndent(), etc.
virtual void setReadOnly(bool readOnly)
empty
virtual bool cursorAtStart()
always false
virtual void setColumnInfo(KexiDB::QueryColumnInfo *cinfo)
virtual TQVariant value()
void setShadowEnabled(bool state)
virtual bool cursorAtEnd()
always false
virtual bool valueIsNull()
virtual void paintEvent(TQPaintEvent *)
An interface providing common text editor's functionality.
void setColumnInfo(KexiDB::QueryColumnInfo *cinfo, TQWidget *w)
Called from KexiFormDataItemInterface::setColumnInfo(KexiDB::QueryColumnInfo* cinfo) implementation.
void paint(TQFrame *w, TQPainter *p, bool textIsEmpty, int alignment, bool hasFocus)
Called from paintEvent( TQPaintEvent *pe ) method of the data aware widget.
Helper class that assigns additional information for the column in a query.
virtual bool valueChanged()