From ffe47019a96da4e6b7057fca30bb64274443099b Mon Sep 17 00:00:00 2001 From: mickeyl Date: Tue, 13 Jan 2004 21:14:51 +0000 Subject: introduce libqtaux in order to get a LGPL clean libopie2 after the merge with libopie1 --- (limited to 'libqtaux') diff --git a/libqtaux/.cvsignore b/libqtaux/.cvsignore new file mode 100644 index 0000000..8f7300c --- a/dev/null +++ b/libqtaux/.cvsignore @@ -0,0 +1,6 @@ +Makefile* +moc* +*moc +*.o +~* + diff --git a/libqtaux/README b/libqtaux/README new file mode 100644 index 0000000..9d9d8a0 --- a/dev/null +++ b/libqtaux/README @@ -0,0 +1,12 @@ +This library contains auxilliary stuff from Qt/Embedded 2.3.x which +is very useful but has been left out from qconfig-qpe.h. + +Note: We can't just enable the said classes in our qconfig, because that + would mean we no longer could link to a sharp rom libqpe. + +Also note: We don't ship that embedded in libopie2 + (nor do we use it from libopie2), because we want to keep + libopie2 LGPL - hence Opie stuff using these classes is also here. + +It could be useful to eventually have some original classes +providing similar functionality. diff --git a/libqtaux/config.in b/libqtaux/config.in new file mode 100644 index 0000000..d34a4cc --- a/dev/null +++ b/libqtaux/config.in @@ -0,0 +1,3 @@ + config LIBQTAUX + boolean "Qt/Embedded Auxilliary Library" + default "n" diff --git a/libqtaux/libqtaux.control b/libqtaux/libqtaux.control new file mode 100644 index 0000000..782a8f4 --- a/dev/null +++ b/libqtaux/libqtaux.control @@ -0,0 +1,10 @@ +Package: libqtaux2 +Files: $OPIEDIR/lib/libqtaux2.so.* +Priority: optional +Section: opie/system +Maintainer: Opie Team +Architecture: arm +Version: 2.3.7-1 +Depends: libqte2 +Provides: libqtaux +Description: Qt/Embedded Auxilliary Stuff diff --git a/libqtaux/libqtaux.postinst b/libqtaux/libqtaux.postinst new file mode 100755 index 0000000..0c37b3d --- a/dev/null +++ b/libqtaux/libqtaux.postinst @@ -0,0 +1,4 @@ +#!/bin/sh + +[ -x /sbin/ldconfig ] && /sbin/ldconfig +exit 0 diff --git a/libqtaux/libqtaux.pro b/libqtaux/libqtaux.pro new file mode 100644 index 0000000..2f7aa91 --- a/dev/null +++ b/libqtaux/libqtaux.pro @@ -0,0 +1,23 @@ +TEMPLATE = lib +CONFIG += qte warn_on debug + +HEADERS = qcolordialog.h \ + qsplitter.h \ + qinputdialog.h \ + \ + ocolorpopupmenu.h + + +SOURCES = qcolordialog.cpp \ + qsplitter.cpp \ + qinputdialog.cpp \ + \ + ocolorpopupmenu.cpp + +TARGET = qtaux2 +INCLUDEPATH += $(OPIEDIR)/include +DESTDIR = $(OPIEDIR)/lib +INTERFACES = + + +include ( $(OPIEDIR)/include.pro ) diff --git a/libqtaux/ocolorpopupmenu.cpp b/libqtaux/ocolorpopupmenu.cpp new file mode 100644 index 0000000..6a2321e --- a/dev/null +++ b/libqtaux/ocolorpopupmenu.cpp @@ -0,0 +1,173 @@ +/* +                This file is part of the Opie Project + +              Copyright (c) 2002 S. Prud'homme +              Dan Williams + =. + .=l. +           .>+-= + _;:,     .>    :=|. This program is free software; you can +.> <`_,   >  .   <= redistribute it and/or modify it under +:`=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; either version 2 of the License, +     ._= =}       : or (at your option) any later version. +    .%`+i>       _;_. +    .i_,=:_.      -`: 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 library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#include "ocolorpopupmenu.h" +#include "qcolordialog.h" + +#include +#include +#include + +OColorPanelButton::OColorPanelButton( const QColor& color, QWidget* parent, const char* name ) + : QFrame( parent, name ) +{ + m_color = color; + + setFixedSize( 16, 16 ); + setActive( FALSE ); +} + +OColorPanelButton::~OColorPanelButton() +{ +} + +void OColorPanelButton::setActive( bool active ) +{ + m_active = active; + + if ( m_active ) { + setFrameStyle( Panel | Sunken ); + } else { + setFrameStyle( NoFrame ); + } +} + +void OColorPanelButton::enterEvent( QEvent* ) +{ + if ( !m_active ) { + setFrameStyle( Panel | Sunken ); + } +} + +void OColorPanelButton::leaveEvent( QEvent* ) +{ + if ( !m_active ) { + setFrameStyle( NoFrame ); + } +} + +void OColorPanelButton::paintEvent( QPaintEvent* e ) +{ + QFrame::paintEvent( e ); + + QPainter painter; + painter.begin( this ); + painter.fillRect( 2, 2, 12, 12, m_color ); + painter.setPen( Qt::black ); + painter.drawRect( 2, 2, 12, 12 ); + painter.end(); +} + +void OColorPanelButton::mouseReleaseEvent( QMouseEvent* ) +{ + emit selected( m_color ); +} + +OColorPopupMenu::OColorPopupMenu( const QColor& color, QWidget* parent, const char* name ) + : QPopupMenu( parent, name ) +{ + m_color = color; + + colorPanel = new QWidget( this ); + + colorLayout = new QGridLayout(colorPanel, 5, 6); + + addColor(QColor(255, 255, 255), 0, 1); + addColor(QColor(192, 192, 192), 0, 2); + addColor(QColor(128, 128, 128), 0, 3); + addColor(QColor(64, 64, 64), 0, 4); + addColor(QColor(0, 0, 0), 0, 5); + + addColor(QColor(255, 0, 0), 1, 0); + addColor(QColor(255, 128, 0), 1, 1); + addColor(QColor(255, 255, 0), 1, 2); + addColor(QColor(128, 255, 0), 1, 3); + addColor(QColor(0, 255, 0), 1, 4); + addColor(QColor(0, 255, 128), 1, 5); + + addColor(QColor(128, 0, 0), 2, 0); + addColor(QColor(128, 64, 0), 2, 1); + addColor(QColor(128, 128, 0), 2, 2); + addColor(QColor(64, 128, 0), 2, 3); + addColor(QColor(0, 128, 0), 2, 4); + addColor(QColor(0, 128, 64), 2, 5); + + addColor(QColor(0, 255, 255), 3, 0); + addColor(QColor(0, 128, 255), 3, 1); + addColor(QColor(0, 0, 255), 3, 2); + addColor(QColor(128, 0, 255), 3, 3); + addColor(QColor(255, 0, 255), 3, 4); + addColor(QColor(255, 0, 128), 3, 5); + + addColor(QColor(0, 128, 128), 4, 0); + addColor(QColor(0, 64, 128), 4, 1); + addColor(QColor(0, 0, 128), 4, 2); + addColor(QColor(64, 0, 128), 4, 3); + addColor(QColor(128, 0, 128), 4, 4); + addColor(QColor(128, 0, 64), 4, 5); + + insertItem( colorPanel ); + insertSeparator(); + insertItem(tr("More"),this,SLOT( moreColorClicked())); + /* + QAction* chooseColorAction = new QAction( tr( "More" ), tr( "More..." ), 0, colorPanel, "More" ); + connect( chooseColorAction, SIGNAL( activated() ), this, SLOT( moreColorClicked() ) ); + chooseColorAction->addTo( this ); + */ + activateItemAt( 0 ); +} + +OColorPopupMenu::~OColorPopupMenu() +{ +} + +void OColorPopupMenu::addColor( const QColor& color, int row, int col ) +{ + OColorPanelButton* panelButton = new OColorPanelButton( color, colorPanel ); + connect( panelButton, SIGNAL( selected( const QColor& ) ), this, SLOT( buttonSelected( const QColor& ) ) ); + colorLayout->addWidget( panelButton, row, col ); +} + +void OColorPopupMenu::buttonSelected( const QColor& color ) +{ + m_color = color; + emit colorSelected( color ); + hide(); +} + +void OColorPopupMenu::moreColorClicked() +{ + QColor color = QColorDialog::getColor( m_color ); + m_color = color; + emit colorSelected( color ); + hide(); +} diff --git a/libqtaux/ocolorpopupmenu.h b/libqtaux/ocolorpopupmenu.h new file mode 100644 index 0000000..90cfbed --- a/dev/null +++ b/libqtaux/ocolorpopupmenu.h @@ -0,0 +1,255 @@ +/* +                This file is part of the Opie Project + +              Copyright (c) 2002 S. Prud'homme +              Dan Williams + =. + .=l. +           .>+-= + _;:,     .>    :=|. This program is free software; you can +.> <`_,   >  .   <= redistribute it and/or modify it under +:`=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; either version 2 of the License, +     ._= =}       : or (at your option) any later version. +    .%`+i>       _;_. +    .i_,=:_.      -`: 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 library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#ifndef COLORPOPUPMENU_H +#define COLORPOPUPMENU_H + +#include +#include + +class QWidget; +class QGridLayout; + +/** + * @class OColorPanelButton + * @brief The OColorPanelButton class provides a button for color selection. + * + * @see OColorPopupMenu + * + * The OColorPanelButton class provides a button for color selection. The button + * is drawn with the desired color and no border. This class is used internally + * by the OColorPopupMenu class to displaying colors in its menu. + */ +class OColorPanelButton : public QFrame +{ + Q_OBJECT + +public: + +/** + * @fn OColorPanelButton( const QColor& color, QWidget* parent = 0, const char* name = 0 ) + * @brief Object constructor. + * + * @param color Desired color. + * @param parent Pointer to parent of this control. + * @param name Name of control. + * + * Constructs a new ColorPanelButton control with parent, name and desired color. + */ + OColorPanelButton(const QColor& color, QWidget* parent = 0, const char* name = 0); + +/** + * @fn ~OColorPanelButton() + * @brief Object destructor. + */ + ~OColorPanelButton(); + +/** + * @fn setActive( bool active ) + * @brief Sets button selection state. + * + * @param active Boolean indicator of new button state. + * + * Changes button selection state. If button is selected, a highlighted border + * is drawn. + */ + void setActive(bool active); + +/** + * @fn enterEvent( QEvent* e ) + * @brief Reimplemented for internal reasons. + * + * @param e Event currently being processed. + * + * Reimplemented to ensure correct display of button based on whether it is + * active or not. + */ + void enterEvent(QEvent* e); + +/** + * @fn leaveEvent( QEvent* e ) + * @brief Reimplemented for internal reasons. + * + * @param e Event currently being processed. + * + * Reimplemented to ensure correct display of button based on whether it is + * active or not. + */ + void leaveEvent(QEvent* e); + +/** + * @fn paintEvent( QPaintEvent* e ) + * @brief Reimplemented for internal reasons. + * + * @param e Event currently being processed. + * @reimp + * Reimplemented to ensure correct display of button. + */ + void paintEvent(QPaintEvent* e); + +/** + * @fn mouseReleaseEvent( QMouseEvent* e ) + * @brief Slot executed when button is pressed. + * + * @param e Mouse event currently being processed. + * + * @see selected() + * + * This slot executes when the button has been pressed. It emits the selected + * signal as notification that it has been pressed. + */ + void mouseReleaseEvent(QMouseEvent* e); + +signals: + +/** + * @fn selected( const QColor& color ) + * @brief Signal to indicate button has been pressed. + * + * @param color Button color. + * + * This signal is emitted when the button is pressed. It provides the color + * associated to this button. + */ + void selected(const QColor&); + +private: + QColor m_color; + bool m_active : 1; + class ColorPanelButtonPrivate; + ColorPanelButtonPrivate *d; +}; + +/** + * @class OColorPopupMenu + * @brief The OColorPopupMenu class provides a small color selection + * popup menu. + * + * OColorPopupMenu is a derivation of TrollTech's QPopupMenu and provides + * a small color selection popup menu which can be attached to another control + * such as a toolbar button of menu item. + * + * The popup menu displays 30 default colors available in a grid, and also + * includes an option at the bottom to display a color selection dialog box for + * finer color control. + */ +class OColorPopupMenu : public QPopupMenu +{ + Q_OBJECT + +public: + +/** + * @fn OColorPopupMenu( const QColor& color, QWidget* parent = 0, const char* name = 0 ) + * @brief Object constructor. + * + * @param color Initial color selected in menu. + * @param parent Pointer to parent of this control. + * @param name Name of control. + * + * Constructs a new OColorPopupMenu control with parent, name and initial color selected. + */ + // FIXME add Wflags? -zecke + OColorPopupMenu( const QColor& color, QWidget* parent = 0, const char* name = 0 ); + +/** + * @fn ~OColorPopupMenu() + * @brief Object destructor. + */ + ~OColorPopupMenu(); + +private: + class ColorPopupMenuPrivate; + ColorPopupMenuPrivate *d; + QColor m_color; + QWidget* colorPanel; + QGridLayout* colorLayout; + +/** + * @fn addColor( const QColor& color, int row, int col ) + * @brief Adds color selection option to popup menu. + * + * @param color Color to be displayed in menu. + * @param row Row where color is to appear in menu. + * @param col Column where color is to appear in menu. + * + * Adds a color selection option to popup menu. Used internally when + * initially constructing the menu control. + */ + void addColor( const QColor& color, int row, int col ); + +signals: + +/** + * @fn colorSelected( const QColor& color ) + * @brief Signal to indicate color chosen from the menu. + * + * @param color Color selected from the menu. + * + * This signal is emitted when a color has been selected either directly from + * the menu, or chosen from the color selection dialog. + */ + void colorSelected( const QColor& color ); + +protected slots: + +/** + * @fn buttonSelected( const QColor& color ) + * @brief Slot to process selected color. + * + * @param color Color selected from the menu. + * + * @see colorSelected() + * + * This slot executes when a color has been selected from the menu. It performs + * two functions: + * - Emit the colorSelected signal with the color selected. + * - Hide the menu. + */ + void buttonSelected( const QColor& color ); + +/** + * @fn moreColorClicked() + * @brief Slot to process display color selection dialog. + * + * @see colorSelected() + * + * This slot executes when the 'More...' option is selected at the bottom of the menu. + * It performs the following functions: + * - Constructs and executes a QColorDialog to allow finer color selection. + * - Emit the colorSelected signal with the color selected. + * - Hide the menu. + */ + void moreColorClicked(); +}; + +#endif // COLORPOPUPMENUANEL_H diff --git a/libqtaux/qcolordialog.cpp b/libqtaux/qcolordialog.cpp new file mode 100644 index 0000000..5881a89 --- a/dev/null +++ b/libqtaux/qcolordialog.cpp @@ -0,0 +1,1629 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QColorDialog class +** +** Created : 990222 +** +** Copyright (C) 1999-2000 Trolltech AS. All rights reserved. +** +** This file is part of the dialogs module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qcolordialog.h" + +#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 "qapplication.h" +#include "qdragobject.h" + +//////////// QWellArray BEGIN + +#include "qobjectdict.h" + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qwellarray.cpp and qcolordialog.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// + + +#include "qtableview.h" + + +struct QWellArrayData; + +class QWellArray : public QTableView +{ + Q_OBJECT + Q_PROPERTY( int numCols READ numCols ) + Q_PROPERTY( int numRows READ numRows ) + Q_PROPERTY( int selectedColumn READ selectedColumn ) + Q_PROPERTY( int selectedRow READ selectedRow ) + +public: + QWellArray( QWidget *parent=0, const char *name=0, bool popup = FALSE ); + + ~QWellArray() {} + QString cellContent( int row, int col ) const; + // ### Paul !!! virtual void setCellContent( int row, int col, const QString &); + + // ##### Obsolete since not const + int numCols() { return nCols; } + int numRows() { return nRows; } + + int numCols() const { return nCols; } + int numRows() const { return nRows; } + + // ##### Obsolete since not const + int selectedColumn() { return selCol; } + int selectedRow() { return selRow; } + + int selectedColumn() const { return selCol; } + int selectedRow() const { return selRow; } + + virtual void setSelected( int row, int col ); + + void setCellSize( int w, int h ) { setCellWidth(w);setCellHeight( h ); } + + QSize sizeHint() const; + + virtual void setDimension( int rows, int cols ); + virtual void setCellBrush( int row, int col, const QBrush & ); + QBrush cellBrush( int row, int col ); + +signals: + void selected( int row, int col ); + +protected: + virtual void setCurrent( int row, int col ); + + virtual void drawContents( QPainter *, int row, int col, const QRect& ); + void drawContents( QPainter * ); + + void paintCell( QPainter*, int row, int col ); + void mousePressEvent( QMouseEvent* ); + void mouseReleaseEvent( QMouseEvent* ); + void mouseMoveEvent( QMouseEvent* ); + void keyPressEvent( QKeyEvent* ); + void focusInEvent( QFocusEvent* ); + void focusOutEvent( QFocusEvent* ); + +private: + int curRow; + int curCol; + int selRow; + int selCol; + int nCols; + int nRows; + bool smallStyle; + QWellArrayData *d; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QWellArray( const QWellArray & ); + QWellArray& operator=( const QWellArray & ); +#endif +}; + + + +// non-interface ... + + + +struct QWellArrayData { + QBrush *brush; +}; + +// NOT REVISED +/* WARNING, NOT + \class QWellArray qwellarray_p.h + \brief .... + + .... + + \ingroup advanced +*/ + +QWellArray::QWellArray( QWidget *parent, const char * name, bool popup ) + : QTableView( parent, name, + popup ? (WStyle_Customize|WStyle_Tool|WStyle_NoBorder) : 0 ) +{ + d = 0; + setFocusPolicy( StrongFocus ); + setBackgroundMode( PaletteButton ); + nCols = 7; + nRows = 7; + int w = 24; // cell width + int h = 21; // cell height + smallStyle = popup; + + if ( popup ) { + w = h = 18; + if ( style() == WindowsStyle ) + setFrameStyle( QFrame::WinPanel | QFrame::Raised ); + else + setFrameStyle( QFrame::Panel | QFrame::Raised ); + setMargin( 1 ); + setLineWidth( 2 ); + } + setNumCols( nCols ); + setNumRows( nRows ); + setCellWidth( w ); + setCellHeight( h ); + curCol = 0; + curRow = 0; + selCol = -1; + selRow = -1; + + if ( smallStyle ) + setMouseTracking( TRUE ); + setOffset( 5 , 10 ); + + resize( sizeHint() ); + +} + + +QSize QWellArray::sizeHint() const +{ + constPolish(); + int f = frameWidth() * 2; + int w = nCols * cellWidth() + f; + int h = nRows * cellHeight() + f; + return QSize( w, h ); +} + + +void QWellArray::paintCell( QPainter* p, int row, int col ) +{ + int w = cellWidth( col ); // width of cell in pixels + int h = cellHeight( row ); // height of cell in pixels + int b = 1; + + if ( !smallStyle ) + b = 3; + + const QColorGroup & g = colorGroup(); + p->setPen( QPen( black, 0, SolidLine ) ); + if ( !smallStyle && row ==selRow && col == selCol && + style() != MotifStyle ) { + int n = 2; + p->drawRect( n, n, w-2*n, h-2*n ); + } + + + if ( style() == WindowsStyle ) { + qDrawWinPanel( p, b, b , w - 2*b, h - 2*b, + g, TRUE ); + b += 2; + } else { + if ( smallStyle ) { + qDrawShadePanel( p, b, b , w - 2*b, h - 2*b, + g, TRUE, 2 ); + b += 2; + } else { + int t = ( row == selRow && col == selCol ) ? 2 : 0; + b -= t; + qDrawShadePanel( p, b, b , w - 2*b, h - 2*b, + g, TRUE, 2 ); + 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().drawFocusRect(p, QRect(0,0,w,h), g ); + } + } + drawContents( p, row, col, QRect(b, b, w - 2*b, h - 2*b) ); +} + +/*! + Pass-through to QTableView::drawContents() to avoid hiding. +*/ +void QWellArray::drawContents( QPainter *p ) +{ + QTableView::drawContents(p); +} + +/*! + Reimplement this function to change the contents of the well array. + */ +void QWellArray::drawContents( QPainter *p, int row, int col, const QRect &r ) +{ + + if ( d ) { + p->fillRect( r, d->brush[row*nCols+col] ); + } else { + p->fillRect( r, white ); + p->setPen( black ); + p->drawLine( r.topLeft(), r.bottomRight() ); + p->drawLine( r.topRight(), r.bottomLeft() ); + } +} + + +/*\reimp +*/ +void QWellArray::mousePressEvent( QMouseEvent* e ) +{ + // The current cell marker is set to the cell the mouse is pressed + // in. + QPoint pos = e->pos(); + setCurrent( findRow( pos.y() ), findCol( pos.x() ) ); +} + +/*\reimp +*/ +void QWellArray::mouseReleaseEvent( QMouseEvent* ) +{ + // The current cell marker is set to the cell the mouse is clicked + // in. + setSelected( curRow, curCol ); +} + + +/*\reimp +*/ +void QWellArray::mouseMoveEvent( QMouseEvent* e ) +{ + // The current cell marker is set to the cell the mouse is + // clicked in. + if ( smallStyle ) { + QPoint pos = e->pos(); + setCurrent( findRow( pos.y() ), findCol( pos.x() ) ); + } +} + +/* + Sets the cell currently having the focus. This is not necessarily + the same as the currently selected cell. +*/ + +void QWellArray::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 QWellArray::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() && parentWidget() && parentWidget()->inherits("QPopupMenu") ) + parentWidget()->close(); + +} + + + +/*!\reimp +*/ +void QWellArray::focusInEvent( QFocusEvent* ) +{ + updateCell( curRow, curCol ); +} + + +/*! + Sets the size of the well array to be \c rows cells by \c cols. + Resets any brush info set by setCellBrush(). + + Must be called by reimplementors. + */ +void QWellArray::setDimension( int rows, int cols ) +{ + nRows = rows; + nCols = cols; + if ( d ) { + if ( d->brush ) + delete[] d->brush; + delete d; + d = 0; + } + setNumCols( nCols ); + setNumRows( nRows ); +} + +void QWellArray::setCellBrush( int row, int col, const QBrush &b ) +{ + if ( !d ) { + d = new QWellArrayData; + d->brush = new QBrush[nRows*nCols]; + } + if ( row >= 0 && row < nRows && col >= 0 && col < nCols ) + d->brush[row*nCols+col] = b; +#ifdef CHECK_RANGE + else + qWarning( "QWellArray::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. +*/ + +QBrush QWellArray::cellBrush( int row, int col ) +{ + if ( d && row >= 0 && row < nRows && col >= 0 && col < nCols ) + return d->brush[row*nCols+col]; + return NoBrush; +} + + + +/*!\reimp +*/ + +void QWellArray::focusOutEvent( QFocusEvent* ) +{ + updateCell( curRow, curCol ); +} + +/*\reimp +*/ +void QWellArray::keyPressEvent( QKeyEvent* 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 + int edge = leftCell(); // find left edge + if ( curCol < edge ) // if we have moved off edge, + setLeftCell( edge - 1 ); // scroll view to rectify + } + break; + case Key_Right: // Correspondingly... + if( curCol < numCols()-1 ) { + setCurrent( curRow, curCol + 1); + int edge = lastColVisible(); + if ( curCol >= edge ) + setLeftCell( leftCell() + 1 ); + } + break; + case Key_Up: + if( curRow > 0 ) { + setCurrent( curRow - 1, curCol); + int edge = topCell(); + if ( curRow < edge ) + setTopCell( edge - 1 ); + } else if ( smallStyle ) + focusNextPrevChild( FALSE ); + break; + case Key_Down: + if( curRow < numRows()-1 ) { + setCurrent( curRow + 1, curCol); + int edge = lastRowVisible(); + if ( curRow >= edge ) + setTopCell( topCell() + 1 ); + } 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; + } + +} + +//////////// QWellArray END + +static bool initrgb = FALSE; +static QRgb stdrgb[6*8]; +static QRgb cusrgb[2*8]; + + +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 + QColorDialog. All color dialogs share the same custom colors. +*/ +int QColorDialog::customCount() +{ + return 2*8; +} + +/*! + Returns custom color number \a i as a QRgb. + */ +QRgb QColorDialog::customColor( int i ) +{ + initRGB(); + if ( i < 0 || i >= customCount() ) { +#ifdef CHECK_RANGE + qWarning( "QColorDialog::customColor() index %d out of range", i ); +#endif + i = 0; + } + return cusrgb[i]; +} + +/*! + Sets custom color number \a i to the QRgb value \a c. +*/ +void QColorDialog::setCustomColor( int i, QRgb c ) +{ + initRGB(); + if ( i < 0 || i >= customCount() ) { +#ifdef CHECK_RANGE + qWarning( "QColorDialog::customColor() index %d out of range", i ); +#endif + return; + } + cusrgb[i] = c; +} + +static inline void rgb2hsv( QRgb rgb, int&h, int&s, int&v ) +{ + QColor c; + c.setRgb( rgb ); + c.getHsv(h,s,v); +} + +class QColorWell : public QWellArray +{ +public: + QColorWell( QWidget *parent, int r, int c, QRgb *vals ) + :QWellArray( parent, "" ), values( vals ), mousePressed( FALSE ), oldCurrent( -1, -1 ) + { setDimension(r,c); setWFlags( WResizeNoErase ); } + QSizePolicy sizePolicy() const; + +protected: + void drawContents( QPainter *, int row, int col, const QRect& ); + void drawContents( QPainter *p ) { QWellArray::drawContents(p); } + void mousePressEvent( QMouseEvent *e ); + void mouseMoveEvent( QMouseEvent *e ); + void mouseReleaseEvent( QMouseEvent *e ); +#ifndef QT_NO_DRAGANDDROP + void dragEnterEvent( QDragEnterEvent *e ); + void dragLeaveEvent( QDragLeaveEvent *e ); + void dragMoveEvent( QDragMoveEvent *e ); + void dropEvent( QDropEvent *e ); +#endif + +private: + QRgb *values; + bool mousePressed; + QPoint pressPos; + QPoint oldCurrent; + +}; + +QSizePolicy QColorWell::sizePolicy() const +{ + return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); +} + +void QColorWell::drawContents( QPainter *p, int row, int col, const QRect &r ) +{ + int i = row + col*numRows(); + p->fillRect( r, QColor( values[i] ) ); +} + +void QColorWell::mousePressEvent( QMouseEvent *e ) +{ + oldCurrent = QPoint( selectedRow(), selectedColumn() ); + QWellArray::mousePressEvent( e ); + mousePressed = TRUE; + pressPos = e->pos(); +} + +void QColorWell::mouseMoveEvent( QMouseEvent *e ) +{ + QWellArray::mouseMoveEvent( e ); +#ifndef QT_NO_DRAGANDDROP + if ( !mousePressed ) + return; + if ( ( pressPos - e->pos() ).manhattanLength() > QApplication::startDragDistance() ) { + setCurrent( oldCurrent.x(), oldCurrent.y() ); + int i = findRow( e->y() ) + findCol( e->x() ) * numRows(); + QColor col( values[ i ] ); + QColorDrag *drg = new QColorDrag( col, this ); + QPixmap pix( cellWidth(), cellHeight() ); + pix.fill( col ); + QPainter 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 QColorWell::dragEnterEvent( QDragEnterEvent *e ) +{ + setFocus(); + if ( QColorDrag::canDecode( e ) ) + e->accept(); + else + e->ignore(); +} + +void QColorWell::dragLeaveEvent( QDragLeaveEvent * ) +{ + if ( hasFocus() ) + parentWidget()->setFocus(); +} + +void QColorWell::dragMoveEvent( QDragMoveEvent *e ) +{ + if ( QColorDrag::canDecode( e ) ) { + setCurrent( findRow( e->pos().y() ), findCol( e->pos().x() ) ); + e->accept(); + } else + e->ignore(); +} + +void QColorWell::dropEvent( QDropEvent *e ) +{ + if ( QColorDrag::canDecode( e ) ) { + int i = findRow( e->pos().y() ) + findCol( e->pos().x() ) * numRows(); + QColor col; + QColorDrag::decode( e, col ); + values[ i ] = col.rgb(); + repaint( FALSE ); + e->accept(); + } else { + e->ignore(); + } +} + +#endif // QT_NO_DRAGANDDROP + +void QColorWell::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( !mousePressed ) + return; + QWellArray::mouseReleaseEvent( e ); + mousePressed = FALSE; +} + +class QColorPicker : public QFrame +{ + Q_OBJECT +public: + QColorPicker(QWidget* parent=0, const char* name=0); + ~QColorPicker(); + +public slots: + void setCol( int h, int s ); + +signals: + void newCol( int h, int s ); + +protected: + QSize sizeHint() const; + QSizePolicy sizePolicy() const; + void drawContents(QPainter* p); + void mouseMoveEvent( QMouseEvent * ); + void mousePressEvent( QMouseEvent * ); + +private: + int hue; + int sat; + + QPoint colPt(); + int huePt( const QPoint &pt ); + int satPt( const QPoint &pt ); + void setCol( const QPoint &pt ); + + QPixmap *pix; +}; + +static int pWidth = 200; +static int pHeight = 200; + +class QColorLuminancePicker : public QWidget +{ + Q_OBJECT +public: + QColorLuminancePicker(QWidget* parent=0, const char* name=0); + ~QColorLuminancePicker(); + +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: +// QSize sizeHint() const; +// QSizePolicy sizePolicy() const; + void paintEvent( QPaintEvent*); + void mouseMoveEvent( QMouseEvent * ); + void mousePressEvent( QMouseEvent * ); + +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 ); + + QPixmap *pix; +}; + + +int QColorLuminancePicker::y2val( int y ) +{ + int d = height() - 2*coff - 1; + return 255 - (y - coff)*255/d; +} + +int QColorLuminancePicker::val2y( int v ) +{ + int d = height() - 2*coff - 1; + return coff + (255-v)*d/255; +} + +QColorLuminancePicker::QColorLuminancePicker(QWidget* parent, + const char* name) + :QWidget( parent, name ) +{ + hue = 100; val = 100; sat = 100; + pix = 0; + // setBackgroundMode( NoBackground ); +} + +QColorLuminancePicker::~QColorLuminancePicker() +{ + delete pix; +} + +void QColorLuminancePicker::mouseMoveEvent( QMouseEvent *m ) +{ + setVal( y2val(m->y()) ); +} +void QColorLuminancePicker::mousePressEvent( QMouseEvent *m ) +{ + setVal( y2val(m->y()) ); +} + +void QColorLuminancePicker::setVal( int v ) +{ + if ( val == v ) + return; + val = QMAX( 0, QMIN(v,255)); + delete pix; pix=0; + repaint( FALSE ); //### + emit newHsv( hue, sat, val ); +} + +//receives from a hue,sat chooser and relays. +void QColorLuminancePicker::setCol( int h, int s ) +{ + setCol( h, s, val ); + emit newHsv( h, s, val ); +} + +void QColorLuminancePicker::paintEvent( QPaintEvent * ) +{ + int w = width() - 5; + + QRect 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; + QImage img( wi, hi, 32 ); + int y; + for ( y = 0; y < hi; y++ ) { + QColor c( hue, sat, y2val(y+coff), QColor::Hsv ); + QRgb r = c.rgb(); + int x; + for ( x = 0; x < wi; x++ ) + img.setPixel( x, y, r ); + } + pix = new QPixmap; + pix->convertFromImage(img); + } + QPainter p(this); + p.drawPixmap( 1, coff, *pix ); + QColorGroup g = colorGroup(); + qDrawShadePanel( &p, r, g, TRUE ); + p.setPen( g.foreground() ); + p.setBrush( g.foreground() ); + QPointArray 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 QColorLuminancePicker::setCol( int h, int s , int v ) +{ + val = v; + hue = h; + sat = s; + delete pix; pix=0; + repaint( FALSE );//#### +} + +QPoint QColorPicker::colPt() +{ return QPoint( (360-hue)*(pWidth-1)/360, (255-sat)*(pHeight-1)/255 ); } +int QColorPicker::huePt( const QPoint &pt ) +{ return 360 - pt.x()*360/(pWidth-1); } +int QColorPicker::satPt( const QPoint &pt ) +{ return 255 - pt.y()*255/(pHeight-1) ; } +void QColorPicker::setCol( const QPoint &pt ) +{ setCol( huePt(pt), satPt(pt) ); } + +QColorPicker::QColorPicker(QWidget* parent, const char* name ) + : QFrame( parent, name ) +{ + hue = 0; sat = 0; + setCol( 150, 255 ); + + QImage img( pWidth, pHeight, 32 ); + int x,y; + for ( y = 0; y < pHeight; y++ ) + for ( x = 0; x < pWidth; x++ ) { + QPoint p( x, y ); + img.setPixel( x, y, QColor(huePt(p), satPt(p), + 200, QColor::Hsv).rgb() ); + } + pix = new QPixmap; + pix->convertFromImage(img); + setBackgroundMode( NoBackground ); +} + +QColorPicker::~QColorPicker() +{ + delete pix; +} + +QSize QColorPicker::sizeHint() const +{ + return QSize( pWidth + 2*frameWidth(), pHeight + 2*frameWidth() ); +} + +QSizePolicy QColorPicker::sizePolicy() const +{ + return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); +} + +void QColorPicker::setCol( int h, int s ) +{ + int nhue = QMIN( QMAX(0,h), 360 ); + int nsat = QMIN( QMAX(0,s), 255); + if ( nhue == hue && nsat == sat ) + return; + QRect r( colPt(), QSize(20,20) ); + hue = nhue; sat = nsat; + r = r.unite( QRect( colPt(), QSize(20,20) ) ); + r.moveBy( contentsRect().x()-9, contentsRect().y()-9 ); + // update( r ); + repaint( r, FALSE ); +} + +void QColorPicker::mouseMoveEvent( QMouseEvent *m ) +{ + QPoint p = m->pos() - contentsRect().topLeft(); + setCol( p ); + emit newCol( hue, sat ); +} + +void QColorPicker::mousePressEvent( QMouseEvent *m ) +{ + QPoint p = m->pos() - contentsRect().topLeft(); + setCol( p ); + emit newCol( hue, sat ); +} + +void QColorPicker::drawContents(QPainter* p) +{ + QRect r = contentsRect(); + + p->drawPixmap( r.topLeft(), *pix ); + QPoint pt = colPt() + r.topLeft(); + p->setPen( QPen(black) ); + + p->fillRect( pt.x()-9, pt.y(), 20, 2, black ); + p->fillRect( pt.x(), pt.y()-9, 2, 20, black ); + +} + +class QColorShowLabel; + + + +class QColIntValidator: public QIntValidator +{ +public: + QColIntValidator( int bottom, int top, + QWidget * parent, const char *name = 0 ) + :QIntValidator( bottom, top, parent, name ) {} + + QValidator::State validate( QString &, int & ) const; +}; + +QValidator::State QColIntValidator::validate( QString &s, int &pos ) const +{ + State state = QIntValidator::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 QColNumLineEdit : public QLineEdit +{ +public: + QColNumLineEdit( QWidget *parent, const char* name = 0 ) + : QLineEdit( parent, name ) { setMaxLength( 3 );} + QSize sizeHint() const { + return QSize( 30, //##### + QLineEdit::sizeHint().height() ); } + void setNum( int i ) { + QString s; + s.setNum(i); + bool block = signalsBlocked(); + blockSignals(TRUE); + setText( s ); + blockSignals(block); + } + int val() const { return text().toInt(); } +}; + + +class QColorShower : public QWidget +{ + Q_OBJECT +public: + QColorShower( QWidget *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 ); + + + QRgb currentColor() const { return curCol; } + +public slots: + void setRgb( QRgb rgb ); + +signals: + void newCol( QRgb rgb ); +private slots: + void rgbEd(); + void hsvEd(); +private: + void showCurrentColor(); + int hue, sat, val; + QRgb curCol; + QColNumLineEdit *hEd; + QColNumLineEdit *sEd; + QColNumLineEdit *vEd; + QColNumLineEdit *rEd; + QColNumLineEdit *gEd; + QColNumLineEdit *bEd; + QColNumLineEdit *alphaEd; + QLabel *alphaLab; + QColorShowLabel *lab; + bool rgbOriginal; +}; + +class QColorShowLabel : public QFrame +{ + Q_OBJECT + +public: + QColorShowLabel( QWidget *parent ) :QFrame( parent ) { + setFrameStyle( QFrame::Panel|QFrame::Sunken ); + setBackgroundMode( PaletteBackground ); + setAcceptDrops( TRUE ); + mousePressed = FALSE; + } + void setColor( QColor c ) { col = c; } + +signals: + void colorDropped( QRgb ); + +protected: + void drawContents( QPainter *p ); + void mousePressEvent( QMouseEvent *e ); + void mouseMoveEvent( QMouseEvent *e ); + void mouseReleaseEvent( QMouseEvent *e ); +#ifndef QT_NO_DRAGANDDROP + void dragEnterEvent( QDragEnterEvent *e ); + void dragLeaveEvent( QDragLeaveEvent *e ); + void dropEvent( QDropEvent *e ); +#endif + +private: + QColor col; + bool mousePressed; + QPoint pressPos; + +}; + +void QColorShowLabel::drawContents( QPainter *p ) +{ + p->fillRect( contentsRect(), col ); +} + +void QColorShower::showAlpha( bool b ) +{ + if ( b ) { + alphaLab->show(); + alphaEd->show(); + } else { + alphaLab->hide(); + alphaEd->hide(); + } +} + +void QColorShowLabel::mousePressEvent( QMouseEvent *e ) +{ + mousePressed = TRUE; + pressPos = e->pos(); +} + +void QColorShowLabel::mouseMoveEvent( QMouseEvent *e ) +{ +#ifndef QT_NO_DRAGANDDROP + if ( !mousePressed ) + return; + if ( ( pressPos - e->pos() ).manhattanLength() > QApplication::startDragDistance() ) { + QColorDrag *drg = new QColorDrag( col, this ); + QPixmap pix( 30, 20 ); + pix.fill( col ); + QPainter 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 QColorShowLabel::dragEnterEvent( QDragEnterEvent *e ) +{ + if ( QColorDrag::canDecode( e ) ) + e->accept(); + else + e->ignore(); +} + +void QColorShowLabel::dragLeaveEvent( QDragLeaveEvent * ) +{ +} + +void QColorShowLabel::dropEvent( QDropEvent *e ) +{ + if ( QColorDrag::canDecode( e ) ) { + QColorDrag::decode( e, col ); + repaint( FALSE ); + emit colorDropped( col.rgb() ); + e->accept(); + } else { + e->ignore(); + } +} +#endif // QT_NO_DRAGANDDROP + +void QColorShowLabel::mouseReleaseEvent( QMouseEvent * ) +{ + if ( !mousePressed ) + return; + mousePressed = FALSE; +} + +QColorShower::QColorShower( QWidget *parent, const char *name ) + :QWidget( parent, name) +{ + curCol = qRgb( -1, -1, -1 ); + QColIntValidator *val256 = new QColIntValidator( 0, 255, this ); + QColIntValidator *val360 = new QColIntValidator( 0, 360, this ); + + QGridLayout *gl = new QGridLayout( this, 1, 1, 6 ); + lab = new QColorShowLabel( this ); + lab->setMinimumWidth( 60 ); //### + gl->addMultiCellWidget(lab, 0,-1,0,0); + connect( lab, SIGNAL( colorDropped(QRgb) ), + this, SIGNAL( newCol(QRgb) ) ); + connect( lab, SIGNAL( colorDropped(QRgb) ), + this, SLOT( setRgb(QRgb) ) ); + + hEd = new QColNumLineEdit( this ); + hEd->setValidator( val360 ); + QLabel *l = new QLabel( hEd, QColorDialog::tr("Hu&e:"), this ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 0, 1 ); + gl->addWidget( hEd, 0, 2 ); + + sEd = new QColNumLineEdit( this ); + sEd->setValidator( val256 ); + l = new QLabel( sEd, QColorDialog::tr("&Sat:"), this ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 1, 1 ); + gl->addWidget( sEd, 1, 2 ); + + vEd = new QColNumLineEdit( this ); + vEd->setValidator( val256 ); + l = new QLabel( vEd, QColorDialog::tr("&Val:"), this ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 2, 1 ); + gl->addWidget( vEd, 2, 2 ); + + rEd = new QColNumLineEdit( this ); + rEd->setValidator( val256 ); + l = new QLabel( rEd, QColorDialog::tr("&Red:"), this ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 0, 3 ); + gl->addWidget( rEd, 0, 4 ); + + gEd = new QColNumLineEdit( this ); + gEd->setValidator( val256 ); + l = new QLabel( gEd, QColorDialog::tr("&Green:"), this ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 1, 3 ); + gl->addWidget( gEd, 1, 4 ); + + bEd = new QColNumLineEdit( this ); + bEd->setValidator( val256 ); + l = new QLabel( bEd, QColorDialog::tr("Bl&ue:"), this ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 2, 3 ); + gl->addWidget( bEd, 2, 4 ); + + alphaEd = new QColNumLineEdit( this ); + alphaEd->setValidator( val256 ); + alphaLab = new QLabel( alphaEd, QColorDialog::tr("A&lpha channel:"), this ); + 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 QString&)), this, SLOT(hsvEd()) ); + connect( sEd, SIGNAL(textChanged(const QString&)), this, SLOT(hsvEd()) ); + connect( vEd, SIGNAL(textChanged(const QString&)), this, SLOT(hsvEd()) ); + + connect( rEd, SIGNAL(textChanged(const QString&)), this, SLOT(rgbEd()) ); + connect( gEd, SIGNAL(textChanged(const QString&)), this, SLOT(rgbEd()) ); + connect( bEd, SIGNAL(textChanged(const QString&)), this, SLOT(rgbEd()) ); +} + +void QColorShower::showCurrentColor() +{ + lab->setColor( currentColor() ); + lab->repaint(FALSE); //### +} + +void QColorShower::rgbEd() +{ + rgbOriginal = TRUE; + 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 QColorShower::hsvEd() +{ + rgbOriginal = FALSE; + hue = hEd->val(); + sat = sEd->val(); + val = vEd->val(); + + curCol = QColor( hue, sat, val, QColor::Hsv ).rgb(); + + rEd->setNum( qRed(currentColor()) ); + gEd->setNum( qGreen(currentColor()) ); + bEd->setNum( qBlue(currentColor()) ); + + showCurrentColor(); + emit newCol( currentColor() ); +} + +void QColorShower::setRgb( QRgb 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 QColorShower::setHsv( int h, int s, int v ) +{ + rgbOriginal = FALSE; + hue = h; val = v; sat = s; //Range check### + curCol = QColor( hue, sat, val, QColor::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 QColorDialogPrivate : public QObject +{ +Q_OBJECT +public: + QColorDialogPrivate( QColorDialog *p ); + QRgb currentColor() const { return cs->currentColor(); } + void setCurrentColor( QRgb rgb ); + + int currentAlpha() const { return cs->currentAlpha(); } + void setCurrentAlpha( int a ) { cs->setCurrentAlpha( a ); } + void showAlpha( bool b ) { cs->showAlpha( b ); } + +private slots: + void addCustom(); + + void newHsv( int h, int s, int v ); + void newColorTypedIn( QRgb rgb ); + void newCustom( int, int ); + void newStandard( int, int ); +private: + QColorPicker *cp; + QColorLuminancePicker *lp; + QWellArray *custom; + QWellArray *standard; + QColorShower *cs; + int nextCust; + bool compact; +}; + +//sets all widgets to display h,s,v +void QColorDialogPrivate::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 QColorDialogPrivate::setCurrentColor( QRgb rgb ) +{ + cs->setRgb( rgb ); + newColorTypedIn( rgb ); +} + +//sets all widgets exept cs to display rgb +void QColorDialogPrivate::newColorTypedIn( QRgb rgb ) +{ + int h, s, v; + rgb2hsv(rgb, h, s, v ); + cp->setCol( h, s ); + lp->setCol( h, s, v); +} + +void QColorDialogPrivate::newCustom( int r, int c ) +{ + int i = r+2*c; + setCurrentColor( cusrgb[i] ); + nextCust = i; + standard->setSelected(-1,-1); +} + +void QColorDialogPrivate::newStandard( int r, int c ) +{ + setCurrentColor( stdrgb[r+c*6] ); + custom->setSelected(-1,-1); +} + +QColorDialogPrivate::QColorDialogPrivate( QColorDialog *dialog ) : + QObject(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; + QHBoxLayout *topLay = new QHBoxLayout( dialog, border, 6 ); + QVBoxLayout *leftLay = 0; + + if ( !compact ) + leftLay = new QVBoxLayout( topLay ); + + initRGB(); + + if ( !compact ) { + standard = new QColorWell( dialog, 6, 8, stdrgb ); + standard->setCellSize( 28, 24 ); + QLabel * lab = new QLabel( standard, + QColorDialog::tr( "&Basic colors"), dialog ); + connect( standard, SIGNAL(selected(int,int)), SLOT(newStandard(int,int))); + leftLay->addWidget( lab ); + leftLay->addWidget( standard ); + + + leftLay->addStretch(); + + custom = new QColorWell( dialog, 2, 8, cusrgb ); + custom->setCellSize( 28, 24 ); + custom->setAcceptDrops( TRUE ); + + connect( custom, SIGNAL(selected(int,int)), SLOT(newCustom(int,int))); + lab = new QLabel( custom, QColorDialog::tr( "&Custom colors") , dialog ); + leftLay->addWidget( lab ); + leftLay->addWidget( custom ); + + QPushButton *custbut = + new QPushButton( QColorDialog::tr("&Define Custom Colors >>"), + dialog ); + custbut->setEnabled( FALSE ); + leftLay->addWidget( custbut ); + } else { + // better color picker size for small displays + pWidth = 150; + pHeight = 100; + } + + QVBoxLayout *rightLay = new QVBoxLayout( topLay ); + + QHBoxLayout *pickLay = new QHBoxLayout( rightLay ); + + + QVBoxLayout *cLay = new QVBoxLayout( pickLay ); + cp = new QColorPicker( dialog ); + cp->setFrameStyle( QFrame::Panel + QFrame::Sunken ); + cLay->addSpacing( lumSpace ); + cLay->addWidget( cp ); + cLay->addSpacing( lumSpace ); + + lp = new QColorLuminancePicker( dialog ); + 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 QColorShower( dialog ); + connect( cs, SIGNAL(newCol(QRgb)), this, SLOT(newColorTypedIn(QRgb))); + rightLay->addWidget( cs ); + + QHBoxLayout *buttons; + if ( compact ) + buttons = new QHBoxLayout( rightLay ); + else + buttons = new QHBoxLayout( leftLay ); + + QPushButton *ok, *cancel; + ok = new QPushButton( QColorDialog::tr("OK"), dialog ); + connect( ok, SIGNAL(clicked()), dialog, SLOT(accept()) ); + ok->setDefault(TRUE); + cancel = new QPushButton( QColorDialog::tr("Cancel"), dialog ); + connect( cancel, SIGNAL(clicked()), dialog, SLOT(reject()) ); + buttons->addWidget( ok ); + buttons->addWidget( cancel ); + buttons->addStretch(); + + if ( !compact ) { + QPushButton *addCusBt = new QPushButton( + QColorDialog::tr("&Add To Custom Colors"), + dialog ); + rightLay->addWidget( addCusBt ); + connect( addCusBt, SIGNAL(clicked()), this, SLOT(addCustom()) ); + } +} + +void QColorDialogPrivate::addCustom() +{ + cusrgb[nextCust] = cs->currentColor(); + custom->repaint( FALSE ); //### + nextCust = (nextCust+1) % 16; +} + + +// BEING REVISED: jo +/*! + \class QColorDialog qcolordialog.h + \brief The QColorDialog class provides a dialog widget for specifying colors. + \ingroup dialogs + + The color dialog's function is to allow users to choose colors - + for instance, you might use this in a drawing program to allow the + user to set the brush color. + + This version of Qt only provides modal color dialogs. The static + getColor() function shows the dialog and allows the user to specify a color, + while getRgba() does the same but 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 customColor() to get them. + + +*/ + +/*! + Constructs a default color dialog. Use setColor() for setting an initial value. + + \sa getColor() +*/ + +QColorDialog::QColorDialog(QWidget* parent, const char* name, bool modal) : + QDialog(parent, name, modal ) +{ + setSizeGripEnabled( TRUE ); + d = new QColorDialogPrivate( this ); +} + + +/*! + Pops up a modal color dialog letting the user choose a color and returns + that color. The color is initially set to \a initial. Returns an \link QColor::isValid() invalid\endlink color if the user cancels + the dialog. All colors allocated by the dialog will be deallocated + before this function returns. +*/ + +QColor QColorDialog::getColor( QColor initial, QWidget *parent, + const char *name ) +{ + int allocContext = QColor::enterAllocContext(); + QColorDialog *dlg = new QColorDialog( parent, name, TRUE ); //modal + if ( parent && parent->icon() && !parent->icon()->isNull() ) + dlg->setIcon( *parent->icon() ); + else if ( qApp->mainWidget() && qApp->mainWidget()->icon() && !qApp->mainWidget()->icon()->isNull() ) + dlg->setIcon( *qApp->mainWidget()->icon() ); + + dlg->setCaption( QColorDialog::tr( "Select color" ) ); + dlg->setColor( initial ); + int resultCode = dlg->exec(); + QColor::leaveAllocContext(); + QColor result; + if ( resultCode == QDialog::Accepted ) + result = dlg->color(); + QColor::destroyAllocContext(allocContext); + delete dlg; + return result; +} + + +/*! + Pops up a modal color dialog, letting the user choose a color and an + alpha channel value. The color+alpha is initially set to \a initial. + + If \a ok is non-null, \c *ok is set to TRUE if the user clicked OK, + and FALSE if the user clicked Cancel. + + If the user clicks Cancel the \a initial value is returned. +*/ + +QRgb QColorDialog::getRgba( QRgb initial, bool *ok, + QWidget *parent, const char* name ) +{ + int allocContext = QColor::enterAllocContext(); + QColorDialog *dlg = new QColorDialog( parent, name, TRUE ); //modal + dlg->setColor( initial ); + dlg->setSelectedAlpha( qAlpha(initial) ); + int resultCode = dlg->exec(); + QColor::leaveAllocContext(); + QRgb result = initial; + if ( resultCode == QDialog::Accepted ) { + QRgb c = dlg->color().rgb(); + int alpha = dlg->selectedAlpha(); + result = qRgba( qRed(c), qGreen(c), qBlue(c), alpha ); + } + if ( ok ) + *ok = resultCode == QDialog::Accepted; + + QColor::destroyAllocContext(allocContext); + delete dlg; + return result; +} + + + + + +/*! + Returns the color currently selected in the dialog. + + \sa setColor() +*/ + +QColor QColorDialog::color() const +{ + return QColor(d->currentColor()); +} + + +/*! Destructs the dialog and frees any memory it allocated. + +*/ + +QColorDialog::~QColorDialog() +{ + //d inherits QObject, so it is deleted by Qt. +} + + +/*! + Sets the color shown in the dialog to \a c. + + \sa color() +*/ + +void QColorDialog::setColor( QColor c ) +{ + d->setCurrentColor( c.rgb() ); +} + + + + +/*! + Sets the initial alpha channel value to \a a, and show the alpha channel + entry box. +*/ + +void QColorDialog::setSelectedAlpha( int a ) +{ + d->showAlpha( TRUE ); + d->setCurrentAlpha( a ); +} + + +/*! + Returns the value selected for the alpha channel. +*/ + +int QColorDialog::selectedAlpha() const +{ + return d->currentAlpha(); +} + + diff --git a/libqtaux/qcolordialog.h b/libqtaux/qcolordialog.h new file mode 100644 index 0000000..89c6283 --- a/dev/null +++ b/libqtaux/qcolordialog.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QColorDialog class +** +** Created : 990222 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the dialogs module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QCOLORDIALOG_H +#define QCOLORDIALOG_H + +#ifndef QT_H +#include +#endif // QT_H + +class QColorDialogPrivate; + +class Q_EXPORT QColorDialog : public QDialog +{ + Q_OBJECT + +public: + static QColor getColor( QColor, QWidget *parent=0, const char* name=0 ); // ### 3.0: make const QColor& + static QRgb getRgba( QRgb, bool* ok = 0, + QWidget *parent=0, const char* name=0 ); + + + static int customCount(); + static QRgb customColor( int ); + static void setCustomColor( int, QRgb ); + +private: + ~QColorDialog(); + + QColorDialog( QWidget* parent=0, const char* name=0, bool modal=FALSE ); + void setColor( QColor ); // ### 3.0: make const QColor& + QColor color() const; + +private: + void setSelectedAlpha( int ); + int selectedAlpha() const; + + void showCustom( bool=TRUE ); +private: + QColorDialogPrivate *d; + friend class QColorDialogPrivate; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QColorDialog( const QColorDialog & ); + QColorDialog& operator=( const QColorDialog & ); +#endif +}; + +#endif diff --git a/libqtaux/qinputdialog.cpp b/libqtaux/qinputdialog.cpp new file mode 100644 index 0000000..821c74d --- a/dev/null +++ b/libqtaux/qinputdialog.cpp @@ -0,0 +1,493 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QInputDialog class +** +** Created : 991212 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the dialogs module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qinputdialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QInputDialogPrivate +{ +public: + friend class QInputDialog; + QLineEdit *lineEdit; + QSpinBox *spinBox; + QComboBox *comboBox, *editComboBox; + QPushButton *ok; + QWidgetStack *stack; + QInputDialog::Type type; +}; + +/*! + \class QInputDialog qinputdialog.h + \brief A convenience dialog to get a simple input from the user + \ingroup dialogs + + The QInputDialog is a simple dialog which can be used if you + need a simple input from the user. This can be text, a number or + an item from a list. Also a label has to be set to tell the user + what he/she should input. + + In this Qt version only the 4 static convenience functions + getText(), getInteger(), getDouble() and getItem() of QInputDialog + are available. + + Use it like this: + + \code + bool ok = FALSE; + QString text = QInputDialog::getText( tr( "Make an input" ), tr( "Please enter your name" ), QString::null, &ok, this ); + if ( ok && !text.isEmpty() ) + ;// user entered something and pressed ok + else + ;// user entered nothing or pressed cancel + \endcode + + There are more static convenience methods! + + \sa getText(), getInteger(), getDouble(), getItem() +*/ + +/*! + \enum QInputDialog::Type + + This enum type specifies the type of the dialog + (which kind of input can be done): + +
    +
  • \c LineEdit - A QLineEdit is used for taking the input, so a textual or + (e.g. using a QValidator) a numerical input can be done. Using lineEdit() + the QLineEdit can be accessed. +
  • \c SpinBox - A QSpinBox is used for taking the input, so a decimal + input can be done. Using spinBox() the QSpinBox can be accessed. +
  • \c ComboBox - A read-only QComboBox is used for taking the input, + so one item of a list can be chosen. Using comboBox() the QComboBox + can be accessed. +
  • \c EditableComboBox - An editable QComboBox is used for taking the input, + so either one item of a list can be chosen or a text can be entered. Using + editableComboBox() the QComboBox can be accessed. +
+*/ + +/*! + Constructs the dialog. \a label is the text which is shown to the user (it should mention + to the user what he/she should input), \a parent the parent widget of the dialog, \a name + the name of it and if you set \a modal to TRUE, the dialog pops up modally, else it pops + up modeless. With \a type you specify the type of the dialog. + + \sa getText(), getInteger(), getDouble(), getItem() +*/ + +QInputDialog::QInputDialog( const QString &label, QWidget* parent, const char* name, + bool modal, Type type) + : QDialog( parent, name, modal ) +{ + if ( parent && parent->icon() &&!parent->icon()->isNull() ) + setIcon( *parent->icon() ); + else if ( qApp->mainWidget() && qApp->mainWidget()->icon() && !qApp->mainWidget()->icon()->isNull() ) + QDialog::setIcon( *qApp->mainWidget()->icon() ); + + d = new QInputDialogPrivate; + d->lineEdit = 0; + d->spinBox = 0; + d->comboBox = 0; + + QVBoxLayout *vbox = new QVBoxLayout( this, 6, 6 ); + + QLabel* l = new QLabel( label, this ); + vbox->addWidget( l ); + + d->stack = new QWidgetStack( this ); + vbox->addWidget( d->stack ); + d->lineEdit = new QLineEdit( d->stack ); + d->spinBox = new QSpinBox( d->stack ); + d->comboBox = new QComboBox( FALSE, d->stack ); + d->editComboBox = new QComboBox( TRUE, d->stack ); + + QHBoxLayout *hbox = new QHBoxLayout( 6 ); + vbox->addLayout( hbox, AlignRight ); + + d->ok = new QPushButton( tr( "&OK" ), this ); + d->ok->setDefault( TRUE ); + QPushButton *cancel = new QPushButton( tr( "&Cancel" ), this ); + + QSize bs( d->ok->sizeHint() ); + if ( cancel->sizeHint().width() > bs.width() ) + bs.setWidth( cancel->sizeHint().width() ); + + d->ok->setFixedSize( bs ); + cancel->setFixedSize( bs ); + + hbox->addWidget( new QWidget( this ) ); + hbox->addWidget( d->ok ); + hbox->addWidget( cancel ); + + connect( d->lineEdit, SIGNAL( returnPressed() ), + this, SLOT( tryAccept() ) ); + connect( d->lineEdit, SIGNAL( textChanged(const QString&) ), + this, SLOT( textChanged(const QString&) ) ); + + connect( d->ok, SIGNAL( clicked() ), this, SLOT( accept() ) ); + connect( cancel, SIGNAL( clicked() ), this, SLOT( reject() ) ); + + resize( QMAX( sizeHint().width(), 400 ), sizeHint().height() ); + + setType( type ); +} + +/*! + Returns the line edit, which is used in the LineEdit mode +*/ + +QLineEdit *QInputDialog::lineEdit() const +{ + return d->lineEdit; +} + +/*! + Returns the spinbox, which is used in the SpinBox mode +*/ + +QSpinBox *QInputDialog::spinBox() const +{ + return d->spinBox; +} + +/*! + Returns the combobox, which is used in the ComboBox mode +*/ + +QComboBox *QInputDialog::comboBox() const +{ + return d->comboBox; +} + +/*! + Returns the combobox, which is used in the EditableComboBox mode +*/ + +QComboBox *QInputDialog::editableComboBox() const +{ + return d->editComboBox; +} + +/*! + Sets the input type of the dialog to \a t. +*/ + +void QInputDialog::setType( Type t ) +{ + switch ( t ) { + case LineEdit: + d->stack->raiseWidget( d->lineEdit ); + d->lineEdit->setFocus(); + break; + case SpinBox: + d->stack->raiseWidget( d->spinBox ); + d->spinBox->setFocus(); + break; + case ComboBox: + d->stack->raiseWidget( d->comboBox ); + d->comboBox->setFocus(); + break; + case EditableComboBox: + d->stack->raiseWidget( d->editComboBox ); + d->editComboBox->setFocus(); + break; + } + + d->type = t; +} + +/*! + Returns the input type of the dialog. + + \sa setType() +*/ + +QInputDialog::Type QInputDialog::type() const +{ + return d->type; +} + +/*! + Destructor. +*/ + +QInputDialog::~QInputDialog() +{ + delete d; +} + +/*! + Static convenience function to get a textual input from the user. \a caption is the text + which is displayed in the title bar of the dialog. \a label is the text which + is shown to the user (it should mention to the user what he/she should input), \a text + the default text which will be initially set to the line edit, \a ok a pointer to + a bool which will be (if not 0!) set to TRUE if the user pressed ok or to FALSE if the + user pressed cancel, \a parent the parent widget of the dialog and \a name + the name of it. The dialogs pops up modally! + + This method returns the text which has been entered in the line edit. + + You will use this static method like this: + + \code + bool ok = FALSE; + QString text = QInputDialog::getText( tr( "Please enter your name" ), QString::null, &ok, this ); + if ( ok && !text.isEmpty() ) + ;// user entered something and pressed ok + else + ;// user entered nothing or pressed cancel + \endcode +*/ + +QString QInputDialog::getText( const QString &caption, const QString &label, const QString &text, + bool *ok, QWidget *parent, const char *name ) +{ + return getText( caption, label, QLineEdit::Normal, text, ok, parent, name ); +} + +/*! + Like above, but accepts an a \a mode which the line edit will use to display text. + + \sa getText() +*/ + +QString QInputDialog::getText( const QString &caption, const QString &label, QLineEdit::EchoMode mode, + const QString &text, bool *ok, QWidget *parent, const char *name ) +{ + QInputDialog *dlg = new QInputDialog( label, parent, name, TRUE, LineEdit ); + dlg->setCaption( caption ); + dlg->lineEdit()->setText( text ); + dlg->lineEdit()->setEchoMode( mode ); + if ( !text.isEmpty() ) + dlg->lineEdit()->selectAll(); + + bool ok_ = FALSE; + QString result; + ok_ = dlg->exec() == QDialog::Accepted; + if ( ok ) + *ok = ok_; + if ( ok_ ) + result = dlg->lineEdit()->text(); + + delete dlg; + return result; +} + +/*! + Static convenience function to get an integral input from the user. \a caption is the text + which is displayed in the title bar of the dialog. \a label is the text which + is shown to the user (it should mention to the user what he/she should input), \a num + the default number which will be initially set to the spinbox, \a from and \a to the + range in which the entered number has to be, \a step the step in which the number can + be increased/decreased by the spinbox, \a ok a pointer to + a bool which will be (if not 0!) set to TRUE if the user pressed ok or to FALSE if the + user pressed cancel, \a parent the parent widget of the dialog and \a name + the name of it. The dialogs pops up modally! + + This method returns the number which has been entered by the user. + + You will use this static method like this: + + \code + bool ok = FALSE; + int res = QInputDialog::getInteger( tr( "Please enter a number" ), 22, 0, 1000, 2, &ok, this ); + if ( ok ) + ;// user entered something and pressed ok + else + ;// user pressed cancel + \endcode +*/ + +int QInputDialog::getInteger( const QString &caption, const QString &label, int num, int from, int to, int step, + bool *ok, QWidget *parent, const char *name ) +{ + QInputDialog *dlg = new QInputDialog( label, parent, name, TRUE, SpinBox ); + dlg->setCaption( caption ); + dlg->spinBox()->setRange( from, to ); + dlg->spinBox()->setSteps( step, 0 ); + dlg->spinBox()->setValue( num ); + + bool ok_ = FALSE; + int result; + ok_ = dlg->exec() == QDialog::Accepted; + if ( ok ) + *ok = ok_; + result = dlg->spinBox()->value(); + + delete dlg; + return result; +} + +/*! + Static convenience function to get a decimal input from the user. \a caption is the text + which is displayed in the title bar of the dialog. \a label is the text which + is shown to the user (it should mention to the user what he/she should input), \a num + the default decimal number which will be initially set to the line edit, \a from and \a to the + range in which the entered number has to be, \a decimals the number of decimal which + the number may have, \a ok a pointer to + a bool which will be (if not 0!) set to TRUE if the user pressed ok or to FALSE if the + user pressed cancel, \a parent the parent widget of the dialog and \a name + the name of it. The dialogs pops up modally! + + This method returns the number which has been entered by the user. + + You will use this static method like this: + + \code + bool ok = FALSE; + double res = QInputDialog::getDouble( tr( "Please enter a decimal number" ), 33.7, 0, 1000, 2, &ok, this ); + if ( ok ) + ;// user entered something and pressed ok + else + ;// user pressed cancel + \endcode +*/ + +double QInputDialog::getDouble( const QString &caption, const QString &label, double num, + double from, double to, int decimals, + bool *ok, QWidget *parent, const char *name ) +{ + QInputDialog *dlg = new QInputDialog( label, parent, name, TRUE, LineEdit ); + dlg->setCaption( caption ); + dlg->lineEdit()->setValidator( new QDoubleValidator( from, to, decimals, dlg->lineEdit() ) ); + dlg->lineEdit()->setText( QString::number( num, 'f', decimals ) ); + dlg->lineEdit()->selectAll(); + + bool accepted = ( dlg->exec() == QDialog::Accepted ); + if ( ok ) + *ok = accepted; + + double result = dlg->lineEdit()->text().toDouble(); + + delete dlg; + return result; +} + +/*! + Static convenience function to let the user select an item from a string list. \a caption is the text + which is displayed in the title bar of the dialog. \a label is the text which + is shown to the user (it should mention to the user what he/she should input), \a list the + string list which is inserted into the combobox, \a current the number of the item which should + be initially the current item, \a editable specifies if the combobox should be editable (if it is TRUE) + or read-only (if \a editable is FALSE), \a ok a pointer to + a bool which will be (if not 0!) set to TRUE if the user pressed ok or to FALSE if the + user pressed cancel, \a parent the parent widget of the dialog and \a name + the name of it. The dialogs pops up modally! + + This method returns the text of the current item, or if \a editable was TRUE, the current + text of the combobox. + + You will use this static method like this: + + \code + QStringList lst; + lst << "First" << "Second" << "Third" << "Fourth" << "Fifth"; + bool ok = FALSE; + QString res = QInputDialog::getItem( tr( "Please select an item" ), lst, 1, TRUE, &ok, this ); + if ( ok ) + ;// user selected an item and pressed ok + else + ;// user pressed cancel + \endcode +*/ + +QString QInputDialog::getItem( const QString &caption, const QString &label, const QStringList &list, + int current, bool editable, + bool *ok, QWidget *parent, const char *name ) +{ + QInputDialog *dlg = new QInputDialog( label, parent, name, TRUE, editable ? EditableComboBox : ComboBox ); + dlg->setCaption( caption ); + if ( editable ) { + dlg->editableComboBox()->insertStringList( list ); + dlg->editableComboBox()->setCurrentItem( current ); + } else { + dlg->comboBox()->insertStringList( list ); + dlg->comboBox()->setCurrentItem( current ); + } + + bool ok_ = FALSE; + QString result; + ok_ = dlg->exec() == QDialog::Accepted; + if ( ok ) + *ok = ok_; + if ( editable ) + result = dlg->editableComboBox()->currentText(); + else + result = dlg->comboBox()->currentText(); + + delete dlg; + return result; +} + +/*! + \internal +*/ + +void QInputDialog::textChanged( const QString &s ) +{ + bool on; + if ( d->lineEdit->validator() ) { + QString str = d->lineEdit->text(); + int index = d->lineEdit->cursorPosition(); + on = ( d->lineEdit->validator()->validate(str, index) == + QValidator::Acceptable ); + } else { + on = !s.isEmpty(); + } + d->ok->setEnabled( on ); +} + +/*! + \internal +*/ + +void QInputDialog::tryAccept() +{ + if ( !d->lineEdit->text().isEmpty() ) + accept(); +} + diff --git a/libqtaux/qinputdialog.h b/libqtaux/qinputdialog.h new file mode 100644 index 0000000..2583185 --- a/dev/null +++ b/libqtaux/qinputdialog.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QInputDialog class +** +** Created : 991212 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the dialogs module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QINPUTDIALOG_H +#define QINPUTDIALOG_H + +#ifndef QT_H +#include +#include +#include +#endif // QT_H + +class QInputDialogPrivate; + +class QSpinBox; +class QComboBox; + +class Q_EXPORT QInputDialog : public QDialog +{ +#if defined(_CC_MSVC_) + friend class QInputDialog; +#endif + Q_OBJECT + +private: + enum Type { LineEdit, SpinBox, ComboBox, EditableComboBox }; + + QInputDialog( const QString &label, QWidget* parent = 0, const char* name = 0, + bool modal = TRUE, Type type = LineEdit ); + ~QInputDialog(); + + QLineEdit *lineEdit() const; + QSpinBox *spinBox() const; + QComboBox *comboBox() const; + QComboBox *editableComboBox() const; + + void setType( Type t ); + Type type() const; + +public: + static QString getText( const QString &caption, const QString &label, const QString &text = QString::null, + bool *ok = 0, QWidget *parent = 0, const char *name = 0 ); // ### merge with below in 3.0 + static QString getText( const QString &caption, const QString &label, QLineEdit::EchoMode echo, //### make default Normal in 3.0 + const QString &text = QString::null, bool *ok = 0, QWidget *parent = 0, const char *name = 0 ); + + static int getInteger( const QString &caption, const QString &label, int num = 0, int from = -2147483647, + int to = 2147483647, + int step = 1, bool *ok = 0, QWidget *parent = 0, const char *name = 0 ); + static double getDouble( const QString &caption, const QString &label, double num = 0, + double from = -2147483647, double to = 2147483647, + int decimals = 1, bool *ok = 0, QWidget *parent = 0, const char *name = 0 ); + static QString getItem( const QString &caption, const QString &label, const QStringList &list, + int current = 0, bool editable = TRUE, + bool *ok = 0, QWidget *parent = 0, const char *name = 0 ); + +private slots: + void textChanged( const QString &s ); + void tryAccept(); + +private: + QInputDialogPrivate *d; + // just to avoid warnings... + friend class QInputDialogPrivate; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QInputDialog( const QInputDialog & ); + QInputDialog &operator=( const QInputDialog & ); +#endif +}; + +#endif // QINPUTDIALOG_H diff --git a/libqtaux/qlayoutengine_p.h b/libqtaux/qlayoutengine_p.h new file mode 100644 index 0000000..1b463b5 --- a/dev/null +++ b/libqtaux/qlayoutengine_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** $Id$ +** +** Internal header file. +** +** Created : 981027 +** +** Copyright (C) 1998-99 by Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QLAYOUTENGINE_P_H +#define QLAYOUTENGINE_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qlayout.cpp, qlayoutengine.cpp, qmainwindow.cpp and qsplitter.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// +// + + +#ifndef QT_H +#include "qabstractlayout.h" +#endif // QT_H +#ifndef QT_NO_LAYOUT +struct QLayoutStruct +{ + void init() { stretch = 0; initParameters(); } + void initParameters() { minimumSize = sizeHint = 0; + maximumSize = QWIDGETSIZE_MAX; expansive = FALSE; empty = TRUE; } + //permanent storage: + int stretch; + //parameters: + QCOORD sizeHint; + QCOORD maximumSize; + QCOORD minimumSize; + bool expansive; + bool empty; + //temporary storage: + bool done; + //result: + int pos; + int size; +}; + + +void qGeomCalc( QArray &chain, int start, int count, int pos, + int space, int spacer ); + + + +/* + Modify total maximum (max) and total expansion (exp) + when adding boxmax/boxexp. + + Expansive boxes win over non-expansive boxes. +*/ +static inline void qMaxExpCalc( QCOORD & max, bool &exp, + QCOORD boxmax, bool boxexp ) +{ + if ( exp ) { + if ( boxexp ) + max = QMAX( max, boxmax ); + } else { + if ( boxexp ) + max = boxmax; + else + max = QMIN( max, boxmax ); + } + exp = exp || boxexp; +} + +#endif //QT_NO_LAYOUT +#endif diff --git a/libqtaux/qsplitter.cpp b/libqtaux/qsplitter.cpp new file mode 100644 index 0000000..ab6e01b --- a/dev/null +++ b/libqtaux/qsplitter.cpp @@ -0,0 +1,1128 @@ +/**************************************************************************** +** $Id$ +** +** Splitter widget +** +** Created: 980105 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include "qsplitter.h" + +#include "qpainter.h" +#include "qdrawutil.h" +#include "qbitmap.h" +#include "qlayoutengine_p.h" +#include "qlist.h" +#include "qarray.h" +#include "qobjectlist.h" +#include "qapplication.h" //sendPostedEvents + +class QSplitterHandle : public QWidget +{ +public: + QSplitterHandle( Qt::Orientation o, + QSplitter *parent, const char* name=0 ); + void setOrientation( Qt::Orientation o ); + Qt::Orientation orientation() const { return orient; } + + bool opaque() const { return s->opaqueResize(); } + + QSize sizeHint() const; + QSizePolicy sizePolicy() const; + + int id() const { return myId; } // data->list.at(id())->wid == this + void setId( int i ) { myId = i; } + +protected: + void paintEvent( QPaintEvent * ); + void mouseMoveEvent( QMouseEvent * ); + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + +private: + Qt::Orientation orient; + bool opaq; + int myId; + + QSplitter *s; +}; + +static int mouseOffset; +static int opaqueOldPos = -1; //### there's only one mouse, but this is a bit risky + + +QSplitterHandle::QSplitterHandle( Qt::Orientation o, + QSplitter *parent, const char * name ) + : QWidget( parent, name ) +{ + s = parent; + setOrientation(o); +} + +QSizePolicy QSplitterHandle::sizePolicy() const +{ + //### removeme 3.0 + return QWidget::sizePolicy(); +} + +QSize QSplitterHandle::sizeHint() const +{ + int sw = style().splitterWidth(); + return QSize(sw,sw).expandedTo( QApplication::globalStrut() ); +} + +void QSplitterHandle::setOrientation( Qt::Orientation o ) +{ + orient = o; +#ifndef QT_NO_CURSOR + if ( o == QSplitter::Horizontal ) + setCursor( splitHCursor ); + else + setCursor( splitVCursor ); +#endif +} + + +void QSplitterHandle::mouseMoveEvent( QMouseEvent *e ) +{ + if ( !(e->state()&LeftButton) ) + return; + QCOORD pos = s->pick(parentWidget()->mapFromGlobal(e->globalPos())) + - mouseOffset; + if ( opaque() ) { + s->moveSplitter( pos, id() ); + } else { + int min = pos; int max = pos; + s->getRange( id(), &min, &max ); + s->setRubberband( QMAX( min, QMIN(max, pos ))); + } +} + +void QSplitterHandle::mousePressEvent( QMouseEvent *e ) +{ + if ( e->button() == LeftButton ) + mouseOffset = s->pick(e->pos()); +} + +void QSplitterHandle::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( !opaque() && e->button() == LeftButton ) { + QCOORD pos = s->pick(parentWidget()->mapFromGlobal(e->globalPos())); + s->setRubberband( -1 ); + s->moveSplitter( pos, id() ); + } +} + +void QSplitterHandle::paintEvent( QPaintEvent * ) +{ + QPainter p( this ); + s->drawSplitter( &p, 0, 0, width(), height() ); +} + + +class QSplitterLayoutStruct +{ +public: + QSplitter::ResizeMode mode; + QCOORD sizer; + bool isSplitter; + QWidget *wid; +}; + +class QSplitterData +{ +public: + QSplitterData() : opaque( FALSE ), firstShow( TRUE ) {} + + QList list; + bool opaque; + bool firstShow; +}; + + +// NOT REVISED +/*! + \class QSplitter qsplitter.h + \brief The QSplitter class implements a splitter widget. + + \ingroup organizers + + A splitter lets the user control the size of child widgets by + dragging the boundary between the children. Any number of widgets + may be controlled. + + To show a QListBox, a QListView and a QMultiLineEdit side by side: + + \code + QSplitter *split = new QSplitter( parent ); + QListBox *lb = new QListBox( split ); + QListView *lv = new QListView( split ); + QMultiLineEdit *ed = new QMultiLineEdit( split ); + \endcode + + In QSplitter the boundary can be either horizontal or vertical. The + default is horizontal (the children are side by side) and you + can use setOrientation( QSplitter::Vertical ) to set it to vertical. + + By default, all widgets can be as large or as small as the user + wishes, down to \link QWidget::minimumSizeHint() minimumSizeHint()\endlink. + You can naturally use setMinimumSize() and/or + setMaximumSize() on the children. Use setResizeMode() to specify that + a widget should keep its size when the splitter is resized. + + QSplitter normally resizes the children only at the end of a + resize operation, but if you call setOpaqueResize( TRUE ), the + widgets are resized as often as possible. + + The initial distribution of size between the widgets is determined + by the initial size of each widget. You can also use setSizes() to + set the sizes of all the widgets. The function sizes() returns the + sizes set by the user. + + If you hide() a child, its space will be distributed among the other + children. When you show() it again, it will be reinstated. + + + + \sa QTabBar +*/ + + + +static QSize minSize( const QWidget *w ) +{ + QSize min = w->minimumSize(); + QSize s; + if ( min.height() <= 0 || min.width() <= 0 ) + s = w->minimumSizeHint(); + if ( min.height() > 0 ) + s.setHeight( min.height() ); + if ( min.width() > 0 ) + s.setWidth( min.width() ); + return s.expandedTo(QSize(0,0)); +} + +/*! + Constructs a horizontal splitter. +*/ + +QSplitter::QSplitter( QWidget *parent, const char *name ) + :QFrame(parent,name,WPaintUnclipped) +{ + orient = Horizontal; + init(); +} + + +/*! + Constructs splitter with orientation \a o. +*/ + +QSplitter::QSplitter( Orientation o, QWidget *parent, const char *name ) + :QFrame(parent,name,WPaintUnclipped) +{ + orient = o; + init(); +} + + +/*! + Destructs the splitter. +*/ + +QSplitter::~QSplitter() +{ + data->list.setAutoDelete( TRUE ); + delete data; +} + + +void QSplitter::init() +{ + data = new QSplitterData; + if ( orient == Horizontal ) + setSizePolicy( QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Minimum) ); + else + setSizePolicy( QSizePolicy(QSizePolicy::Minimum,QSizePolicy::Fixed) ); +} + + +/*! + \fn void QSplitter::refresh() + + Updates the splitter state. You should not need to call this + function during normal use of the splitter. +*/ + + +/*! Sets the orientation to \a o. By default the orientation is + horizontal (the widgets are side by side). + + \sa orientation() +*/ + +void QSplitter::setOrientation( Orientation o ) +{ + if ( orient == o ) + return; + orient = o; + + if ( orient == Horizontal ) + setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ) ); + else + setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) ); + + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->isSplitter ) + ((QSplitterHandle*)s->wid)->setOrientation( o ); + s = data->list.next(); // ### next at end of loop, no iterator + } + recalc( isVisible() ); +} + + +/*! + \fn Orientation QSplitter::orientation() const + + Returns the orientation (\c Horizontal or \c Vertical) of the splitter. + \sa setOrientation() +*/ + +/*! + \reimp +*/ +void QSplitter::resizeEvent( QResizeEvent * ) +{ + doResize(); +} + + +/*! + Inserts the widget \a w at the end, or at the beginning if \a first is TRUE + + It is the responsibility of the caller of this function to make sure + that \a w is not already in the splitter, and to call recalcId if + needed. (If \a first is TRUE, then recalcId is very probably + needed.) +*/ + +QSplitterLayoutStruct *QSplitter::addWidget( QWidget *w, bool first ) +{ + QSplitterLayoutStruct *s; + QSplitterHandle *newHandle = 0; + if ( data->list.count() > 0 ) { + s = new QSplitterLayoutStruct; + s->mode = KeepSize; + newHandle = new QSplitterHandle( orientation(), this ); + s->wid = newHandle; + newHandle->setId(data->list.count()); + s->isSplitter = TRUE; + s->sizer = pick( newHandle->sizeHint() ); + if ( first ) + data->list.insert( 0, s ); + else + data->list.append( s ); + } + s = new QSplitterLayoutStruct; + s->mode = Stretch; + s->wid = w; + if ( !testWState( WState_Resized ) && w->sizeHint().isValid() ) + s->sizer = pick( w->sizeHint() ); + else + s->sizer = pick( w->size() ); + s->isSplitter = FALSE; + if ( first ) + data->list.insert( 0, s ); + else + data->list.append( s ); + if ( newHandle && isVisible() ) + newHandle->show(); //will trigger sending of post events + return s; +} + + +/*! + Tells the splitter that a child widget has been inserted/removed. +*/ + +void QSplitter::childEvent( QChildEvent *c ) +{ + if ( c->type() == QEvent::ChildInserted ) { + if ( !c->child()->isWidgetType() ) + return; + + if ( ((QWidget*)c->child())->testWFlags( WType_TopLevel ) ) + return; + + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == c->child() ) + return; + s = data->list.next(); + } + addWidget( (QWidget*)c->child() ); + recalc( isVisible() ); + + } else if ( c->type() == QEvent::ChildRemoved ) { + QSplitterLayoutStruct *p = 0; + if ( data->list.count() > 1 ) + p = data->list.at(1); //remove handle _after_ first widget. + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == c->child() ) { + data->list.removeRef( s ); + delete s; + if ( p && p->isSplitter ) { + data->list.removeRef( p ); + delete p->wid; //will call childEvent + delete p; + } + recalcId(); + doResize(); + return; + } + p = s; + s = data->list.next(); + } + } +} + + +/*! + Shows a rubber band at position \a p. If \a p is negative, the + rubber band is removed. +*/ + +void QSplitter::setRubberband( int p ) +{ + QPainter paint( this ); + paint.setPen( gray ); + paint.setBrush( gray ); + paint.setRasterOp( XorROP ); + QRect r = contentsRect(); + const int rBord = 3; //Themable???? + const int sw = style().splitterWidth(); + if ( orient == Horizontal ) { + if ( opaqueOldPos >= 0 ) + paint.drawRect( opaqueOldPos + sw/2 - rBord , r.y(), + 2*rBord, r.height() ); + if ( p >= 0 ) + paint.drawRect( p + sw/2 - rBord, r.y(), 2*rBord, r.height() ); + } else { + if ( opaqueOldPos >= 0 ) + paint.drawRect( r.x(), opaqueOldPos + sw/2 - rBord, + r.width(), 2*rBord ); + if ( p >= 0 ) + paint.drawRect( r.x(), p + sw/2 - rBord, r.width(), 2*rBord ); + } + opaqueOldPos = p; +} + + +/*! \reimp */ + +bool QSplitter::event( QEvent *e ) +{ + if ( e->type() == QEvent::LayoutHint || ( e->type() == QEvent::Show && data->firstShow ) ) { + recalc( isVisible() ); + if ( e->type() == QEvent::Show ) + data->firstShow = FALSE; + } + return QWidget::event( e ); +} + + +/*! + Draws the splitter handle in the rectangle described by \a x, \a y, + \a w, \a h using painter \a p. + \sa QStyle::drawSplitter +*/ + +void QSplitter::drawSplitter( QPainter *p, + QCOORD x, QCOORD y, QCOORD w, QCOORD h ) +{ + style().drawSplitter( p, x, y, w, h, colorGroup(), orient ); +} + + +/*! + Returns the id of the splitter to the right of or below the widget \a w, + or 0 if there is no such splitter. + (ie. it is either not in this QSplitter, or it is at the end). +*/ + +int QSplitter::idAfter( QWidget* w ) const +{ + QSplitterLayoutStruct *s = data->list.first(); + bool seen_w = FALSE; + while ( s ) { + if ( s->isSplitter && seen_w ) + return data->list.at(); + if ( !s->isSplitter && s->wid == w ) + seen_w = TRUE; + s = data->list.next(); + } + return 0; +} + + +/*! + Moves the left/top edge of the splitter handle with id \a id as + close as possible to \a p which is the distance from the left (or + top) edge of the widget. + + \sa idAfter() +*/ +void QSplitter::moveSplitter( QCOORD p, int id ) +{ + p = adjustPos( p, id ); + + QSplitterLayoutStruct *s = data->list.at(id); + int oldP = orient == Horizontal? s->wid->x() : s->wid->y(); + bool upLeft = p < oldP; + + moveAfter( p, id, upLeft ); + moveBefore( p-1, id-1, upLeft ); + + storeSizes(); +} + + +void QSplitter::setG( QWidget *w, int p, int s ) +{ + if ( orient == Horizontal ) + w->setGeometry( p, contentsRect().y(), s, contentsRect().height() ); + else + w->setGeometry( contentsRect().x(), p, contentsRect().width(), s ); +} + + +/*! + Places the right/bottom edge of the widget at \a id at position \a pos. + + \sa idAfter() +*/ + +void QSplitter::moveBefore( int pos, int id, bool upLeft ) +{ + QSplitterLayoutStruct *s = data->list.at(id); + if ( !s ) + return; + QWidget *w = s->wid; + if ( w->isHidden() ) { + moveBefore( pos, id-1, upLeft ); + } else if ( s->isSplitter ) { + int dd = s->sizer; + if ( upLeft ) { + setG( w, pos-dd+1, dd ); + moveBefore( pos-dd, id-1, upLeft ); + } else { + moveBefore( pos-dd, id-1, upLeft ); + setG( w, pos-dd+1, dd ); + } + } else { + int left = pick( w->pos() ); + int dd = pos - left + 1; + dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize()))); + int newLeft = pos-dd+1; + setG( w, newLeft, dd ); + if ( left != newLeft ) + moveBefore( newLeft-1, id-1, upLeft ); + } +} + + +/*! + Places the left/top edge of the widget at \a id at position \a pos. + + \sa idAfter() +*/ + +void QSplitter::moveAfter( int pos, int id, bool upLeft ) +{ + QSplitterLayoutStruct *s = id < int(data->list.count()) ? + data->list.at(id) : 0; + if ( !s ) + return; + QWidget *w = s->wid; + if ( w->isHidden() ) { + moveAfter( pos, id+1, upLeft ); + } else if ( pick( w->pos() ) == pos ) { + //No need to do anything if it's already there. + return; + } else if ( s->isSplitter ) { + int dd = s->sizer; + if ( upLeft ) { + setG( w, pos, dd ); + moveAfter( pos+dd, id+1, upLeft ); + } else { + moveAfter( pos+dd, id+1, upLeft ); + setG( w, pos, dd ); + } + } else { + int right = pick( w->geometry().bottomRight() ); + + int dd = right - pos + 1; + dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize()))); + int newRight = pos+dd-1; + setG( w, pos, dd ); + moveAfter( newRight+1, id+1, upLeft ); + } +} + + +/*! + Returns the valid range of the splitter with id \a id in \a min and \a max. + + \sa idAfter() +*/ + +void QSplitter::getRange( int id, int *min, int *max ) +{ + int minB = 0; //before + int maxB = 0; + int minA = 0; + int maxA = 0; //after + int n = data->list.count(); + if ( id < 0 || id >= n ) + return; + int i; + for ( i = 0; i < id; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->wid->isHidden() ) { + //ignore + } else if ( s->isSplitter ) { + minB += s->sizer; + maxB += s->sizer; + } else { + minB += pick( minSize(s->wid) ); + maxB += pick( s->wid->maximumSize() ); + } + } + for ( i = id; i < n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->wid->isHidden() ) { + //ignore + } else if ( s->isSplitter ) { + minA += s->sizer; + maxA += s->sizer; + } else { + minA += pick( minSize(s->wid) ); + maxA += pick( s->wid->maximumSize() ); + } + } + QRect r = contentsRect(); + if ( min ) + *min = pick(r.topLeft()) + QMAX( minB, pick(r.size())-maxA ); + if ( max ) + *max = pick(r.topLeft()) + QMIN( maxB, pick(r.size())-minA ); + +} + + +/*! + Returns the legal position closest to \a p of the splitter with id \a id. + + \sa idAfter() +*/ + +int QSplitter::adjustPos( int p, int id ) +{ + int min = 0; + int max = 0; + getRange( id, &min, &max ); + p = QMAX( min, QMIN( p, max ) ); + + return p; +} + + +void QSplitter::doResize() +{ + QRect r = contentsRect(); + int i; + int n = data->list.count(); + QArray a( n ); + for ( i = 0; i< n; i++ ) { + a[i].init(); + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->wid->isHidden() ) { + a[i].stretch = 0; + a[i].sizeHint = a[i].minimumSize = 0; + a[i].maximumSize = 0; + } else if ( s->isSplitter ) { + a[i].stretch = 0; + a[i].sizeHint = a[i].minimumSize = a[i].maximumSize = s->sizer; + a[i].empty = FALSE; + } else if ( s->mode == KeepSize ) { + a[i].stretch = 0; + a[i].minimumSize = pick( minSize(s->wid) ); + a[i].sizeHint = s->sizer; + a[i].maximumSize = pick( s->wid->maximumSize() ); + a[i].empty = FALSE; + } else if ( s->mode == FollowSizeHint ) { + a[i].stretch = 0; + a[i].minimumSize = a[i].sizeHint = pick( s->wid->sizeHint() ); + a[i].maximumSize = pick( s->wid->maximumSize() ); + a[i].empty = FALSE; + } else { //proportional + a[i].stretch = s->sizer; + a[i].maximumSize = pick( s->wid->maximumSize() ); + a[i].sizeHint = a[i].minimumSize = pick( minSize(s->wid) ); + a[i].empty = FALSE; + } + } + + qGeomCalc( a, 0, n, pick( r.topLeft() ), pick( r.size() ), 0 ); + for ( i = 0; i< n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( orient == Horizontal ) + s->wid->setGeometry( a[i].pos, r.top(), a[i].size, r.height() ); + else + s->wid->setGeometry( r.left(), a[i].pos, r.width(), a[i].size ); + } + +} + + +void QSplitter::recalc( bool update ) +{ + int fi = 2*frameWidth(); + int maxl = fi; + int minl = fi; + int maxt = QWIDGETSIZE_MAX; + int mint = fi; + int n = data->list.count(); + bool first = TRUE; + /* + The splitter before a hidden widget is always hidden. + The splitter before the first visible widget is hidden. + The splitter before any other visible widget is visible. + */ + for ( int i = 0; i< n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( !s->isSplitter ) { + QSplitterLayoutStruct *p = (i > 0) ? p = data->list.at( i-1 ) : 0; + if ( p && p->isSplitter ) + if ( first || s->wid->isHidden() ) + p->wid->hide(); //may trigger new recalc + else + p->wid->show(); //may trigger new recalc + if ( !s->wid->isHidden() ) + first = FALSE; + } + } + + bool empty=TRUE; + for ( int j = 0; j< n; j++ ) { + QSplitterLayoutStruct *s = data->list.at(j); + if ( !s->wid->isHidden() ) { + empty = FALSE; + if ( s->isSplitter ) { + minl += s->sizer; + maxl += s->sizer; + } else { + QSize minS = minSize(s->wid); + minl += pick( minS ); + maxl += pick( s->wid->maximumSize() ); + mint = QMAX( mint, trans( minS )); + int tm = trans( s->wid->maximumSize() ); + if ( tm > 0 ) + maxt = QMIN( maxt, tm ); + } + } + } + if ( empty ) + maxl = maxt = 0; + else + maxl = QMIN( maxl, QWIDGETSIZE_MAX ); + if ( maxt < mint ) + maxt = mint; + + if ( orient == Horizontal ) { + setMaximumSize( maxl, maxt ); + setMinimumSize( minl, mint ); + } else { + setMaximumSize( maxt, maxl ); + setMinimumSize( mint, minl ); + } + if ( update ) + doResize(); +} + +/*! \enum QSplitter::ResizeMode + + This enum type describes how QSplitter will resize each of its child widgets. The currently defined values are:
    + +
  • \c Stretch - the widget will be resized when the splitter + itself is resized. + +
  • \c KeepSize - QSplitter will try to keep this widget's size + unchanged. + +
  • \c FollowSizeHint - QSplitter will resize the widget when its + size hint changes. + +
+ +*/ + +/*! + Sets resize mode of \a w to \a mode. + + \sa ResizeMode +*/ + +void QSplitter::setResizeMode( QWidget *w, ResizeMode mode ) +{ + processChildEvents(); + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == w ) { + s->mode = mode; + return; + } + s = data->list.next(); + } + s = addWidget( w, TRUE ); + s->mode = mode; +} + + +/*! + Returns TRUE if opaque resize is on, FALSE otherwise. + + \sa setOpaqueResize() +*/ + +bool QSplitter::opaqueResize() const +{ + return data->opaque; +} + + +/*! + Sets opaque resize to \a on. Opaque resize is initially turned off. + + \sa opaqueResize() +*/ + +void QSplitter::setOpaqueResize( bool on ) +{ + data->opaque = on; +} + + +/*! + Moves \a w to the leftmost/top position. +*/ + +void QSplitter::moveToFirst( QWidget *w ) +{ + processChildEvents(); + bool found = FALSE; + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == w ) { + found = TRUE; + QSplitterLayoutStruct *p = data->list.prev(); + if ( p ) { // not already at first place + data->list.take(); //take p + data->list.take(); // take s + data->list.insert( 0, p ); + data->list.insert( 0, s ); + } + break; + } + s = data->list.next(); + } + if ( !found ) + addWidget( w, TRUE ); + recalcId(); +} + + +/*! + Moves \a w to the rightmost/bottom position. +*/ + +void QSplitter::moveToLast( QWidget *w ) +{ + processChildEvents(); + bool found = FALSE; + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == w ) { + found = TRUE; + data->list.take(); // take s + QSplitterLayoutStruct *p = data->list.current(); + if ( p ) { // the splitter handle after s + data->list.take(); //take p + data->list.append( p ); + } + data->list.append( s ); + break; + } + s = data->list.next(); + } + if ( !found ) + addWidget( w); + recalcId(); +} + + +void QSplitter::recalcId() +{ + int n = data->list.count(); + for ( int i = 0; i < n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->isSplitter ) + ((QSplitterHandle*)s->wid)->setId(i); + } +} + + +/*!\reimp +*/ +QSize QSplitter::sizeHint() const +{ + constPolish(); + int l = 0; + int t = 0; + if ( children() ) { + const QObjectList * c = children(); + QObjectListIt it( *c ); + QObject * o; + + while( (o=it.current()) != 0 ) { + ++it; + if ( o->isWidgetType() && + !((QWidget*)o)->isHidden() ) { + QSize s = ((QWidget*)o)->sizeHint(); + if ( s.isValid() ) { + l += pick( s ); + t = QMAX( t, trans( s ) ); + } + } + } + } + return orientation() == Horizontal ? QSize( l, t ) : QSize( t, l ); +} + + +/*! +\reimp +*/ + +QSize QSplitter::minimumSizeHint() const +{ + constPolish(); + int l = 0; + int t = 0; + if ( children() ) { + const QObjectList * c = children(); + QObjectListIt it( *c ); + QObject * o; + + while( (o=it.current()) != 0 ) { + ++it; + if ( o->isWidgetType() && + !((QWidget*)o)->isHidden() ) { + QSize s = minSize((QWidget*)o); + if ( s.isValid() ) { + l += pick( s ); + t = QMAX( t, trans( s ) ); + } + } + } + } + return orientation() == Horizontal ? QSize( l, t ) : QSize( t, l ); +} + + + +/*!\reimp +*/ +QSizePolicy QSplitter::sizePolicy() const +{ + return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); +} + + +/*! + Calculates stretch parameters from current sizes +*/ + +void QSplitter::storeSizes() +{ + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( !s->isSplitter ) + s->sizer = pick( s->wid->size() ); + s = data->list.next(); + } +} + + +#if 0 // ### remove this code ASAP + +/*! + Hides \a w if \a hide is TRUE, and updates the splitter. + + \warning Due to a limitation in the current implementation, + calling QWidget::hide() will not work. +*/ + +void QSplitter::setHidden( QWidget *w, bool hide ) +{ + if ( w == w1 ) { + w1show = !hide; + } else if ( w == w2 ) { + w2show = !hide; + } else { +#ifdef CHECK_RANGE + qWarning( "QSplitter::setHidden(), unknown widget" ); +#endif + return; + } + if ( hide ) + w->hide(); + else + w->show(); + recalc( TRUE ); +} + + +/*! + Returns the hidden status of \a w +*/ + +bool QSplitter::isHidden( QWidget *w ) const +{ + if ( w == w1 ) + return !w1show; + else if ( w == w2 ) + return !w2show; +#ifdef CHECK_RANGE + else + qWarning( "QSplitter::isHidden(), unknown widget" ); +#endif + return FALSE; +} +#endif + + +/*! + Returns a list of the size parameters of all the widgets in this + splitter. + + Giving the values to setSizes() will give a splitter with the same + layout as this one. + + \sa setSizes() +*/ + +QValueList QSplitter::sizes() const +{ + if ( !testWState(WState_Polished) ) { + QWidget* that = (QWidget*) this; + that->polish(); + } + QValueList list; + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( !s->isSplitter ) + list.append( s->sizer ); + s = data->list.next(); + } + return list; +} + + + +/*! + Sets the size parameters to the values given in \a list. + If the splitter is horizontal, the values set the sizes from + left to right. If it is vertical, the sizes are applied from + top to bottom. + Extra values in \a list are ignored. + + If \a list contains too few values, the result is undefined + but the program will still be well-behaved. + + \sa sizes() +*/ + +void QSplitter::setSizes( QValueList list ) +{ + processChildEvents(); + QValueList::Iterator it = list.begin(); + QSplitterLayoutStruct *s = data->list.first(); + while ( s && it != list.end() ) { + if ( !s->isSplitter ) { + s->sizer = *it; + ++it; + } + s = data->list.next(); + } + doResize(); +} + + +/*! + Gets all posted child events, ensuring that the internal state of + the splitter is consistent with the programmer's idea. +*/ + +void QSplitter::processChildEvents() +{ + QApplication::sendPostedEvents( this, QEvent::ChildInserted ); +} + + +/*! + \reimp +*/ + +void QSplitter::styleChange( QStyle& old ) +{ + int sw = style().splitterWidth(); + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->isSplitter ) + s->sizer = sw; + s = data->list.next(); + } + doResize(); + QFrame::styleChange( old ); +} + diff --git a/libqtaux/qsplitter.h b/libqtaux/qsplitter.h new file mode 100644 index 0000000..8625c4d --- a/dev/null +++ b/libqtaux/qsplitter.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** $Id$ +** +** Defintion of QSplitter class +** +** Created: 980105 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef QSPLITTER_H +#define QSPLITTER_H + +#ifndef QT_H +#include "qframe.h" +#include "qvaluelist.h" +#endif // QT_H + +class QSplitterHandle; +class QSplitterData; +class QSplitterLayoutStruct; + +class Q_EXPORT QSplitter : public QFrame +{ + Q_OBJECT + Q_PROPERTY( Orientation orientation READ orientation WRITE setOrientation ) + +public: + enum ResizeMode { Stretch, KeepSize, FollowSizeHint }; + + QSplitter( QWidget *parent=0, const char *name=0 ); + QSplitter( Orientation, QWidget *parent=0, const char *name=0 ); + ~QSplitter(); + + virtual void setOrientation( Orientation ); + Orientation orientation() const { return orient; } + + virtual void setResizeMode( QWidget *w, ResizeMode ); + virtual void setOpaqueResize( bool = TRUE ); + bool opaqueResize() const; + + void moveToFirst( QWidget * ); + void moveToLast( QWidget * ); + + void refresh() { recalc( TRUE ); } + QSize sizeHint() const; + QSize minimumSizeHint() const; + QSizePolicy sizePolicy() const; + + QValueList sizes() const; + void setSizes( QValueList ); + +protected: + void childEvent( QChildEvent * ); + + bool event( QEvent * ); + void resizeEvent( QResizeEvent * ); + + int idAfter( QWidget* ) const; + + void moveSplitter( QCOORD pos, int id ); + virtual void drawSplitter( QPainter*, QCOORD x, QCOORD y, + QCOORD w, QCOORD h ); + void styleChange( QStyle& ); + int adjustPos( int , int ); + virtual void setRubberband( int ); + void getRange( int id, int*, int* ); + +private: + void init(); + void recalc( bool update = FALSE ); + void doResize(); + void storeSizes(); + void processChildEvents(); + QSplitterLayoutStruct *addWidget( QWidget*, bool first = FALSE ); + void recalcId(); + void moveBefore( int pos, int id, bool upLeft ); + void moveAfter( int pos, int id, bool upLeft ); + void setG( QWidget *w, int p, int s ); + + QCOORD pick( const QPoint &p ) const + { return orient == Horizontal ? p.x() : p.y(); } + QCOORD pick( const QSize &s ) const + { return orient == Horizontal ? s.width() : s.height(); } + + QCOORD trans( const QPoint &p ) const + { return orient == Vertical ? p.x() : p.y(); } + QCOORD trans( const QSize &s ) const + { return orient == Vertical ? s.width() : s.height(); } + + QSplitterData *data; + + Orientation orient; + friend class QSplitterHandle; +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QSplitter( const QSplitter & ); + QSplitter& operator=( const QSplitter & ); +#endif +}; + +#endif // QSPLITTER_H -- cgit v0.9.0.2