You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tqt3/src/dialogs/qcolordialog.cpp

1674 lines
41 KiB

/****************************************************************************
**
** Implementation of TQColorDialog class
**
** Created : 990222
**
** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved.
**
** This file is part of the dialogs module of the TQt GUI Toolkit.
**
** This file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the files LICENSE.GPL2
** and LICENSE.GPL3 included in the packaging of this file.
** Alternatively you may (at your option) use any later version
** of the GNU General Public License if such license has been
** publicly approved by Trolltech ASA (or its successors, if any)
** and the KDE Free TQt Foundation.
**
** Please review the following information to ensure GNU General
** Public Licensing retquirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** This file may be used under the terms of the Q Public License as
** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
** included in the packaging of this file. Licensees holding valid TQt
** Commercial licenses may use this file in accordance with the TQt
** Commercial License Agreement provided with the Software.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
** herein.
**
**********************************************************************/
#include "qcolordialog.h"
#ifndef QT_NO_COLORDIALOG
#include "qpainter.h"
#include "qlayout.h"
#include "qlabel.h"
#include "qpushbutton.h"
#include "qlineedit.h"
#include "qimage.h"
#include "qpixmap.h"
#include "qdrawutil.h"
#include "qvalidator.h"
#include "qdragobject.h"
#include "qgridview.h"
#include "qapplication.h"
#include "qstyle.h"
#include "qsettings.h"
#include "qpopupmenu.h"
#ifdef Q_WS_MAC
TQRgb macGetRgba( TQRgb initial, bool *ok, TQWidget *parent, const char* name );
TQColor macGetColor( const TQColor& initial, TQWidget *parent, const char *name );
#endif
#ifdef Q_WS_X11
#include "private/qtkdeintegration_x11_p.h"
#endif
//////////// TQWellArray BEGIN
struct TQWellArrayData;
class TQWellArray : public TQGridView
{
Q_OBJECT
Q_PROPERTY( int selectedColumn READ selectedColumn )
Q_PROPERTY( int selectedRow READ selectedRow )
public:
TQWellArray( TQWidget* parent=0, const char* name=0, bool popup = FALSE );
~TQWellArray() {}
TQString cellContent( int row, int col ) const;
// ### Paul !!! virtual void setCellContent( int row, int col, const TQString &);
int selectedColumn() const { return selCol; }
int selectedRow() const { return selRow; }
virtual void setCurrent( int row, int col );
virtual void setSelected( int row, int col );
TQSize sizeHint() const;
virtual void setCellBrush( int row, int col, const TQBrush & );
TQBrush cellBrush( int row, int col );
signals:
void selected( int row, int col );
protected:
void dimensionChange( int oldRows, int oldCols );
virtual void paintCell( TQPainter *, int row, int col );
virtual void paintCellContents( TQPainter *, int row, int col, const TQRect& );
void mousePressEvent( TQMouseEvent* );
void mouseReleaseEvent( TQMouseEvent* );
void mouseMoveEvent( TQMouseEvent* );
void keyPressEvent( TQKeyEvent* );
void focusInEvent( TQFocusEvent* );
void focusOutEvent( TQFocusEvent* );
private:
int curRow;
int curCol;
int selRow;
int selCol;
bool smallStyle;
TQWellArrayData *d;
private: // Disabled copy constructor and operator=
#if defined(Q_DISABLE_COPY)
TQWellArray( const TQWellArray & );
TQWellArray& operator=( const TQWellArray & );
#endif
};
// non-interface ...
struct TQWellArrayData {
TQBrush *brush;
};
/*!
\internal
\class TQWellArray qwellarray_p.h
\brief The TQWellArray class provides a well array.
\ingroup advanced
*/
TQWellArray::TQWellArray( TQWidget *parent, const char * name, bool popup )
: TQGridView( parent, name,
(popup ? (WStyle_Customize|WStyle_Tool|WStyle_NoBorder) : 0 ) )
{
d = 0;
setFocusPolicy( StrongFocus );
setVScrollBarMode(AlwaysOff);
setHScrollBarMode(AlwaysOff);
viewport()->setBackgroundMode( PaletteBackground );
setNumCols( 7 );
setNumRows( 7 );
setCellWidth( 24 );
setCellHeight( 21 );
smallStyle = popup;
if ( popup ) {
setCellWidth( 18 );
setCellHeight( 18 );
setFrameStyle(TQFrame::StyledPanel | TQFrame::Raised);
setMargin( 1 );
setLineWidth( 2 );
} else {
setFrameStyle( TQFrame::NoFrame );
}
curCol = 0;
curRow = 0;
selCol = -1;
selRow = -1;
if ( smallStyle )
setMouseTracking( TRUE );
}
TQSize TQWellArray::sizeHint() const
{
constPolish();
TQSize s = gridSize().boundedTo( TQSize(640, 480 ) );
return TQSize( s.width() + 2*frameWidth(), s.height() + 2*frameWidth() );
}
void TQWellArray::paintCell( TQPainter* p, int row, int col )
{
int w = cellWidth(); // width of cell in pixels
int h = cellHeight(); // height of cell in pixels
int b = 1;
if ( !smallStyle )
b = 3;
const TQColorGroup & g = colorGroup();
p->setPen( TQPen( black, 0, SolidLine ) );
if ( !smallStyle && row ==selRow && col == selCol &&
style().styleHint(TQStyle::SH_GUIStyle) != MotifStyle) {
int n = 2;
p->drawRect( n, n, w-2*n, h-2*n );
}
style().drawPrimitive(TQStyle::PE_Panel, p, TQRect(b, b, w-2*b, h-2*b), g,
TQStyle::Style_Enabled | TQStyle::Style_Sunken);
int t = 0;
if (style().styleHint(TQStyle::SH_GUIStyle) == MotifStyle)
t = ( row == selRow && col == selCol ) ? 2 : 0;
b += 2 + t;
if ( (row == curRow) && (col == curCol) ) {
if ( smallStyle ) {
p->setPen ( white );
p->drawRect( 1, 1, w-2, h-2 );
p->setPen ( black );
p->drawRect( 0, 0, w, h );
p->drawRect( 2, 2, w-4, h-4 );
b = 3;
} else if ( hasFocus() ) {
style().drawPrimitive(TQStyle::PE_FocusRect, p, TQRect(0, 0, w, h), g);
}
}
paintCellContents( p, row, col, TQRect(b, b, w - 2*b, h - 2*b) );
}
/*!
Reimplement this function to change the contents of the well array.
*/
void TQWellArray::paintCellContents( TQPainter *p, int row, int col, const TQRect &r )
{
if ( d ) {
p->fillRect( r, d->brush[row*numCols()+col] );
} else {
p->fillRect( r, white );
p->setPen( black );
p->drawLine( r.topLeft(), r.bottomRight() );
p->drawLine( r.topRight(), r.bottomLeft() );
}
}
/*\reimp
*/
void TQWellArray::mousePressEvent( TQMouseEvent* e )
{
// The current cell marker is set to the cell the mouse is pressed
// in.
TQPoint pos = e->pos();
setCurrent( rowAt( pos.y() ), columnAt( pos.x() ) );
}
/*\reimp
*/
void TQWellArray::mouseReleaseEvent( TQMouseEvent* )
{
// The current cell marker is set to the cell the mouse is clicked
// in.
setSelected( curRow, curCol );
}
/*\reimp
*/
void TQWellArray::mouseMoveEvent( TQMouseEvent* e )
{
// The current cell marker is set to the cell the mouse is
// clicked in.
if ( smallStyle ) {
TQPoint pos = e->pos();
setCurrent( rowAt( pos.y() ), columnAt( pos.x() ) );
}
}
/*
Sets the cell currently having the focus. This is not necessarily
the same as the currently selected cell.
*/
void TQWellArray::setCurrent( int row, int col )
{
if ( (curRow == row) && (curCol == col) )
return;
if ( row < 0 || col < 0 )
row = col = -1;
int oldRow = curRow;
int oldCol = curCol;
curRow = row;
curCol = col;
updateCell( oldRow, oldCol );
updateCell( curRow, curCol );
}
/*!
Sets the currently selected cell to \a row, \a col. If \a row or \a
col are less than zero, the current cell is unselected.
Does not set the position of the focus indicator.
*/
void TQWellArray::setSelected( int row, int col )
{
if ( (selRow == row) && (selCol == col) )
return;
int oldRow = selRow;
int oldCol = selCol;
if ( row < 0 || col < 0 )
row = col = -1;
selCol = col;
selRow = row;
updateCell( oldRow, oldCol );
updateCell( selRow, selCol );
if ( row >= 0 )
emit selected( row, col );
if ( isVisible() && ::qt_cast<TQPopupMenu*>(parentWidget()) )
parentWidget()->close();
}
/*!\reimp
*/
void TQWellArray::focusInEvent( TQFocusEvent* )
{
updateCell( curRow, curCol );
}
/*!
Sets the size of the well array to be \a rows cells by \a cols.
Resets any brush information set by setCellBrush().
*/
void TQWellArray::dimensionChange( int, int )
{
if ( d ) {
if ( d->brush )
delete[] d->brush;
delete d;
d = 0;
}
}
void TQWellArray::setCellBrush( int row, int col, const TQBrush &b )
{
if ( !d ) {
d = new TQWellArrayData;
int i = numRows()*numCols();
d->brush = new TQBrush[i];
}
if ( row >= 0 && row < numRows() && col >= 0 && col < numCols() )
d->brush[row*numCols()+col] = b;
#ifdef QT_CHECK_RANGE
else
qWarning( "TQWellArray::setCellBrush( %d, %d ) out of range", row, col );
#endif
}
/*!
Returns the brush set for the cell at \a row, \a col. If no brush is set,
\c NoBrush is returned.
*/
TQBrush TQWellArray::cellBrush( int row, int col )
{
if ( d && row >= 0 && row < numRows() && col >= 0 && col < numCols() )
return d->brush[row*numCols()+col];
return NoBrush;
}
/*!\reimp
*/
void TQWellArray::focusOutEvent( TQFocusEvent* )
{
updateCell( curRow, curCol );
}
/*\reimp
*/
void TQWellArray::keyPressEvent( TQKeyEvent* e )
{
switch( e->key() ) { // Look at the key code
case Key_Left: // If 'left arrow'-key,
if( curCol > 0 ) // and cr't not in leftmost col
setCurrent( curRow, curCol - 1); // set cr't to next left column
break;
case Key_Right: // Correspondingly...
if( curCol < numCols()-1 )
setCurrent( curRow, curCol + 1);
break;
case Key_Up:
if( curRow > 0 )
setCurrent( curRow - 1, curCol);
else if ( smallStyle )
focusNextPrevChild( FALSE );
break;
case Key_Down:
if( curRow < numRows()-1 )
setCurrent( curRow + 1, curCol);
else if ( smallStyle )
focusNextPrevChild( TRUE );
break;
case Key_Space:
case Key_Return:
case Key_Enter:
setSelected( curRow, curCol );
break;
default: // If not an interesting key,
e->ignore(); // we don't accept the event
return;
}
}
//////////// TQWellArray END
static bool initrgb = FALSE;
static TQRgb stdrgb[6*8];
static TQRgb cusrgb[2*8];
static bool customSet = FALSE;
static void initRGB()
{
if ( initrgb )
return;
initrgb = TRUE;
int i = 0;
for ( int g = 0; g < 4; g++ )
for ( int r = 0; r < 4; r++ )
for ( int b = 0; b < 3; b++ )
stdrgb[i++] = qRgb( r*255/3, g*255/3, b*255/2 );
for ( i = 0; i < 2*8; i++ )
cusrgb[i] = qRgb(0xff,0xff,0xff);
}
/*!
Returns the number of custom colors supported by TQColorDialog. All
color dialogs share the same custom colors.
*/
int TQColorDialog::customCount()
{
return 2*8;
}
/*!
Returns custom color number \a i as a TQRgb.
*/
TQRgb TQColorDialog::customColor( int i )
{
initRGB();
if ( i < 0 || i >= customCount() ) {
#ifdef QT_CHECK_RANGE
qWarning( "TQColorDialog::customColor() index %d out of range", i );
#endif
i = 0;
}
return cusrgb[i];
}
/*!
Sets custom color number \a i to the TQRgb value \a c.
*/
void TQColorDialog::setCustomColor( int i, TQRgb c )
{
initRGB();
if ( i < 0 || i >= customCount() ) {
#ifdef QT_CHECK_RANGE
qWarning( "TQColorDialog::setCustomColor() index %d out of range", i );
#endif
return;
}
customSet = TRUE;
cusrgb[i] = c;
}
/*!
Sets standard color number \a i to the TQRgb value \a c.
*/
void TQColorDialog::setStandardColor( int i, TQRgb c )
{
initRGB();
if ( i < 0 || i >= 6*8 ) {
#ifdef QT_CHECK_RANGE
qWarning( "TQColorDialog::setStandardColor() index %d out of range", i );
#endif
return;
}
stdrgb[i] = c;
}
static inline void rgb2hsv( TQRgb rgb, int&h, int&s, int&v )
{
TQColor c;
c.setRgb( rgb );
c.getHsv(h,s,v);
}
class TQColorWell : public TQWellArray
{
public:
TQColorWell( TQWidget *parent, int r, int c, TQRgb *vals )
:TQWellArray( parent, "" ), values( vals ), mousePressed( FALSE ), oldCurrent( -1, -1 )
{ setNumRows(r), setNumCols(c); setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum) ); }
protected:
void paintCellContents( TQPainter *, int row, int col, const TQRect& );
void mousePressEvent( TQMouseEvent *e );
void mouseMoveEvent( TQMouseEvent *e );
void mouseReleaseEvent( TQMouseEvent *e );
#ifndef QT_NO_DRAGANDDROP
void dragEnterEvent( TQDragEnterEvent *e );
void dragLeaveEvent( TQDragLeaveEvent *e );
void dragMoveEvent( TQDragMoveEvent *e );
void dropEvent( TQDropEvent *e );
#endif
private:
TQRgb *values;
bool mousePressed;
TQPoint pressPos;
TQPoint oldCurrent;
};
void TQColorWell::paintCellContents( TQPainter *p, int row, int col, const TQRect &r )
{
int i = row + col*numRows();
p->fillRect( r, TQColor( values[i] ) );
}
void TQColorWell::mousePressEvent( TQMouseEvent *e )
{
oldCurrent = TQPoint( selectedRow(), selectedColumn() );
TQWellArray::mousePressEvent( e );
mousePressed = TRUE;
pressPos = e->pos();
}
void TQColorWell::mouseMoveEvent( TQMouseEvent *e )
{
TQWellArray::mouseMoveEvent( e );
#ifndef QT_NO_DRAGANDDROP
if ( !mousePressed )
return;
if ( ( pressPos - e->pos() ).manhattanLength() > TQApplication::startDragDistance() ) {
setCurrent( oldCurrent.x(), oldCurrent.y() );
int i = rowAt(pressPos.y()) + columnAt(pressPos.x()) * numRows();
TQColor col( values[ i ] );
TQColorDrag *drg = new TQColorDrag( col, this );
TQPixmap pix( cellWidth(), cellHeight() );
pix.fill( col );
TQPainter p( &pix );
p.drawRect( 0, 0, pix.width(), pix.height() );
p.end();
drg->setPixmap( pix );
mousePressed = FALSE;
drg->dragCopy();
}
#endif
}
#ifndef QT_NO_DRAGANDDROP
void TQColorWell::dragEnterEvent( TQDragEnterEvent *e )
{
setFocus();
if ( TQColorDrag::canDecode( e ) )
e->accept();
else
e->ignore();
}
void TQColorWell::dragLeaveEvent( TQDragLeaveEvent * )
{
if ( hasFocus() )
parentWidget()->setFocus();
}
void TQColorWell::dragMoveEvent( TQDragMoveEvent *e )
{
if ( TQColorDrag::canDecode( e ) ) {
setCurrent( rowAt( e->pos().y() ), columnAt( e->pos().x() ) );
e->accept();
} else
e->ignore();
}
void TQColorWell::dropEvent( TQDropEvent *e )
{
if ( TQColorDrag::canDecode( e ) ) {
int i = rowAt( e->pos().y() ) + columnAt( e->pos().x() ) * numRows();
TQColor col;
TQColorDrag::decode( e, col );
values[ i ] = col.rgb();
repaintContents( FALSE );
e->accept();
} else {
e->ignore();
}
}
#endif // QT_NO_DRAGANDDROP
void TQColorWell::mouseReleaseEvent( TQMouseEvent *e )
{
if ( !mousePressed )
return;
TQWellArray::mouseReleaseEvent( e );
mousePressed = FALSE;
}
class TQColorPicker : public TQFrame
{
Q_OBJECT
public:
TQColorPicker(TQWidget* parent=0, const char* name=0);
~TQColorPicker();
public slots:
void setCol( int h, int s );
signals:
void newCol( int h, int s );
protected:
TQSize sizeHint() const;
void drawContents(TQPainter* p);
void mouseMoveEvent( TQMouseEvent * );
void mousePressEvent( TQMouseEvent * );
private:
int hue;
int sat;
TQPoint colPt();
int huePt( const TQPoint &pt );
int satPt( const TQPoint &pt );
void setCol( const TQPoint &pt );
TQPixmap *pix;
};
static int pWidth = 200;
static int pHeight = 200;
class TQColorLuminancePicker : public TQWidget
{
Q_OBJECT
public:
TQColorLuminancePicker(TQWidget* parent=0, const char* name=0);
~TQColorLuminancePicker();
public slots:
void setCol( int h, int s, int v );
void setCol( int h, int s );
signals:
void newHsv( int h, int s, int v );
protected:
void paintEvent( TQPaintEvent*);
void mouseMoveEvent( TQMouseEvent * );
void mousePressEvent( TQMouseEvent * );
private:
enum { foff = 3, coff = 4 }; //frame and contents offset
int val;
int hue;
int sat;
int y2val( int y );
int val2y( int val );
void setVal( int v );
TQPixmap *pix;
};
int TQColorLuminancePicker::y2val( int y )
{
int d = height() - 2*coff - 1;
return 255 - (y - coff)*255/d;
}
int TQColorLuminancePicker::val2y( int v )
{
int d = height() - 2*coff - 1;
return coff + (255-v)*d/255;
}
TQColorLuminancePicker::TQColorLuminancePicker(TQWidget* parent,
const char* name)
:TQWidget( parent, name )
{
hue = 100; val = 100; sat = 100;
pix = 0;
// setBackgroundMode( NoBackground );
}
TQColorLuminancePicker::~TQColorLuminancePicker()
{
delete pix;
}
void TQColorLuminancePicker::mouseMoveEvent( TQMouseEvent *m )
{
setVal( y2val(m->y()) );
}
void TQColorLuminancePicker::mousePressEvent( TQMouseEvent *m )
{
setVal( y2val(m->y()) );
}
void TQColorLuminancePicker::setVal( int v )
{
if ( val == v )
return;
val = TQMAX( 0, TQMIN(v,255));
delete pix; pix=0;
repaint( FALSE ); //###
emit newHsv( hue, sat, val );
}
//receives from a hue,sat chooser and relays.
void TQColorLuminancePicker::setCol( int h, int s )
{
setCol( h, s, val );
emit newHsv( h, s, val );
}
void TQColorLuminancePicker::paintEvent( TQPaintEvent * )
{
int w = width() - 5;
TQRect r( 0, foff, w, height() - 2*foff );
int wi = r.width() - 2;
int hi = r.height() - 2;
if ( !pix || pix->height() != hi || pix->width() != wi ) {
delete pix;
TQImage img( wi, hi, 32 );
int y;
for ( y = 0; y < hi; y++ ) {
TQColor c( hue, sat, y2val(y+coff), TQColor::Hsv );
TQRgb r = c.rgb();
int x;
for ( x = 0; x < wi; x++ )
img.setPixel( x, y, r );
}
pix = new TQPixmap;
pix->convertFromImage(img);
}
TQPainter p(this);
p.drawPixmap( 1, coff, *pix );
const TQColorGroup &g = colorGroup();
qDrawShadePanel( &p, r, g, TRUE );
p.setPen( g.foreground() );
p.setBrush( g.foreground() );
TQPointArray a;
int y = val2y(val);
a.setPoints( 3, w, y, w+5, y+5, w+5, y-5 );
erase( w, 0, 5, height() );
p.drawPolygon( a );
}
void TQColorLuminancePicker::setCol( int h, int s , int v )
{
val = v;
hue = h;
sat = s;
delete pix; pix=0;
repaint( FALSE );//####
}
TQPoint TQColorPicker::colPt()
{ return TQPoint( (360-hue)*(pWidth-1)/360, (255-sat)*(pHeight-1)/255 ); }
int TQColorPicker::huePt( const TQPoint &pt )
{ return 360 - pt.x()*360/(pWidth-1); }
int TQColorPicker::satPt( const TQPoint &pt )
{ return 255 - pt.y()*255/(pHeight-1) ; }
void TQColorPicker::setCol( const TQPoint &pt )
{ setCol( huePt(pt), satPt(pt) ); }
TQColorPicker::TQColorPicker(TQWidget* parent, const char* name )
: TQFrame( parent, name )
{
hue = 0; sat = 0;
setCol( 150, 255 );
TQImage img( pWidth, pHeight, 32 );
int x,y;
for ( y = 0; y < pHeight; y++ )
for ( x = 0; x < pWidth; x++ ) {
TQPoint p( x, y );
img.setPixel( x, y, TQColor(huePt(p), satPt(p),
200, TQColor::Hsv).rgb() );
}
pix = new TQPixmap;
pix->convertFromImage(img);
setBackgroundMode( NoBackground );
setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
}
TQColorPicker::~TQColorPicker()
{
delete pix;
}
TQSize TQColorPicker::sizeHint() const
{
return TQSize( pWidth + 2*frameWidth(), pHeight + 2*frameWidth() );
}
void TQColorPicker::setCol( int h, int s )
{
int nhue = TQMIN( TQMAX(0,h), 360 );
int nsat = TQMIN( TQMAX(0,s), 255);
if ( nhue == hue && nsat == sat )
return;
TQRect r( colPt(), TQSize(20,20) );
hue = nhue; sat = nsat;
r = r.unite( TQRect( colPt(), TQSize(20,20) ) );
r.moveBy( contentsRect().x()-9, contentsRect().y()-9 );
// update( r );
repaint( r, FALSE );
}
void TQColorPicker::mouseMoveEvent( TQMouseEvent *m )
{
TQPoint p = m->pos() - contentsRect().topLeft();
setCol( p );
emit newCol( hue, sat );
}
void TQColorPicker::mousePressEvent( TQMouseEvent *m )
{
TQPoint p = m->pos() - contentsRect().topLeft();
setCol( p );
emit newCol( hue, sat );
}
void TQColorPicker::drawContents(TQPainter* p)
{
TQRect r = contentsRect();
p->drawPixmap( r.topLeft(), *pix );
TQPoint pt = colPt() + r.topLeft();
p->setPen( TQPen(black) );
p->fillRect( pt.x()-9, pt.y(), 20, 2, black );
p->fillRect( pt.x(), pt.y()-9, 2, 20, black );
}
class TQColorShowLabel;
class TQColIntValidator: public TQIntValidator
{
public:
TQColIntValidator( int bottom, int top,
TQWidget * parent, const char *name = 0 )
:TQIntValidator( bottom, top, parent, name ) {}
TQValidator::State validate( TQString &, int & ) const;
};
TQValidator::State TQColIntValidator::validate( TQString &s, int &pos ) const
{
State state = TQIntValidator::validate(s,pos);
if ( state == Valid ) {
long int val = s.toLong();
// This is not a general solution, assumes that top() > 0 and
// bottom >= 0
if ( val < 0 ) {
s = "0";
pos = 1;
} else if ( val > top() ) {
s.setNum( top() );
pos = s.length();
}
}
return state;
}
class TQColNumLineEdit : public TQLineEdit
{
public:
TQColNumLineEdit( TQWidget *parent, const char* name=0 )
: TQLineEdit( parent, name ) { setMaxLength( 3 );}
TQSize sizeHint() const {
return TQSize( fontMetrics().width( "999" ) + 2 * ( margin() + frameWidth() ),
TQLineEdit::sizeHint().height() ); }
void setNum( int i ) {
TQString s;
s.setNum(i);
bool block = signalsBlocked();
blockSignals(TRUE);
setText( s );
blockSignals(block);
}
int val() const { return text().toInt(); }
};
class TQColorShower : public TQWidget
{
Q_OBJECT
public:
TQColorShower( TQWidget *parent, const char *name=0 );
//things that don't emit signals
void setHsv( int h, int s, int v );
int currentAlpha() const { return alphaEd->val(); }
void setCurrentAlpha( int a ) { alphaEd->setNum( a ); }
void showAlpha( bool b );
TQRgb currentColor() const { return curCol; }
public slots:
void setRgb( TQRgb rgb );
signals:
void newCol( TQRgb rgb );
private slots:
void rgbEd();
void hsvEd();
private:
void showCurrentColor();
int hue, sat, val;
TQRgb curCol;
TQColNumLineEdit *hEd;
TQColNumLineEdit *sEd;
TQColNumLineEdit *vEd;
TQColNumLineEdit *rEd;
TQColNumLineEdit *gEd;
TQColNumLineEdit *bEd;
TQColNumLineEdit *alphaEd;
TQLabel *alphaLab;
TQColorShowLabel *lab;
bool rgbOriginal;
};
class TQColorShowLabel : public TQFrame
{
Q_OBJECT
public:
TQColorShowLabel( TQWidget *parent ) : TQFrame( parent, "qt_colorshow_lbl" ) {
setFrameStyle( TQFrame::Panel|TQFrame::Sunken );
setBackgroundMode( PaletteBackground );
setAcceptDrops( TRUE );
mousePressed = FALSE;
}
void setColor( TQColor c ) { col = c; }
signals:
void colorDropped( TQRgb );
protected:
void drawContents( TQPainter *p );
void mousePressEvent( TQMouseEvent *e );
void mouseMoveEvent( TQMouseEvent *e );
void mouseReleaseEvent( TQMouseEvent *e );
#ifndef QT_NO_DRAGANDDROP
void dragEnterEvent( TQDragEnterEvent *e );
void dragLeaveEvent( TQDragLeaveEvent *e );
void dropEvent( TQDropEvent *e );
#endif
private:
TQColor col;
bool mousePressed;
TQPoint pressPos;
};
void TQColorShowLabel::drawContents( TQPainter *p )
{
p->fillRect( contentsRect(), col );
}
void TQColorShower::showAlpha( bool b )
{
if ( b ) {
alphaLab->show();
alphaEd->show();
} else {
alphaLab->hide();
alphaEd->hide();
}
}
void TQColorShowLabel::mousePressEvent( TQMouseEvent *e )
{
mousePressed = TRUE;
pressPos = e->pos();
}
void TQColorShowLabel::mouseMoveEvent( TQMouseEvent *e )
{
#ifndef QT_NO_DRAGANDDROP
if ( !mousePressed )
return;
if ( ( pressPos - e->pos() ).manhattanLength() > TQApplication::startDragDistance() ) {
TQColorDrag *drg = new TQColorDrag( col, this );
TQPixmap pix( 30, 20 );
pix.fill( col );
TQPainter p( &pix );
p.drawRect( 0, 0, pix.width(), pix.height() );
p.end();
drg->setPixmap( pix );
mousePressed = FALSE;
drg->dragCopy();
}
#endif
}
#ifndef QT_NO_DRAGANDDROP
void TQColorShowLabel::dragEnterEvent( TQDragEnterEvent *e )
{
if ( TQColorDrag::canDecode( e ) )
e->accept();
else
e->ignore();
}
void TQColorShowLabel::dragLeaveEvent( TQDragLeaveEvent * )
{
}
void TQColorShowLabel::dropEvent( TQDropEvent *e )
{
if ( TQColorDrag::canDecode( e ) ) {
TQColorDrag::decode( e, col );
repaint( FALSE );
emit colorDropped( col.rgb() );
e->accept();
} else {
e->ignore();
}
}
#endif // QT_NO_DRAGANDDROP
void TQColorShowLabel::mouseReleaseEvent( TQMouseEvent * )
{
if ( !mousePressed )
return;
mousePressed = FALSE;
}
TQColorShower::TQColorShower( TQWidget *parent, const char *name )
:TQWidget( parent, name)
{
curCol = qRgb( -1, -1, -1 );
TQColIntValidator *val256 = new TQColIntValidator( 0, 255, this );
TQColIntValidator *val360 = new TQColIntValidator( 0, 360, this );
TQGridLayout *gl = new TQGridLayout( this, 1, 1, 6 );
lab = new TQColorShowLabel( this );
lab->setMinimumWidth( 60 ); //###
gl->addMultiCellWidget(lab, 0,-1,0,0);
connect( lab, SIGNAL( colorDropped(TQRgb) ),
this, SIGNAL( newCol(TQRgb) ) );
connect( lab, SIGNAL( colorDropped(TQRgb) ),
this, SLOT( setRgb(TQRgb) ) );
hEd = new TQColNumLineEdit( this, "qt_hue_edit" );
hEd->setValidator( val360 );
TQLabel *l = new TQLabel( hEd, TQColorDialog::tr("Hu&e:"), this, "qt_hue_lbl" );
l->setAlignment( AlignRight|AlignVCenter );
gl->addWidget( l, 0, 1 );
gl->addWidget( hEd, 0, 2 );
sEd = new TQColNumLineEdit( this, "qt_sat_edit" );
sEd->setValidator( val256 );
l = new TQLabel( sEd, TQColorDialog::tr("&Sat:"), this, "qt_sat_lbl" );
l->setAlignment( AlignRight|AlignVCenter );
gl->addWidget( l, 1, 1 );
gl->addWidget( sEd, 1, 2 );
vEd = new TQColNumLineEdit( this, "qt_val_edit" );
vEd->setValidator( val256 );
l = new TQLabel( vEd, TQColorDialog::tr("&Val:"), this, "qt_val_lbl" );
l->setAlignment( AlignRight|AlignVCenter );
gl->addWidget( l, 2, 1 );
gl->addWidget( vEd, 2, 2 );
rEd = new TQColNumLineEdit( this, "qt_red_edit" );
rEd->setValidator( val256 );
l = new TQLabel( rEd, TQColorDialog::tr("&Red:"), this, "qt_red_lbl" );
l->setAlignment( AlignRight|AlignVCenter );
gl->addWidget( l, 0, 3 );
gl->addWidget( rEd, 0, 4 );
gEd = new TQColNumLineEdit( this, "qt_grn_edit" );
gEd->setValidator( val256 );
l = new TQLabel( gEd, TQColorDialog::tr("&Green:"), this, "qt_grn_lbl" );
l->setAlignment( AlignRight|AlignVCenter );
gl->addWidget( l, 1, 3 );
gl->addWidget( gEd, 1, 4 );
bEd = new TQColNumLineEdit( this, "qt_blue_edit" );
bEd->setValidator( val256 );
l = new TQLabel( bEd, TQColorDialog::tr("Bl&ue:"), this, "qt_blue_lbl" );
l->setAlignment( AlignRight|AlignVCenter );
gl->addWidget( l, 2, 3 );
gl->addWidget( bEd, 2, 4 );
alphaEd = new TQColNumLineEdit( this, "qt_aplha_edit" );
alphaEd->setValidator( val256 );
alphaLab = new TQLabel( alphaEd, TQColorDialog::tr("A&lpha channel:"), this, "qt_alpha_lbl" );
alphaLab->setAlignment( AlignRight|AlignVCenter );
gl->addMultiCellWidget( alphaLab, 3, 3, 1, 3 );
gl->addWidget( alphaEd, 3, 4 );
alphaEd->hide();
alphaLab->hide();
connect( hEd, SIGNAL(textChanged(const TQString&)), this, SLOT(hsvEd()) );
connect( sEd, SIGNAL(textChanged(const TQString&)), this, SLOT(hsvEd()) );
connect( vEd, SIGNAL(textChanged(const TQString&)), this, SLOT(hsvEd()) );
connect( rEd, SIGNAL(textChanged(const TQString&)), this, SLOT(rgbEd()) );
connect( gEd, SIGNAL(textChanged(const TQString&)), this, SLOT(rgbEd()) );
connect( bEd, SIGNAL(textChanged(const TQString&)), this, SLOT(rgbEd()) );
connect( alphaEd, SIGNAL(textChanged(const TQString&)), this, SLOT(rgbEd()) );
}
void TQColorShower::showCurrentColor()
{
lab->setColor( currentColor() );
lab->repaint(FALSE); //###
}
void TQColorShower::rgbEd()
{
rgbOriginal = TRUE;
if ( alphaEd->isVisible() )
curCol = qRgba( rEd->val(), gEd->val(), bEd->val(), currentAlpha() );
else
curCol = qRgb( rEd->val(), gEd->val(), bEd->val() );
rgb2hsv(currentColor(), hue, sat, val );
hEd->setNum( hue );
sEd->setNum( sat );
vEd->setNum( val );
showCurrentColor();
emit newCol( currentColor() );
}
void TQColorShower::hsvEd()
{
rgbOriginal = FALSE;
hue = hEd->val();
sat = sEd->val();
val = vEd->val();
curCol = TQColor( hue, sat, val, TQColor::Hsv ).rgb();
rEd->setNum( qRed(currentColor()) );
gEd->setNum( qGreen(currentColor()) );
bEd->setNum( qBlue(currentColor()) );
showCurrentColor();
emit newCol( currentColor() );
}
void TQColorShower::setRgb( TQRgb rgb )
{
rgbOriginal = TRUE;
curCol = rgb;
rgb2hsv( currentColor(), hue, sat, val );
hEd->setNum( hue );
sEd->setNum( sat );
vEd->setNum( val );
rEd->setNum( qRed(currentColor()) );
gEd->setNum( qGreen(currentColor()) );
bEd->setNum( qBlue(currentColor()) );
showCurrentColor();
}
void TQColorShower::setHsv( int h, int s, int v )
{
rgbOriginal = FALSE;
hue = h; val = v; sat = s; //Range check###
curCol = TQColor( hue, sat, val, TQColor::Hsv ).rgb();
hEd->setNum( hue );
sEd->setNum( sat );
vEd->setNum( val );
rEd->setNum( qRed(currentColor()) );
gEd->setNum( qGreen(currentColor()) );
bEd->setNum( qBlue(currentColor()) );
showCurrentColor();
}
class TQColorDialogPrivate : public TQObject
{
Q_OBJECT
public:
TQColorDialogPrivate( TQColorDialog *p );
TQRgb currentColor() const { return cs->currentColor(); }
void setCurrentColor( TQRgb rgb );
int currentAlpha() const { return cs->currentAlpha(); }
void setCurrentAlpha( int a ) { cs->setCurrentAlpha( a ); }
void showAlpha( bool b ) { cs->showAlpha( b ); }
public slots:
void addCustom();
void newHsv( int h, int s, int v );
void newColorTypedIn( TQRgb rgb );
void newCustom( int, int );
void newStandard( int, int );
public:
TQWellArray *custom;
TQWellArray *standard;
TQColorPicker *cp;
TQColorLuminancePicker *lp;
TQColorShower *cs;
int nextCust;
bool compact;
};
//sets all widgets to display h,s,v
void TQColorDialogPrivate::newHsv( int h, int s, int v )
{
cs->setHsv( h, s, v );
cp->setCol( h, s );
lp->setCol( h, s, v );
}
//sets all widgets to display rgb
void TQColorDialogPrivate::setCurrentColor( TQRgb rgb )
{
cs->setRgb( rgb );
newColorTypedIn( rgb );
}
//sets all widgets exept cs to display rgb
void TQColorDialogPrivate::newColorTypedIn( TQRgb rgb )
{
int h, s, v;
rgb2hsv(rgb, h, s, v );
cp->setCol( h, s );
lp->setCol( h, s, v);
}
void TQColorDialogPrivate::newCustom( int r, int c )
{
int i = r+2*c;
setCurrentColor( cusrgb[i] );
nextCust = i;
if (standard)
standard->setSelected(-1,-1);
}
void TQColorDialogPrivate::newStandard( int r, int c )
{
setCurrentColor( stdrgb[r+c*6] );
if (custom)
custom->setSelected(-1,-1);
}
TQColorDialogPrivate::TQColorDialogPrivate( TQColorDialog *dialog ) :
TQObject(dialog)
{
compact = FALSE;
// small displays (e.g. PDAs cannot fit the full color dialog,
// so just use the color picker.
if ( qApp->desktop()->width() < 480 || qApp->desktop()->height() < 350 )
compact = TRUE;
nextCust = 0;
const int lumSpace = 3;
int border = 12;
if ( compact )
border = 6;
TQHBoxLayout *topLay = new TQHBoxLayout( dialog, border, 6 );
TQVBoxLayout *leftLay = 0;
if ( !compact )
leftLay = new TQVBoxLayout( topLay );
initRGB();
if ( !compact ) {
standard = new TQColorWell( dialog, 6, 8, stdrgb );
standard->setCellWidth( 28 );
standard->setCellHeight( 24 );
TQLabel * lab = new TQLabel( standard,
TQColorDialog::tr( "&Basic colors"), dialog, "qt_basiccolors_lbl" );
connect( standard, SIGNAL(selected(int,int)), SLOT(newStandard(int,int)));
leftLay->addWidget( lab );
leftLay->addWidget( standard );
leftLay->addStretch();
custom = new TQColorWell( dialog, 2, 8, cusrgb );
custom->setCellWidth( 28 );
custom->setCellHeight( 24 );
custom->setAcceptDrops( TRUE );
connect( custom, SIGNAL(selected(int,int)), SLOT(newCustom(int,int)));
lab = new TQLabel( custom, TQColorDialog::tr( "&Custom colors") , dialog, "qt_custcolors_lbl" );
leftLay->addWidget( lab );
leftLay->addWidget( custom );
TQPushButton *custbut =
new TQPushButton( TQColorDialog::tr("&Define Custom Colors >>"),
dialog, "qt_def_custcolors_lbl" );
custbut->setEnabled( FALSE );
leftLay->addWidget( custbut );
} else {
// better color picker size for small displays
pWidth = 150;
pHeight = 100;
custom = 0;
standard = 0;
}
TQVBoxLayout *rightLay = new TQVBoxLayout( topLay );
TQHBoxLayout *pickLay = new TQHBoxLayout( rightLay );
TQVBoxLayout *cLay = new TQVBoxLayout( pickLay );
cp = new TQColorPicker( dialog, "qt_colorpicker" );
cp->setFrameStyle( TQFrame::Panel + TQFrame::Sunken );
cLay->addSpacing( lumSpace );
cLay->addWidget( cp );
cLay->addSpacing( lumSpace );
lp = new TQColorLuminancePicker( dialog, "qt_luminance_picker" );
lp->setFixedWidth( 20 ); //###
pickLay->addWidget( lp );
connect( cp, SIGNAL(newCol(int,int)), lp, SLOT(setCol(int,int)) );
connect( lp, SIGNAL(newHsv(int,int,int)), this, SLOT(newHsv(int,int,int)) );
rightLay->addStretch();
cs = new TQColorShower( dialog, "qt_colorshower" );
connect( cs, SIGNAL(newCol(TQRgb)), this, SLOT(newColorTypedIn(TQRgb)));
rightLay->addWidget( cs );
TQHBoxLayout *buttons;
if ( compact )
buttons = new TQHBoxLayout( rightLay );
else
buttons = new TQHBoxLayout( leftLay );
TQPushButton *ok, *cancel;
ok = new TQPushButton( TQColorDialog::tr("OK"), dialog, "qt_ok_btn" );
connect( ok, SIGNAL(clicked()), dialog, SLOT(accept()) );
ok->setDefault(TRUE);
cancel = new TQPushButton( TQColorDialog::tr("Cancel"), dialog, "qt_cancel_btn" );
connect( cancel, SIGNAL(clicked()), dialog, SLOT(reject()) );
buttons->addWidget( ok );
buttons->addWidget( cancel );
buttons->addStretch();
if ( !compact ) {
TQPushButton *addCusBt = new TQPushButton(
TQColorDialog::tr("&Add to Custom Colors"),
dialog, "qt_add_btn" );
rightLay->addWidget( addCusBt );
connect( addCusBt, SIGNAL(clicked()), this, SLOT(addCustom()) );
}
}
void TQColorDialogPrivate::addCustom()
{
cusrgb[nextCust] = cs->currentColor();
if (custom)
custom->repaintContents( FALSE );
nextCust = (nextCust+1) % 16;
}
/*!
\class TQColorDialog qcolordialog.h
\brief The TQColorDialog class provides a dialog widget for specifying colors.
\mainclass
\ingroup dialogs
\ingroup graphics
The color dialog's function is to allow users to choose colors.
For example, you might use this in a drawing program to allow the
user to set the brush color.
The static functions provide modal color dialogs.
\omit
If you retquire a modeless dialog, use the TQColorDialog constructor.
\endomit
The static getColor() function shows the dialog and allows the
user to specify a color. The getRgba() function does the same but
also allows the user to specify a color with an alpha channel
(transparency) value.
The user can store customCount() different custom colors. The
custom colors are shared by all color dialogs, and remembered
during the execution of the program. Use setCustomColor() to set
the custom colors, and use customColor() to get them.
\img qcolordlg-w.png
*/
/*!
Constructs a default color dialog with parent \a parent and called
\a name. If \a modal is TRUE the dialog will be modal. Use
setColor() to set an initial value.
\sa getColor()
*/
TQColorDialog::TQColorDialog(TQWidget* parent, const char* name, bool modal) :
TQDialog(parent, name, modal, ( WType_Dialog | WStyle_Customize | WStyle_Title |
WStyle_DialogBorder | WStyle_SysMenu ) )
{
setSizeGripEnabled( FALSE );
d = new TQColorDialogPrivate( this );
#ifndef QT_NO_SETTINGS
if ( !customSet ) {
TQSettings settings;
settings.insertSearchPath( TQSettings::Windows, "/Trolltech" );
for ( int i = 0; i < 2*8; ++i ) {
bool ok = FALSE;
TQRgb rgb = (TQRgb)settings.readNumEntry( "/TQt/customColors/" + TQString::number( i ), 0, &ok );
if ( ok )
cusrgb[i] = rgb;
}
}
#endif
}
/*!
Pops up a modal color dialog, lets the user choose a color, and
returns that color. The color is initially set to \a initial. The
dialog is a child of \a parent and is called \a name. It returns
an invalid (see TQColor::isValid()) color if the user cancels the
dialog. All colors allocated by the dialog will be deallocated
before this function returns.
*/
TQColor TQColorDialog::getColor( const TQColor& initial, TQWidget *parent,
const char *name )
{
#if defined(Q_WS_X11)
if( TQKDEIntegration::enabled())
return TQKDEIntegration::getColor( initial, parent, name );
#elif defined(Q_WS_MAC)
return macGetColor(initial, parent, name);
#endif
int allocContext = TQColor::enterAllocContext();
TQColorDialog *dlg = new TQColorDialog( parent, name, TRUE ); //modal
#ifndef QT_NO_WIDGET_TOPEXTRA
dlg->setCaption( TQColorDialog::tr( "Select color" ) );
#endif
dlg->setColor( initial );
dlg->selectColor( initial );
int resultCode = dlg->exec();
TQColor::leaveAllocContext();
TQColor result;
if ( resultCode == TQDialog::Accepted )
result = dlg->color();
TQColor::destroyAllocContext(allocContext);
delete dlg;
return result;
}
/*!
Pops up a modal color dialog to allow the user to choose a color
and an alpha channel (transparency) value. The color+alpha is
initially set to \a initial. The dialog is a child of \a parent
and called \a name.
If \a ok is non-null, \e *\a ok is set to TRUE if the user clicked
OK, and to FALSE if the user clicked Cancel.
If the user clicks Cancel, the \a initial value is returned.
*/
TQRgb TQColorDialog::getRgba( TQRgb initial, bool *ok,
TQWidget *parent, const char* name )
{
#if defined(Q_WS_MAC)
if( TQKDEIntegration::enabled()) {
TQColor color = TQKDEIntegration::getColor( TQColor( initial ), parent, name );
if( ok )
*ok = color.isValid();
return color.rgba();
}
#elif defined(Q_WS_MAC)
return macGetRgba(initial, ok, parent, name);
#endif
int allocContext = TQColor::enterAllocContext();
TQColorDialog *dlg = new TQColorDialog( parent, name, TRUE ); //modal
Q_CHECK_PTR( dlg );
#ifndef QT_NO_WIDGET_TOPEXTRA
dlg->setCaption( TQColorDialog::tr( "Select color" ) );
#endif
dlg->setColor( initial );
dlg->selectColor( initial );
dlg->setSelectedAlpha( qAlpha(initial) );
int resultCode = dlg->exec();
TQColor::leaveAllocContext();
TQRgb result = initial;
if ( resultCode == TQDialog::Accepted ) {
TQRgb c = dlg->color().rgb();
int alpha = dlg->selectedAlpha();
result = qRgba( qRed(c), qGreen(c), qBlue(c), alpha );
}
if ( ok )
*ok = resultCode == TQDialog::Accepted;
TQColor::destroyAllocContext(allocContext);
delete dlg;
return result;
}
/*!
Returns the color currently selected in the dialog.
\sa setColor()
*/
TQColor TQColorDialog::color() const
{
return TQColor(d->currentColor());
}
/*!
Destroys the dialog and frees any memory it allocated.
*/
TQColorDialog::~TQColorDialog()
{
#ifndef QT_NO_SETTINGS
if ( !customSet ) {
TQSettings settings;
settings.insertSearchPath( TQSettings::Windows, "/Trolltech" );
for ( int i = 0; i < 2*8; ++i )
settings.writeEntry( "/TQt/customColors/" + TQString::number( i ), (int)cusrgb[i] );
}
#endif
}
/*!
Sets the color shown in the dialog to \a c.
\sa color()
*/
void TQColorDialog::setColor( const TQColor& c )
{
d->setCurrentColor( c.rgb() );
}
/*!
Sets the initial alpha channel value to \a a, and shows the alpha
channel entry box.
*/
void TQColorDialog::setSelectedAlpha( int a )
{
d->showAlpha( TRUE );
d->setCurrentAlpha( a );
}
/*!
Returns the value selected for the alpha channel.
*/
int TQColorDialog::selectedAlpha() const
{
return d->currentAlpha();
}
/*!
Sets focus to the corresponding button, if any.
*/
bool TQColorDialog::selectColor( const TQColor& col )
{
TQRgb color = col.rgb();
int i = 0, j = 0;
// Check standard colors
if (d->standard) {
for ( i = 0; i < 6; i++ ) {
for ( j = 0; j < 8; j++ ) {
if ( color == stdrgb[i + j*6] ) {
d->newStandard( i, j );
d->standard->setCurrent( i, j );
d->standard->setSelected( i, j );
d->standard->setFocus();
return TRUE;
}
}
}
}
// Check custom colors
if (d->custom) {
for ( i = 0; i < 2; i++ ) {
for ( j = 0; j < 8; j++ ) {
if ( color == cusrgb[i + j*2] ) {
d->newCustom( i, j );
d->custom->setCurrent( i, j );
d->custom->setSelected( i, j );
d->custom->setFocus();
return TRUE;
}
}
}
}
return FALSE;
}
#include "qcolordialog.moc"
#endif