diff options
Diffstat (limited to 'src/dialogs')
-rw-r--r-- | src/dialogs/qcolordialog.cpp | 1673 | ||||
-rw-r--r-- | src/dialogs/qcolordialog.h | 93 | ||||
-rw-r--r-- | src/dialogs/qdialog.cpp | 1178 | ||||
-rw-r--r-- | src/dialogs/qdialog.h | 141 | ||||
-rw-r--r-- | src/dialogs/qerrormessage.cpp | 270 | ||||
-rw-r--r-- | src/dialogs/qerrormessage.h | 89 | ||||
-rw-r--r-- | src/dialogs/qfiledialog.cpp | 6486 | ||||
-rw-r--r-- | src/dialogs/qfiledialog.h | 347 | ||||
-rw-r--r-- | src/dialogs/qfontdialog.cpp | 841 | ||||
-rw-r--r-- | src/dialogs/qfontdialog.h | 112 | ||||
-rw-r--r-- | src/dialogs/qinputdialog.cpp | 532 | ||||
-rw-r--r-- | src/dialogs/qinputdialog.h | 107 | ||||
-rw-r--r-- | src/dialogs/qmessagebox.cpp | 1674 | ||||
-rw-r--r-- | src/dialogs/qmessagebox.h | 223 | ||||
-rw-r--r-- | src/dialogs/qprintdialog.cpp | 1672 | ||||
-rw-r--r-- | src/dialogs/qprintdialog.h | 103 | ||||
-rw-r--r-- | src/dialogs/qprogressdialog.cpp | 826 | ||||
-rw-r--r-- | src/dialogs/qprogressdialog.h | 141 | ||||
-rw-r--r-- | src/dialogs/qsemimodal.h | 66 | ||||
-rw-r--r-- | src/dialogs/qt_dialogs.pri | 33 | ||||
-rw-r--r-- | src/dialogs/qtabdialog.cpp | 1145 | ||||
-rw-r--r-- | src/dialogs/qtabdialog.h | 146 | ||||
-rw-r--r-- | src/dialogs/qwizard.cpp | 917 | ||||
-rw-r--r-- | src/dialogs/qwizard.h | 142 |
24 files changed, 18957 insertions, 0 deletions
diff --git a/src/dialogs/qcolordialog.cpp b/src/dialogs/qcolordialog.cpp new file mode 100644 index 000000000..c3edc0f66 --- /dev/null +++ b/src/dialogs/qcolordialog.cpp @@ -0,0 +1,1673 @@ +/**************************************************************************** +** +** Implementation of TQColorDialog class +** +** Created : 990222 +** +** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qcolordialog.h" + +#ifndef QT_NO_COLORDIALOG + +#include "qpainter.h" +#include "qlayout.h" +#include "qlabel.h" +#include "qpushbutton.h" +#include "qlineedit.h" +#include "qimage.h" +#include "qpixmap.h" +#include "qdrawutil.h" +#include "qvalidator.h" +#include "qdragobject.h" +#include "qgridview.h" +#include "qapplication.h" +#include "qstyle.h" +#include "qsettings.h" +#include "qpopupmenu.h" + +#ifdef Q_WS_MAC +TQRgb macGetRgba( TQRgb initial, bool *ok, TQWidget *parent, const char* name ); +TQColor macGetColor( const TQColor& initial, TQWidget *parent, const char *name ); +#endif + +#ifdef Q_WS_X11 +#include "private/qtkdeintegration_x11_p.h" +#endif + +//////////// TQWellArray BEGIN + +struct TQWellArrayData; + +class TQWellArray : public TQGridView +{ + Q_OBJECT + Q_PROPERTY( int selectedColumn READ selectedColumn ) + Q_PROPERTY( int selectedRow READ selectedRow ) + +public: + TQWellArray( TQWidget* parent=0, const char* name=0, bool popup = FALSE ); + + ~TQWellArray() {} + TQString cellContent( int row, int col ) const; + // ### Paul !!! virtual void setCellContent( int row, int col, const TQString &); + + int selectedColumn() const { return selCol; } + int selectedRow() const { return selRow; } + + virtual void setCurrent( int row, int col ); + virtual void setSelected( int row, int col ); + + TQSize sizeHint() const; + + virtual void setCellBrush( int row, int col, const TQBrush & ); + TQBrush cellBrush( int row, int col ); + +signals: + void selected( int row, int col ); + +protected: + void dimensionChange( int oldRows, int oldCols ); + + virtual void paintCell( TQPainter *, int row, int col ); + virtual void paintCellContents( TQPainter *, int row, int col, const TQRect& ); + + void mousePressEvent( TQMouseEvent* ); + void mouseReleaseEvent( TQMouseEvent* ); + void mouseMoveEvent( TQMouseEvent* ); + void keyPressEvent( TQKeyEvent* ); + void focusInEvent( TQFocusEvent* ); + void focusOutEvent( TQFocusEvent* ); + +private: + int curRow; + int curCol; + int selRow; + int selCol; + bool smallStyle; + TQWellArrayData *d; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQWellArray( const TQWellArray & ); + TQWellArray& operator=( const TQWellArray & ); +#endif +}; + + + +// non-interface ... + + + +struct TQWellArrayData { + TQBrush *brush; +}; + +/*! + \internal + \class TQWellArray qwellarray_p.h + \brief The TQWellArray class provides a well array. + + + \ingroup advanced +*/ + +TQWellArray::TQWellArray( TQWidget *parent, const char * name, bool popup ) + : TQGridView( parent, name, + (popup ? (WStyle_Customize|WStyle_Tool|WStyle_NoBorder) : 0 ) ) +{ + d = 0; + setFocusPolicy( StrongFocus ); + setVScrollBarMode(AlwaysOff); + setHScrollBarMode(AlwaysOff); + viewport()->setBackgroundMode( PaletteBackground ); + setNumCols( 7 ); + setNumRows( 7 ); + setCellWidth( 24 ); + setCellHeight( 21 ); + smallStyle = popup; + + if ( popup ) { + setCellWidth( 18 ); + setCellHeight( 18 ); + setFrameStyle(TQFrame::StyledPanel | TQFrame::Raised); + setMargin( 1 ); + setLineWidth( 2 ); + } else { + setFrameStyle( TQFrame::NoFrame ); + } + curCol = 0; + curRow = 0; + selCol = -1; + selRow = -1; + + if ( smallStyle ) + setMouseTracking( TRUE ); +} + + +TQSize TQWellArray::sizeHint() const +{ + constPolish(); + TQSize s = gridSize().boundedTo( TQSize(640, 480 ) ); + return TQSize( s.width() + 2*frameWidth(), s.height() + 2*frameWidth() ); +} + + +void TQWellArray::paintCell( TQPainter* p, int row, int col ) +{ + int w = cellWidth(); // width of cell in pixels + int h = cellHeight(); // height of cell in pixels + int b = 1; + + if ( !smallStyle ) + b = 3; + + const TQColorGroup & g = colorGroup(); + p->setPen( TQPen( black, 0, SolidLine ) ); + if ( !smallStyle && row ==selRow && col == selCol && + style().styleHint(TQStyle::SH_GUIStyle) != MotifStyle) { + int n = 2; + p->drawRect( n, n, w-2*n, h-2*n ); + } + + style().drawPrimitive(TQStyle::PE_Panel, p, TQRect(b, b, w-2*b, h-2*b), g, + TQStyle::Style_Enabled | TQStyle::Style_Sunken); + + int t = 0; + if (style().styleHint(TQStyle::SH_GUIStyle) == MotifStyle) + t = ( row == selRow && col == selCol ) ? 2 : 0; + b += 2 + t; + + if ( (row == curRow) && (col == curCol) ) { + if ( smallStyle ) { + p->setPen ( white ); + p->drawRect( 1, 1, w-2, h-2 ); + p->setPen ( black ); + p->drawRect( 0, 0, w, h ); + p->drawRect( 2, 2, w-4, h-4 ); + b = 3; + } else if ( hasFocus() ) { + style().drawPrimitive(TQStyle::PE_FocusRect, p, TQRect(0, 0, w, h), g); + } + } + paintCellContents( p, row, col, TQRect(b, b, w - 2*b, h - 2*b) ); +} + +/*! + Reimplement this function to change the contents of the well array. + */ +void TQWellArray::paintCellContents( TQPainter *p, int row, int col, const TQRect &r ) +{ + + if ( d ) { + p->fillRect( r, d->brush[row*numCols()+col] ); + } else { + p->fillRect( r, white ); + p->setPen( black ); + p->drawLine( r.topLeft(), r.bottomRight() ); + p->drawLine( r.topRight(), r.bottomLeft() ); + } +} + + +/*\reimp +*/ +void TQWellArray::mousePressEvent( TQMouseEvent* e ) +{ + // The current cell marker is set to the cell the mouse is pressed + // in. + TQPoint pos = e->pos(); + setCurrent( rowAt( pos.y() ), columnAt( pos.x() ) ); +} + +/*\reimp +*/ +void TQWellArray::mouseReleaseEvent( TQMouseEvent* ) +{ + // The current cell marker is set to the cell the mouse is clicked + // in. + setSelected( curRow, curCol ); +} + + +/*\reimp +*/ +void TQWellArray::mouseMoveEvent( TQMouseEvent* e ) +{ + // The current cell marker is set to the cell the mouse is + // clicked in. + if ( smallStyle ) { + TQPoint pos = e->pos(); + setCurrent( rowAt( pos.y() ), columnAt( pos.x() ) ); + } +} + +/* + Sets the cell currently having the focus. This is not necessarily + the same as the currently selected cell. +*/ + +void TQWellArray::setCurrent( int row, int col ) +{ + + if ( (curRow == row) && (curCol == col) ) + return; + + if ( row < 0 || col < 0 ) + row = col = -1; + + int oldRow = curRow; + int oldCol = curCol; + + curRow = row; + curCol = col; + + updateCell( oldRow, oldCol ); + updateCell( curRow, curCol ); +} + + +/*! + Sets the currently selected cell to \a row, \a col. If \a row or \a + col are less than zero, the current cell is unselected. + + Does not set the position of the focus indicator. +*/ + +void TQWellArray::setSelected( int row, int col ) +{ + if ( (selRow == row) && (selCol == col) ) + return; + + int oldRow = selRow; + int oldCol = selCol; + + if ( row < 0 || col < 0 ) + row = col = -1; + + selCol = col; + selRow = row; + + updateCell( oldRow, oldCol ); + updateCell( selRow, selCol ); + if ( row >= 0 ) + emit selected( row, col ); + + if ( isVisible() && ::qt_cast<TQPopupMenu*>(parentWidget()) ) + parentWidget()->close(); +} + + + +/*!\reimp +*/ +void TQWellArray::focusInEvent( TQFocusEvent* ) +{ + updateCell( curRow, curCol ); +} + + +/*! + Sets the size of the well array to be \a rows cells by \a cols. + Resets any brush information set by setCellBrush(). + */ +void TQWellArray::dimensionChange( int, int ) +{ + if ( d ) { + if ( d->brush ) + delete[] d->brush; + delete d; + d = 0; + } +} + +void TQWellArray::setCellBrush( int row, int col, const TQBrush &b ) +{ + if ( !d ) { + d = new TQWellArrayData; + int i = numRows()*numCols(); + d->brush = new TQBrush[i]; + } + if ( row >= 0 && row < numRows() && col >= 0 && col < numCols() ) + d->brush[row*numCols()+col] = b; +#ifdef QT_CHECK_RANGE + else + qWarning( "TQWellArray::setCellBrush( %d, %d ) out of range", row, col ); +#endif +} + + + +/*! + Returns the brush set for the cell at \a row, \a col. If no brush is set, + \c NoBrush is returned. +*/ + +TQBrush TQWellArray::cellBrush( int row, int col ) +{ + if ( d && row >= 0 && row < numRows() && col >= 0 && col < numCols() ) + return d->brush[row*numCols()+col]; + return NoBrush; +} + + + +/*!\reimp +*/ + +void TQWellArray::focusOutEvent( TQFocusEvent* ) +{ + updateCell( curRow, curCol ); +} + +/*\reimp +*/ +void TQWellArray::keyPressEvent( TQKeyEvent* e ) +{ + switch( e->key() ) { // Look at the key code + case Key_Left: // If 'left arrow'-key, + if( curCol > 0 ) // and cr't not in leftmost col + setCurrent( curRow, curCol - 1); // set cr't to next left column + break; + case Key_Right: // Correspondingly... + if( curCol < numCols()-1 ) + setCurrent( curRow, curCol + 1); + break; + case Key_Up: + if( curRow > 0 ) + setCurrent( curRow - 1, curCol); + else if ( smallStyle ) + focusNextPrevChild( FALSE ); + break; + case Key_Down: + if( curRow < numRows()-1 ) + setCurrent( curRow + 1, curCol); + else if ( smallStyle ) + focusNextPrevChild( TRUE ); + break; + case Key_Space: + case Key_Return: + case Key_Enter: + setSelected( curRow, curCol ); + break; + default: // If not an interesting key, + e->ignore(); // we don't accept the event + return; + } + +} + +//////////// TQWellArray END + +static bool initrgb = FALSE; +static TQRgb stdrgb[6*8]; +static TQRgb cusrgb[2*8]; +static bool customSet = FALSE; + + +static void initRGB() +{ + if ( initrgb ) + return; + initrgb = TRUE; + int i = 0; + for ( int g = 0; g < 4; g++ ) + for ( int r = 0; r < 4; r++ ) + for ( int b = 0; b < 3; b++ ) + stdrgb[i++] = qRgb( r*255/3, g*255/3, b*255/2 ); + + for ( i = 0; i < 2*8; i++ ) + cusrgb[i] = qRgb(0xff,0xff,0xff); +} + +/*! + Returns the number of custom colors supported by TQColorDialog. All + color dialogs share the same custom colors. +*/ +int TQColorDialog::customCount() +{ + return 2*8; +} + +/*! + Returns custom color number \a i as a TQRgb. +*/ +TQRgb TQColorDialog::customColor( int i ) +{ + initRGB(); + if ( i < 0 || i >= customCount() ) { +#ifdef QT_CHECK_RANGE + qWarning( "TQColorDialog::customColor() index %d out of range", i ); +#endif + i = 0; + } + return cusrgb[i]; +} + +/*! + Sets custom color number \a i to the TQRgb value \a c. +*/ +void TQColorDialog::setCustomColor( int i, TQRgb c ) +{ + initRGB(); + if ( i < 0 || i >= customCount() ) { +#ifdef QT_CHECK_RANGE + qWarning( "TQColorDialog::setCustomColor() index %d out of range", i ); +#endif + return; + } + customSet = TRUE; + cusrgb[i] = c; +} + +/*! + Sets standard color number \a i to the TQRgb value \a c. +*/ + +void TQColorDialog::setStandardColor( int i, TQRgb c ) +{ + initRGB(); + if ( i < 0 || i >= 6*8 ) { +#ifdef QT_CHECK_RANGE + qWarning( "TQColorDialog::setStandardColor() index %d out of range", i ); +#endif + return; + } + stdrgb[i] = c; +} + +static inline void rgb2hsv( TQRgb rgb, int&h, int&s, int&v ) +{ + TQColor c; + c.setRgb( rgb ); + c.getHsv(h,s,v); +} + +class TQColorWell : public TQWellArray +{ +public: + TQColorWell( TQWidget *parent, int r, int c, TQRgb *vals ) + :TQWellArray( parent, "" ), values( vals ), mousePressed( FALSE ), oldCurrent( -1, -1 ) + { setNumRows(r), setNumCols(c); setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum) ); } + +protected: + void paintCellContents( TQPainter *, int row, int col, const TQRect& ); + void mousePressEvent( TQMouseEvent *e ); + void mouseMoveEvent( TQMouseEvent *e ); + void mouseReleaseEvent( TQMouseEvent *e ); +#ifndef QT_NO_DRAGANDDROP + void dragEnterEvent( TQDragEnterEvent *e ); + void dragLeaveEvent( TQDragLeaveEvent *e ); + void dragMoveEvent( TQDragMoveEvent *e ); + void dropEvent( TQDropEvent *e ); +#endif + +private: + TQRgb *values; + bool mousePressed; + TQPoint pressPos; + TQPoint oldCurrent; + +}; + +void TQColorWell::paintCellContents( TQPainter *p, int row, int col, const TQRect &r ) +{ + int i = row + col*numRows(); + p->fillRect( r, TQColor( values[i] ) ); +} + +void TQColorWell::mousePressEvent( TQMouseEvent *e ) +{ + oldCurrent = TQPoint( selectedRow(), selectedColumn() ); + TQWellArray::mousePressEvent( e ); + mousePressed = TRUE; + pressPos = e->pos(); +} + +void TQColorWell::mouseMoveEvent( TQMouseEvent *e ) +{ + TQWellArray::mouseMoveEvent( e ); +#ifndef QT_NO_DRAGANDDROP + if ( !mousePressed ) + return; + if ( ( pressPos - e->pos() ).manhattanLength() > TQApplication::startDragDistance() ) { + setCurrent( oldCurrent.x(), oldCurrent.y() ); + int i = rowAt(pressPos.y()) + columnAt(pressPos.x()) * numRows(); + TQColor col( values[ i ] ); + TQColorDrag *drg = new TQColorDrag( col, this ); + TQPixmap pix( cellWidth(), cellHeight() ); + pix.fill( col ); + TQPainter p( &pix ); + p.drawRect( 0, 0, pix.width(), pix.height() ); + p.end(); + drg->setPixmap( pix ); + mousePressed = FALSE; + drg->dragCopy(); + } +#endif +} + +#ifndef QT_NO_DRAGANDDROP +void TQColorWell::dragEnterEvent( TQDragEnterEvent *e ) +{ + setFocus(); + if ( TQColorDrag::canDecode( e ) ) + e->accept(); + else + e->ignore(); +} + +void TQColorWell::dragLeaveEvent( TQDragLeaveEvent * ) +{ + if ( hasFocus() ) + parentWidget()->setFocus(); +} + +void TQColorWell::dragMoveEvent( TQDragMoveEvent *e ) +{ + if ( TQColorDrag::canDecode( e ) ) { + setCurrent( rowAt( e->pos().y() ), columnAt( e->pos().x() ) ); + e->accept(); + } else + e->ignore(); +} + +void TQColorWell::dropEvent( TQDropEvent *e ) +{ + if ( TQColorDrag::canDecode( e ) ) { + int i = rowAt( e->pos().y() ) + columnAt( e->pos().x() ) * numRows(); + TQColor col; + TQColorDrag::decode( e, col ); + values[ i ] = col.rgb(); + repaintContents( FALSE ); + e->accept(); + } else { + e->ignore(); + } +} + +#endif // QT_NO_DRAGANDDROP + +void TQColorWell::mouseReleaseEvent( TQMouseEvent *e ) +{ + if ( !mousePressed ) + return; + TQWellArray::mouseReleaseEvent( e ); + mousePressed = FALSE; +} + +class TQColorPicker : public TQFrame +{ + Q_OBJECT +public: + TQColorPicker(TQWidget* parent=0, const char* name=0); + ~TQColorPicker(); + +public slots: + void setCol( int h, int s ); + +signals: + void newCol( int h, int s ); + +protected: + TQSize sizeHint() const; + void drawContents(TQPainter* p); + void mouseMoveEvent( TQMouseEvent * ); + void mousePressEvent( TQMouseEvent * ); + +private: + int hue; + int sat; + + TQPoint colPt(); + int huePt( const TQPoint &pt ); + int satPt( const TQPoint &pt ); + void setCol( const TQPoint &pt ); + + TQPixmap *pix; +}; + +static int pWidth = 200; +static int pHeight = 200; + +class TQColorLuminancePicker : public TQWidget +{ + Q_OBJECT +public: + TQColorLuminancePicker(TQWidget* parent=0, const char* name=0); + ~TQColorLuminancePicker(); + +public slots: + void setCol( int h, int s, int v ); + void setCol( int h, int s ); + +signals: + void newHsv( int h, int s, int v ); + +protected: + void paintEvent( TQPaintEvent*); + void mouseMoveEvent( TQMouseEvent * ); + void mousePressEvent( TQMouseEvent * ); + +private: + enum { foff = 3, coff = 4 }; //frame and contents offset + int val; + int hue; + int sat; + + int y2val( int y ); + int val2y( int val ); + void setVal( int v ); + + TQPixmap *pix; +}; + + +int TQColorLuminancePicker::y2val( int y ) +{ + int d = height() - 2*coff - 1; + return 255 - (y - coff)*255/d; +} + +int TQColorLuminancePicker::val2y( int v ) +{ + int d = height() - 2*coff - 1; + return coff + (255-v)*d/255; +} + +TQColorLuminancePicker::TQColorLuminancePicker(TQWidget* parent, + const char* name) + :TQWidget( parent, name ) +{ + hue = 100; val = 100; sat = 100; + pix = 0; + // setBackgroundMode( NoBackground ); +} + +TQColorLuminancePicker::~TQColorLuminancePicker() +{ + delete pix; +} + +void TQColorLuminancePicker::mouseMoveEvent( TQMouseEvent *m ) +{ + setVal( y2val(m->y()) ); +} +void TQColorLuminancePicker::mousePressEvent( TQMouseEvent *m ) +{ + setVal( y2val(m->y()) ); +} + +void TQColorLuminancePicker::setVal( int v ) +{ + if ( val == v ) + return; + val = TQMAX( 0, TQMIN(v,255)); + delete pix; pix=0; + repaint( FALSE ); //### + emit newHsv( hue, sat, val ); +} + +//receives from a hue,sat chooser and relays. +void TQColorLuminancePicker::setCol( int h, int s ) +{ + setCol( h, s, val ); + emit newHsv( h, s, val ); +} + +void TQColorLuminancePicker::paintEvent( TQPaintEvent * ) +{ + int w = width() - 5; + + TQRect r( 0, foff, w, height() - 2*foff ); + int wi = r.width() - 2; + int hi = r.height() - 2; + if ( !pix || pix->height() != hi || pix->width() != wi ) { + delete pix; + TQImage img( wi, hi, 32 ); + int y; + for ( y = 0; y < hi; y++ ) { + TQColor c( hue, sat, y2val(y+coff), TQColor::Hsv ); + TQRgb r = c.rgb(); + int x; + for ( x = 0; x < wi; x++ ) + img.setPixel( x, y, r ); + } + pix = new TQPixmap; + pix->convertFromImage(img); + } + TQPainter p(this); + p.drawPixmap( 1, coff, *pix ); + const TQColorGroup &g = colorGroup(); + qDrawShadePanel( &p, r, g, TRUE ); + p.setPen( g.foreground() ); + p.setBrush( g.foreground() ); + TQPointArray a; + int y = val2y(val); + a.setPoints( 3, w, y, w+5, y+5, w+5, y-5 ); + erase( w, 0, 5, height() ); + p.drawPolygon( a ); +} + +void TQColorLuminancePicker::setCol( int h, int s , int v ) +{ + val = v; + hue = h; + sat = s; + delete pix; pix=0; + repaint( FALSE );//#### +} + +TQPoint TQColorPicker::colPt() +{ return TQPoint( (360-hue)*(pWidth-1)/360, (255-sat)*(pHeight-1)/255 ); } +int TQColorPicker::huePt( const TQPoint &pt ) +{ return 360 - pt.x()*360/(pWidth-1); } +int TQColorPicker::satPt( const TQPoint &pt ) +{ return 255 - pt.y()*255/(pHeight-1) ; } +void TQColorPicker::setCol( const TQPoint &pt ) +{ setCol( huePt(pt), satPt(pt) ); } + +TQColorPicker::TQColorPicker(TQWidget* parent, const char* name ) + : TQFrame( parent, name ) +{ + hue = 0; sat = 0; + setCol( 150, 255 ); + + TQImage img( pWidth, pHeight, 32 ); + int x,y; + for ( y = 0; y < pHeight; y++ ) + for ( x = 0; x < pWidth; x++ ) { + TQPoint p( x, y ); + img.setPixel( x, y, TQColor(huePt(p), satPt(p), + 200, TQColor::Hsv).rgb() ); + } + pix = new TQPixmap; + pix->convertFromImage(img); + setBackgroundMode( NoBackground ); + setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) ); +} + +TQColorPicker::~TQColorPicker() +{ + delete pix; +} + +TQSize TQColorPicker::sizeHint() const +{ + return TQSize( pWidth + 2*frameWidth(), pHeight + 2*frameWidth() ); +} + +void TQColorPicker::setCol( int h, int s ) +{ + int nhue = TQMIN( TQMAX(0,h), 360 ); + int nsat = TQMIN( TQMAX(0,s), 255); + if ( nhue == hue && nsat == sat ) + return; + TQRect r( colPt(), TQSize(20,20) ); + hue = nhue; sat = nsat; + r = r.unite( TQRect( colPt(), TQSize(20,20) ) ); + r.moveBy( contentsRect().x()-9, contentsRect().y()-9 ); + // update( r ); + repaint( r, FALSE ); +} + +void TQColorPicker::mouseMoveEvent( TQMouseEvent *m ) +{ + TQPoint p = m->pos() - contentsRect().topLeft(); + setCol( p ); + emit newCol( hue, sat ); +} + +void TQColorPicker::mousePressEvent( TQMouseEvent *m ) +{ + TQPoint p = m->pos() - contentsRect().topLeft(); + setCol( p ); + emit newCol( hue, sat ); +} + +void TQColorPicker::drawContents(TQPainter* p) +{ + TQRect r = contentsRect(); + + p->drawPixmap( r.topLeft(), *pix ); + TQPoint pt = colPt() + r.topLeft(); + p->setPen( TQPen(black) ); + + p->fillRect( pt.x()-9, pt.y(), 20, 2, black ); + p->fillRect( pt.x(), pt.y()-9, 2, 20, black ); + +} + +class TQColorShowLabel; + + + +class TQColIntValidator: public TQIntValidator +{ +public: + TQColIntValidator( int bottom, int top, + TQWidget * parent, const char *name = 0 ) + :TQIntValidator( bottom, top, parent, name ) {} + + TQValidator::State validate( TQString &, int & ) const; +}; + +TQValidator::State TQColIntValidator::validate( TQString &s, int &pos ) const +{ + State state = TQIntValidator::validate(s,pos); + if ( state == Valid ) { + long int val = s.toLong(); + // This is not a general solution, assumes that top() > 0 and + // bottom >= 0 + if ( val < 0 ) { + s = "0"; + pos = 1; + } else if ( val > top() ) { + s.setNum( top() ); + pos = s.length(); + } + } + return state; +} + + + +class TQColNumLineEdit : public TQLineEdit +{ +public: + TQColNumLineEdit( TQWidget *parent, const char* name=0 ) + : TQLineEdit( parent, name ) { setMaxLength( 3 );} + TQSize sizeHint() const { + return TQSize( fontMetrics().width( "999" ) + 2 * ( margin() + frameWidth() ), + TQLineEdit::sizeHint().height() ); } + void setNum( int i ) { + TQString s; + s.setNum(i); + bool block = signalsBlocked(); + blockSignals(TRUE); + setText( s ); + blockSignals(block); + } + int val() const { return text().toInt(); } +}; + + +class TQColorShower : public TQWidget +{ + Q_OBJECT +public: + TQColorShower( TQWidget *parent, const char *name=0 ); + + //things that don't emit signals + void setHsv( int h, int s, int v ); + + int currentAlpha() const { return alphaEd->val(); } + void setCurrentAlpha( int a ) { alphaEd->setNum( a ); } + void showAlpha( bool b ); + + + TQRgb currentColor() const { return curCol; } + +public slots: + void setRgb( TQRgb rgb ); + +signals: + void newCol( TQRgb rgb ); +private slots: + void rgbEd(); + void hsvEd(); +private: + void showCurrentColor(); + int hue, sat, val; + TQRgb curCol; + TQColNumLineEdit *hEd; + TQColNumLineEdit *sEd; + TQColNumLineEdit *vEd; + TQColNumLineEdit *rEd; + TQColNumLineEdit *gEd; + TQColNumLineEdit *bEd; + TQColNumLineEdit *alphaEd; + TQLabel *alphaLab; + TQColorShowLabel *lab; + bool rgbOriginal; +}; + +class TQColorShowLabel : public TQFrame +{ + Q_OBJECT + +public: + TQColorShowLabel( TQWidget *parent ) : TQFrame( parent, "qt_colorshow_lbl" ) { + setFrameStyle( TQFrame::Panel|TQFrame::Sunken ); + setBackgroundMode( PaletteBackground ); + setAcceptDrops( TRUE ); + mousePressed = FALSE; + } + void setColor( TQColor c ) { col = c; } + +signals: + void colorDropped( TQRgb ); + +protected: + void drawContents( TQPainter *p ); + void mousePressEvent( TQMouseEvent *e ); + void mouseMoveEvent( TQMouseEvent *e ); + void mouseReleaseEvent( TQMouseEvent *e ); +#ifndef QT_NO_DRAGANDDROP + void dragEnterEvent( TQDragEnterEvent *e ); + void dragLeaveEvent( TQDragLeaveEvent *e ); + void dropEvent( TQDropEvent *e ); +#endif + +private: + TQColor col; + bool mousePressed; + TQPoint pressPos; + +}; + +void TQColorShowLabel::drawContents( TQPainter *p ) +{ + p->fillRect( contentsRect(), col ); +} + +void TQColorShower::showAlpha( bool b ) +{ + if ( b ) { + alphaLab->show(); + alphaEd->show(); + } else { + alphaLab->hide(); + alphaEd->hide(); + } +} + +void TQColorShowLabel::mousePressEvent( TQMouseEvent *e ) +{ + mousePressed = TRUE; + pressPos = e->pos(); +} + +void TQColorShowLabel::mouseMoveEvent( TQMouseEvent *e ) +{ +#ifndef QT_NO_DRAGANDDROP + if ( !mousePressed ) + return; + if ( ( pressPos - e->pos() ).manhattanLength() > TQApplication::startDragDistance() ) { + TQColorDrag *drg = new TQColorDrag( col, this ); + TQPixmap pix( 30, 20 ); + pix.fill( col ); + TQPainter p( &pix ); + p.drawRect( 0, 0, pix.width(), pix.height() ); + p.end(); + drg->setPixmap( pix ); + mousePressed = FALSE; + drg->dragCopy(); + } +#endif +} + +#ifndef QT_NO_DRAGANDDROP +void TQColorShowLabel::dragEnterEvent( TQDragEnterEvent *e ) +{ + if ( TQColorDrag::canDecode( e ) ) + e->accept(); + else + e->ignore(); +} + +void TQColorShowLabel::dragLeaveEvent( TQDragLeaveEvent * ) +{ +} + +void TQColorShowLabel::dropEvent( TQDropEvent *e ) +{ + if ( TQColorDrag::canDecode( e ) ) { + TQColorDrag::decode( e, col ); + repaint( FALSE ); + emit colorDropped( col.rgb() ); + e->accept(); + } else { + e->ignore(); + } +} +#endif // QT_NO_DRAGANDDROP + +void TQColorShowLabel::mouseReleaseEvent( TQMouseEvent * ) +{ + if ( !mousePressed ) + return; + mousePressed = FALSE; +} + +TQColorShower::TQColorShower( TQWidget *parent, const char *name ) + :TQWidget( parent, name) +{ + curCol = qRgb( -1, -1, -1 ); + TQColIntValidator *val256 = new TQColIntValidator( 0, 255, this ); + TQColIntValidator *val360 = new TQColIntValidator( 0, 360, this ); + + TQGridLayout *gl = new TQGridLayout( this, 1, 1, 6 ); + lab = new TQColorShowLabel( this ); + lab->setMinimumWidth( 60 ); //### + gl->addMultiCellWidget(lab, 0,-1,0,0); + connect( lab, SIGNAL( colorDropped(TQRgb) ), + this, SIGNAL( newCol(TQRgb) ) ); + connect( lab, SIGNAL( colorDropped(TQRgb) ), + this, SLOT( setRgb(TQRgb) ) ); + + hEd = new TQColNumLineEdit( this, "qt_hue_edit" ); + hEd->setValidator( val360 ); + TQLabel *l = new TQLabel( hEd, TQColorDialog::tr("Hu&e:"), this, "qt_hue_lbl" ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 0, 1 ); + gl->addWidget( hEd, 0, 2 ); + + sEd = new TQColNumLineEdit( this, "qt_sat_edit" ); + sEd->setValidator( val256 ); + l = new TQLabel( sEd, TQColorDialog::tr("&Sat:"), this, "qt_sat_lbl" ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 1, 1 ); + gl->addWidget( sEd, 1, 2 ); + + vEd = new TQColNumLineEdit( this, "qt_val_edit" ); + vEd->setValidator( val256 ); + l = new TQLabel( vEd, TQColorDialog::tr("&Val:"), this, "qt_val_lbl" ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 2, 1 ); + gl->addWidget( vEd, 2, 2 ); + + rEd = new TQColNumLineEdit( this, "qt_red_edit" ); + rEd->setValidator( val256 ); + l = new TQLabel( rEd, TQColorDialog::tr("&Red:"), this, "qt_red_lbl" ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 0, 3 ); + gl->addWidget( rEd, 0, 4 ); + + gEd = new TQColNumLineEdit( this, "qt_grn_edit" ); + gEd->setValidator( val256 ); + l = new TQLabel( gEd, TQColorDialog::tr("&Green:"), this, "qt_grn_lbl" ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 1, 3 ); + gl->addWidget( gEd, 1, 4 ); + + bEd = new TQColNumLineEdit( this, "qt_blue_edit" ); + bEd->setValidator( val256 ); + l = new TQLabel( bEd, TQColorDialog::tr("Bl&ue:"), this, "qt_blue_lbl" ); + l->setAlignment( AlignRight|AlignVCenter ); + gl->addWidget( l, 2, 3 ); + gl->addWidget( bEd, 2, 4 ); + + alphaEd = new TQColNumLineEdit( this, "qt_aplha_edit" ); + alphaEd->setValidator( val256 ); + alphaLab = new TQLabel( alphaEd, TQColorDialog::tr("A&lpha channel:"), this, "qt_alpha_lbl" ); + alphaLab->setAlignment( AlignRight|AlignVCenter ); + gl->addMultiCellWidget( alphaLab, 3, 3, 1, 3 ); + gl->addWidget( alphaEd, 3, 4 ); + alphaEd->hide(); + alphaLab->hide(); + + connect( hEd, SIGNAL(textChanged(const TQString&)), this, SLOT(hsvEd()) ); + connect( sEd, SIGNAL(textChanged(const TQString&)), this, SLOT(hsvEd()) ); + connect( vEd, SIGNAL(textChanged(const TQString&)), this, SLOT(hsvEd()) ); + + connect( rEd, SIGNAL(textChanged(const TQString&)), this, SLOT(rgbEd()) ); + connect( gEd, SIGNAL(textChanged(const TQString&)), this, SLOT(rgbEd()) ); + connect( bEd, SIGNAL(textChanged(const TQString&)), this, SLOT(rgbEd()) ); + connect( alphaEd, SIGNAL(textChanged(const TQString&)), this, SLOT(rgbEd()) ); +} + +void TQColorShower::showCurrentColor() +{ + lab->setColor( currentColor() ); + lab->repaint(FALSE); //### +} + +void TQColorShower::rgbEd() +{ + rgbOriginal = TRUE; + if ( alphaEd->isVisible() ) + curCol = qRgba( rEd->val(), gEd->val(), bEd->val(), currentAlpha() ); + else + curCol = qRgb( rEd->val(), gEd->val(), bEd->val() ); + + rgb2hsv(currentColor(), hue, sat, val ); + + hEd->setNum( hue ); + sEd->setNum( sat ); + vEd->setNum( val ); + + showCurrentColor(); + emit newCol( currentColor() ); +} + +void TQColorShower::hsvEd() +{ + rgbOriginal = FALSE; + hue = hEd->val(); + sat = sEd->val(); + val = vEd->val(); + + curCol = TQColor( hue, sat, val, TQColor::Hsv ).rgb(); + + rEd->setNum( qRed(currentColor()) ); + gEd->setNum( qGreen(currentColor()) ); + bEd->setNum( qBlue(currentColor()) ); + + showCurrentColor(); + emit newCol( currentColor() ); +} + +void TQColorShower::setRgb( TQRgb rgb ) +{ + rgbOriginal = TRUE; + curCol = rgb; + + rgb2hsv( currentColor(), hue, sat, val ); + + hEd->setNum( hue ); + sEd->setNum( sat ); + vEd->setNum( val ); + + rEd->setNum( qRed(currentColor()) ); + gEd->setNum( qGreen(currentColor()) ); + bEd->setNum( qBlue(currentColor()) ); + + showCurrentColor(); +} + +void TQColorShower::setHsv( int h, int s, int v ) +{ + rgbOriginal = FALSE; + hue = h; val = v; sat = s; //Range check### + curCol = TQColor( hue, sat, val, TQColor::Hsv ).rgb(); + + hEd->setNum( hue ); + sEd->setNum( sat ); + vEd->setNum( val ); + + rEd->setNum( qRed(currentColor()) ); + gEd->setNum( qGreen(currentColor()) ); + bEd->setNum( qBlue(currentColor()) ); + + showCurrentColor(); +} + +class TQColorDialogPrivate : public TQObject +{ +Q_OBJECT +public: + TQColorDialogPrivate( TQColorDialog *p ); + TQRgb currentColor() const { return cs->currentColor(); } + void setCurrentColor( TQRgb rgb ); + + int currentAlpha() const { return cs->currentAlpha(); } + void setCurrentAlpha( int a ) { cs->setCurrentAlpha( a ); } + void showAlpha( bool b ) { cs->showAlpha( b ); } + +public slots: + void addCustom(); + + void newHsv( int h, int s, int v ); + void newColorTypedIn( TQRgb rgb ); + void newCustom( int, int ); + void newStandard( int, int ); +public: + TQWellArray *custom; + TQWellArray *standard; + + TQColorPicker *cp; + TQColorLuminancePicker *lp; + TQColorShower *cs; + int nextCust; + bool compact; +}; + +//sets all widgets to display h,s,v +void TQColorDialogPrivate::newHsv( int h, int s, int v ) +{ + cs->setHsv( h, s, v ); + cp->setCol( h, s ); + lp->setCol( h, s, v ); +} + +//sets all widgets to display rgb +void TQColorDialogPrivate::setCurrentColor( TQRgb rgb ) +{ + cs->setRgb( rgb ); + newColorTypedIn( rgb ); +} + +//sets all widgets exept cs to display rgb +void TQColorDialogPrivate::newColorTypedIn( TQRgb rgb ) +{ + int h, s, v; + rgb2hsv(rgb, h, s, v ); + cp->setCol( h, s ); + lp->setCol( h, s, v); +} + +void TQColorDialogPrivate::newCustom( int r, int c ) +{ + int i = r+2*c; + setCurrentColor( cusrgb[i] ); + nextCust = i; + if (standard) + standard->setSelected(-1,-1); +} + +void TQColorDialogPrivate::newStandard( int r, int c ) +{ + setCurrentColor( stdrgb[r+c*6] ); + if (custom) + custom->setSelected(-1,-1); +} + +TQColorDialogPrivate::TQColorDialogPrivate( TQColorDialog *dialog ) : + TQObject(dialog) +{ + compact = FALSE; + // small displays (e.g. PDAs cannot fit the full color dialog, + // so just use the color picker. + if ( qApp->desktop()->width() < 480 || qApp->desktop()->height() < 350 ) + compact = TRUE; + + nextCust = 0; + const int lumSpace = 3; + int border = 12; + if ( compact ) + border = 6; + TQHBoxLayout *topLay = new TQHBoxLayout( dialog, border, 6 ); + TQVBoxLayout *leftLay = 0; + + if ( !compact ) + leftLay = new TQVBoxLayout( topLay ); + + initRGB(); + + if ( !compact ) { + standard = new TQColorWell( dialog, 6, 8, stdrgb ); + standard->setCellWidth( 28 ); + standard->setCellHeight( 24 ); + TQLabel * lab = new TQLabel( standard, + TQColorDialog::tr( "&Basic colors"), dialog, "qt_basiccolors_lbl" ); + connect( standard, SIGNAL(selected(int,int)), SLOT(newStandard(int,int))); + leftLay->addWidget( lab ); + leftLay->addWidget( standard ); + + + leftLay->addStretch(); + + custom = new TQColorWell( dialog, 2, 8, cusrgb ); + custom->setCellWidth( 28 ); + custom->setCellHeight( 24 ); + custom->setAcceptDrops( TRUE ); + + connect( custom, SIGNAL(selected(int,int)), SLOT(newCustom(int,int))); + lab = new TQLabel( custom, TQColorDialog::tr( "&Custom colors") , dialog, "qt_custcolors_lbl" ); + leftLay->addWidget( lab ); + leftLay->addWidget( custom ); + + TQPushButton *custbut = + new TQPushButton( TQColorDialog::tr("&Define Custom Colors >>"), + dialog, "qt_def_custcolors_lbl" ); + custbut->setEnabled( FALSE ); + leftLay->addWidget( custbut ); + } else { + // better color picker size for small displays + pWidth = 150; + pHeight = 100; + + custom = 0; + standard = 0; + } + + TQVBoxLayout *rightLay = new TQVBoxLayout( topLay ); + + TQHBoxLayout *pickLay = new TQHBoxLayout( rightLay ); + + + TQVBoxLayout *cLay = new TQVBoxLayout( pickLay ); + cp = new TQColorPicker( dialog, "qt_colorpicker" ); + cp->setFrameStyle( TQFrame::Panel + TQFrame::Sunken ); + cLay->addSpacing( lumSpace ); + cLay->addWidget( cp ); + cLay->addSpacing( lumSpace ); + + lp = new TQColorLuminancePicker( dialog, "qt_luminance_picker" ); + lp->setFixedWidth( 20 ); //### + pickLay->addWidget( lp ); + + connect( cp, SIGNAL(newCol(int,int)), lp, SLOT(setCol(int,int)) ); + connect( lp, SIGNAL(newHsv(int,int,int)), this, SLOT(newHsv(int,int,int)) ); + + rightLay->addStretch(); + + cs = new TQColorShower( dialog, "qt_colorshower" ); + connect( cs, SIGNAL(newCol(TQRgb)), this, SLOT(newColorTypedIn(TQRgb))); + rightLay->addWidget( cs ); + + TQHBoxLayout *buttons; + if ( compact ) + buttons = new TQHBoxLayout( rightLay ); + else + buttons = new TQHBoxLayout( leftLay ); + + TQPushButton *ok, *cancel; + ok = new TQPushButton( TQColorDialog::tr("OK"), dialog, "qt_ok_btn" ); + connect( ok, SIGNAL(clicked()), dialog, SLOT(accept()) ); + ok->setDefault(TRUE); + cancel = new TQPushButton( TQColorDialog::tr("Cancel"), dialog, "qt_cancel_btn" ); + connect( cancel, SIGNAL(clicked()), dialog, SLOT(reject()) ); + buttons->addWidget( ok ); + buttons->addWidget( cancel ); + buttons->addStretch(); + + if ( !compact ) { + TQPushButton *addCusBt = new TQPushButton( + TQColorDialog::tr("&Add to Custom Colors"), + dialog, "qt_add_btn" ); + rightLay->addWidget( addCusBt ); + connect( addCusBt, SIGNAL(clicked()), this, SLOT(addCustom()) ); + } +} + +void TQColorDialogPrivate::addCustom() +{ + cusrgb[nextCust] = cs->currentColor(); + if (custom) + custom->repaintContents( FALSE ); + nextCust = (nextCust+1) % 16; +} + + +/*! + \class TQColorDialog qcolordialog.h + \brief The TQColorDialog class provides a dialog widget for specifying colors. + \mainclass + \ingroup dialogs + \ingroup graphics + + The color dialog's function is to allow users to choose colors. + For example, you might use this in a drawing program to allow the + user to set the brush color. + + The static functions provide modal color dialogs. + \omit + If you retquire a modeless dialog, use the TQColorDialog constructor. + \endomit + + The static getColor() function shows the dialog and allows the + user to specify a color. The getRgba() function does the same but + also allows the user to specify a color with an alpha channel + (transparency) value. + + The user can store customCount() different custom colors. The + custom colors are shared by all color dialogs, and remembered + during the execution of the program. Use setCustomColor() to set + the custom colors, and use customColor() to get them. + + \img qcolordlg-w.png +*/ + +/*! + Constructs a default color dialog with parent \a parent and called + \a name. If \a modal is TRUE the dialog will be modal. Use + setColor() to set an initial value. + + \sa getColor() +*/ + +TQColorDialog::TQColorDialog(TQWidget* parent, const char* name, bool modal) : + TQDialog(parent, name, modal, ( WType_Dialog | WStyle_Customize | WStyle_Title | + WStyle_DialogBorder | WStyle_SysMenu ) ) +{ + setSizeGripEnabled( FALSE ); + d = new TQColorDialogPrivate( this ); + +#ifndef QT_NO_SETTINGS + if ( !customSet ) { + TQSettings settings; + settings.insertSearchPath( TQSettings::Windows, "/Trolltech" ); + for ( int i = 0; i < 2*8; ++i ) { + bool ok = FALSE; + TQRgb rgb = (TQRgb)settings.readNumEntry( "/TQt/customColors/" + TQString::number( i ), 0, &ok ); + if ( ok ) + cusrgb[i] = rgb; + } + } +#endif +} + +/*! + Pops up a modal color dialog, lets the user choose a color, and + returns that color. The color is initially set to \a initial. The + dialog is a child of \a parent and is called \a name. It returns + an invalid (see TQColor::isValid()) color if the user cancels the + dialog. All colors allocated by the dialog will be deallocated + before this function returns. +*/ + +TQColor TQColorDialog::getColor( const TQColor& initial, TQWidget *parent, + const char *name ) +{ +#if defined(Q_WS_X11) + if( TQKDEIntegration::enabled()) + return TQKDEIntegration::getColor( initial, parent, name ); +#elif defined(Q_WS_MAC) + return macGetColor(initial, parent, name); +#endif + + int allocContext = TQColor::enterAllocContext(); + TQColorDialog *dlg = new TQColorDialog( parent, name, TRUE ); //modal +#ifndef QT_NO_WIDGET_TOPEXTRA + dlg->setCaption( TQColorDialog::tr( "Select color" ) ); +#endif + dlg->setColor( initial ); + dlg->selectColor( initial ); + int resultCode = dlg->exec(); + TQColor::leaveAllocContext(); + TQColor result; + if ( resultCode == TQDialog::Accepted ) + result = dlg->color(); + TQColor::destroyAllocContext(allocContext); + delete dlg; + return result; +} + + +/*! + Pops up a modal color dialog to allow the user to choose a color + and an alpha channel (transparency) value. The color+alpha is + initially set to \a initial. The dialog is a child of \a parent + and called \a name. + + If \a ok is non-null, \e *\a ok is set to TRUE if the user clicked + OK, and to FALSE if the user clicked Cancel. + + If the user clicks Cancel, the \a initial value is returned. +*/ + +TQRgb TQColorDialog::getRgba( TQRgb initial, bool *ok, + TQWidget *parent, const char* name ) +{ +#if defined(Q_WS_MAC) + if( TQKDEIntegration::enabled()) { + TQColor color = TQKDEIntegration::getColor( TQColor( initial ), parent, name ); + if( ok ) + *ok = color.isValid(); + return color.rgba(); + } +#elif defined(Q_WS_MAC) + return macGetRgba(initial, ok, parent, name); +#endif + + int allocContext = TQColor::enterAllocContext(); + TQColorDialog *dlg = new TQColorDialog( parent, name, TRUE ); //modal + + Q_CHECK_PTR( dlg ); +#ifndef QT_NO_WIDGET_TOPEXTRA + dlg->setCaption( TQColorDialog::tr( "Select color" ) ); +#endif + dlg->setColor( initial ); + dlg->selectColor( initial ); + dlg->setSelectedAlpha( qAlpha(initial) ); + int resultCode = dlg->exec(); + TQColor::leaveAllocContext(); + TQRgb result = initial; + if ( resultCode == TQDialog::Accepted ) { + TQRgb c = dlg->color().rgb(); + int alpha = dlg->selectedAlpha(); + result = qRgba( qRed(c), qGreen(c), qBlue(c), alpha ); + } + if ( ok ) + *ok = resultCode == TQDialog::Accepted; + + TQColor::destroyAllocContext(allocContext); + delete dlg; + return result; +} + + + + + +/*! + Returns the color currently selected in the dialog. + + \sa setColor() +*/ + +TQColor TQColorDialog::color() const +{ + return TQColor(d->currentColor()); +} + + +/*! + Destroys the dialog and frees any memory it allocated. +*/ + +TQColorDialog::~TQColorDialog() +{ +#ifndef QT_NO_SETTINGS + if ( !customSet ) { + TQSettings settings; + settings.insertSearchPath( TQSettings::Windows, "/Trolltech" ); + for ( int i = 0; i < 2*8; ++i ) + settings.writeEntry( "/TQt/customColors/" + TQString::number( i ), (int)cusrgb[i] ); + } +#endif +} + + +/*! + Sets the color shown in the dialog to \a c. + + \sa color() +*/ + +void TQColorDialog::setColor( const TQColor& c ) +{ + d->setCurrentColor( c.rgb() ); +} + + + + +/*! + Sets the initial alpha channel value to \a a, and shows the alpha + channel entry box. +*/ + +void TQColorDialog::setSelectedAlpha( int a ) +{ + d->showAlpha( TRUE ); + d->setCurrentAlpha( a ); +} + + +/*! + Returns the value selected for the alpha channel. +*/ + +int TQColorDialog::selectedAlpha() const +{ + return d->currentAlpha(); +} + +/*! + Sets focus to the corresponding button, if any. +*/ +bool TQColorDialog::selectColor( const TQColor& col ) +{ + TQRgb color = col.rgb(); + int i = 0, j = 0; + // Check standard colors + if (d->standard) { + for ( i = 0; i < 6; i++ ) { + for ( j = 0; j < 8; j++ ) { + if ( color == stdrgb[i + j*6] ) { + d->newStandard( i, j ); + d->standard->setCurrent( i, j ); + d->standard->setSelected( i, j ); + d->standard->setFocus(); + return TRUE; + } + } + } + } + // Check custom colors + if (d->custom) { + for ( i = 0; i < 2; i++ ) { + for ( j = 0; j < 8; j++ ) { + if ( color == cusrgb[i + j*2] ) { + d->newCustom( i, j ); + d->custom->setCurrent( i, j ); + d->custom->setSelected( i, j ); + d->custom->setFocus(); + return TRUE; + } + } + } + } + return FALSE; +} + +#include "qcolordialog.moc" + +#endif diff --git a/src/dialogs/qcolordialog.h b/src/dialogs/qcolordialog.h new file mode 100644 index 000000000..eff846a82 --- /dev/null +++ b/src/dialogs/qcolordialog.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Definition of TQColorDialog class +** +** Created : 990222 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQCOLORDIALOG_H +#define TQCOLORDIALOG_H + +#ifndef QT_H +#include "qdialog.h" +#endif // QT_H + +#ifndef QT_NO_COLORDIALOG + +class TQColorDialogPrivate; + +class Q_EXPORT TQColorDialog : public TQDialog +{ + Q_OBJECT + +public: + static TQColor getColor( const TQColor& init = white, TQWidget* parent=0, const char* name=0 ); + static TQRgb getRgba( TQRgb, bool* ok = 0, + TQWidget* parent=0, const char* name=0 ); + + static int customCount(); + static TQRgb customColor( int ); + static void setCustomColor( int, TQRgb ); + static void setStandardColor( int, TQRgb ); + +private: + ~TQColorDialog(); + TQColorDialog( TQWidget* parent=0, const char* name=0, bool modal=FALSE ); + + void setColor( const TQColor& ); + TQColor color() const; + + bool selectColor( const TQColor& ); + + void setSelectedAlpha( int ); + int selectedAlpha() const; + + void showCustom( bool=TRUE ); + +private: // Disabled copy constructor and operator= + TQColorDialogPrivate *d; + friend class TQColorDialogPrivate; + friend class TQColorShower; + +#if defined(Q_DISABLE_COPY) + TQColorDialog( const TQColorDialog & ); + TQColorDialog& operator=( const TQColorDialog & ); +#endif +}; + +#endif + +#endif //TQCOLORDIALOG_H diff --git a/src/dialogs/qdialog.cpp b/src/dialogs/qdialog.cpp new file mode 100644 index 000000000..6bd440def --- /dev/null +++ b/src/dialogs/qdialog.cpp @@ -0,0 +1,1178 @@ +/**************************************************************************** +** +** Implementation of TQDialog class +** +** Created : 950502 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qdialog.h" + +#ifndef QT_NO_DIALOG + +#include "qpushbutton.h" +#include "qfocusdata.h" +#include "qapplication.h" +#include "qobjectlist.h" +#include "qwidgetlist.h" +#include "qlayout.h" +#include "qsizegrip.h" +#include "qwhatsthis.h" +#include "qpopupmenu.h" +#include "qcursor.h" +#if defined(QT_ACCESSIBILITY_SUPPORT) +#include "qaccessible.h" +#endif +#if defined( Q_OS_TEMP ) +#include "qt_windows.h" +#endif + +/*! + \class TQDialog + \brief The TQDialog class is the base class of dialog windows. + + \ingroup dialogs + \ingroup abstractwidgets + \mainclass + + A dialog window is a top-level window mostly used for short-term + tasks and brief communications with the user. TQDialogs may be + modal or modeless. TQDialogs support \link #extensibility + extensibility\endlink and can provide a \link #return return + value\endlink. They can have \link #default default + buttons\endlink. TQDialogs can also have a TQSizeGrip in their + lower-right corner, using setSizeGripEnabled(). + + Note that TQDialog uses the parent widget slightly differently from + other classes in TQt. A dialog is always a top-level widget, but if + it has a parent, its default location is centered on top of the + parent's top-level widget (if it is not top-level itself). It will + also share the parent's taskbar entry. + + \target modal + \section1 Modal Dialogs + + A <b>modal</b> dialog is a dialog that blocks input to other + visible windows in the same application. Users must finish + interacting with the dialog and close it before they can access + any other window in the application. Dialogs that are used to + request a file name from the user or that are used to set + application preferences are usually modal. + + The most common way to display a modal dialog is to call its + exec() function. When the user closes the dialog, exec() will + provide a useful \link #return return value\endlink. Typically we + connect a default button, e.g. "OK", to the accept() slot and a + "Cancel" button to the reject() slot, to get the dialog to close + and return the appropriate value. Alternatively you can connect to + the done() slot, passing it \c Accepted or \c Rejected. + + An alternative is to call setModal(TRUE), then show(). Unlike + exec(), show() returns control to the caller immediately. Calling + setModal(TRUE) is especially useful for progress dialogs, where + the user must have the ability to interact with the dialog, e.g. + to cancel a long running operation. If you use show() and + setModal(TRUE) together you must call + TQApplication::processEvents() periodically during processing to + enable the user to interact with the dialog. (See \l + TQProgressDialog.) + + \target modeless + \section1 Modeless Dialogs + + A <b>modeless</b> dialog is a dialog that operates + independently of other windows in the same application. Find and + replace dialogs in word-processors are often modeless to allow the + user to interact with both the application's main window and with + the dialog. + + Modeless dialogs are displayed using show(), which returns control + to the caller immediately. + + \target default + \section1 Default button + + A dialog's \e default button is the button that's pressed when the + user presses Enter (Return). This button is used to signify that + the user accepts the dialog's settings and wants to close the + dialog. Use TQPushButton::setDefault(), TQPushButton::isDefault() + and TQPushButton::autoDefault() to set and control the dialog's + default button. + + \target escapekey + \section1 Escape Key + + If the user presses the Esc key in a dialog, TQDialog::reject() + will be called. This will cause the window to close: the \link + TQCloseEvent closeEvent \endlink cannot be \link + TQCloseEvent::ignore() ignored \endlink. + + \target extensibility + \section1 Extensibility + + Extensibility is the ability to show the dialog in two ways: a + partial dialog that shows the most commonly used options, and a + full dialog that shows all the options. Typically an extensible + dialog will initially appear as a partial dialog, but with a + "More" toggle button. If the user presses the "More" button down, + the full dialog will appear. The extension widget will be resized + to its sizeHint(). If orientation is \c Horizontal the extension + widget's height() will be expanded to the height() of the dialog. + If the orientation is \c Vertical the extension widget's width() + will be expanded to the width() of the dialog. Extensibility is + controlled with setExtension(), setOrientation() and + showExtension(). + + \target return + \section1 Return value (modal dialogs) + + Modal dialogs are often used in situations where a return value is + retquired, e.g. to indicate whether the user pressed "OK" or + "Cancel". A dialog can be closed by calling the accept() or the + reject() slots, and exec() will return \c Accepted or \c Rejected + as appropriate. The exec() call returns the result of the dialog. + The result is also available from result() if the dialog has not + been destroyed. If the \c WDestructiveClose flag is set, the + dialog is deleted after exec() returns. + + \target examples + \section1 Examples + + A modal dialog. + + \quotefile network/networkprotocol/view.cpp + \skipto TQFileDialog *dlg + \printuntil return + + A modeless dialog. After the show() call, control returns to the main + event loop. + \quotefile life/main.cpp + \skipto argv + \printuntil TQApplication + \skipto scale + \printline + \skipto LifeDialog + \printuntil show + \skipto exec + \printuntil } + + \sa TQTabDialog TQWidget TQProgressDialog + \link guibooks.html#fowler GUI Design Handbook: Dialogs, Standard\endlink +*/ + +/*! \enum TQDialog::DialogCode + + The value returned by a modal dialog. + + \value Accepted + \value Rejected + +*/ + +/*! + \property TQDialog::sizeGripEnabled + \brief whether the size grip is enabled + + A TQSizeGrip is placed in the bottom right corner of the dialog when this + property is enabled. By default, the size grip is disabled. +*/ + +class TQDialogPrivate : public TQt +{ +public: + + TQDialogPrivate() + : mainDef(0), orientation(Horizontal),extension(0), doShowExtension(FALSE) +#ifndef QT_NO_SIZEGRIP + ,resizer(0) +#endif + { + } + + TQPushButton* mainDef; + Orientation orientation; + TQWidget* extension; + bool doShowExtension; + TQSize size, min, max; +#ifndef QT_NO_SIZEGRIP + TQSizeGrip* resizer; +#endif + TQPoint lastRMBPress; + TQPoint relPos; // relative position to the main window +}; + +/*! + Constructs a dialog called \a name, with parent \a parent. + + A dialog is always a top-level widget, but if it has a parent, its + default location is centered on top of the parent. It will also + share the parent's taskbar entry. + + The widget flags \a f are passed on to the TQWidget constructor. + If, for example, you don't want a What's This button in the titlebar + of the dialog, pass WStyle_Customize | WStyle_NormalBorder | + WStyle_Title | WStyle_SysMenu in \a f. + + \warning In TQt 3.2, the \a modal flag is obsolete. There is now a + setModal() function that can be used for obtaining a modal behavior + when calling show(). This is rarely needed, because modal dialogs + are usually invoked using exec(), which ignores the \a modal flag. + + \sa TQWidget::setWFlags() TQt::WidgetFlags +*/ + +TQDialog::TQDialog( TQWidget *parent, const char *name, bool modal, WFlags f ) + : TQWidget( parent, name, + (modal ? (f|WShowModal) : f) | WType_Dialog ), + rescode(0), did_move(0), has_relpos(0), did_resize(0), in_loop(0) +{ + d = new TQDialogPrivate; +} + +/*! + Destroys the TQDialog, deleting all its children. +*/ + +TQDialog::~TQDialog() +{ + // Need to hide() here, as our (to-be) overridden hide() + // will not be called in ~TQWidget. + hide(); + delete d; +} + +/*! + \internal + This function is called by the push button \a pushButton when it + becomes the default button. If \a pushButton is 0, the dialogs + default default button becomes the default button. This is what a + push button calls when it loses focus. +*/ + +void TQDialog::setDefault( TQPushButton *pushButton ) +{ +#ifndef QT_NO_PUSHBUTTON + TQObjectList *list = queryList( "TQPushButton" ); + Q_ASSERT(list); + TQObjectListIt it( *list ); + TQPushButton *pb; + bool hasMain = FALSE; + while ( (pb = (TQPushButton*)it.current()) ) { + ++it; + if ( pb->topLevelWidget() != this ) + continue; + if ( pb == d->mainDef ) + hasMain = TRUE; + if ( pb != pushButton ) + pb->setDefault( FALSE ); + } + if (!pushButton && hasMain) + d->mainDef->setDefault( TRUE ); + if (!hasMain) + d->mainDef = pushButton; + delete list; +#endif +} + +/*! + \internal + This function sets the default default pushbutton to \a pushButton. + This function is called by TQPushButton::setDefault(). +*/ +void TQDialog::setMainDefault( TQPushButton *pushButton ) +{ +#ifndef QT_NO_PUSHBUTTON + d->mainDef = 0; + setDefault(pushButton); +#endif +} + +/*! + \internal + Hides the default button indicator. Called when non auto-default + push button get focus. + */ +void TQDialog::hideDefault() +{ +#ifndef QT_NO_PUSHBUTTON + TQObjectList *list = queryList( "TQPushButton" ); + TQObjectListIt it( *list ); + TQPushButton *pb; + while ( (pb = (TQPushButton*)it.current()) ) { + ++it; + pb->setDefault( FALSE ); + } + delete list; +#endif +} + +#ifdef Q_OS_TEMP +/*! + \internal + Hides special buttons which are rather shown in the titlebar + on WinCE, to conserve screen space. +*/ +# include "qmessagebox.h" +extern const char * mb_texts[]; // Defined in qmessagebox.cpp +void TQDialog::hideSpecial() +{ + // "OK" buttons are hidden, and (Ok) shown on titlebar + // "Cancel" buttons are hidden, and (X) shown on titlebar + // "Help" buttons are hidden, and (?) shown on titlebar + bool showOK = FALSE, + showX = FALSE, + showQ = FALSE; + TQObjectList *list = queryList( "TQPushButton" ); + TQObjectListIt it( *list ); + TQPushButton *pb; + while ( (pb = (TQPushButton*)it.current()) ) { + if ( !showOK && + pb->text() == qApp->translate( "TQMessageBox", mb_texts[TQMessageBox::Ok] ) ) { + pb->hide(); + showOK = TRUE; + } else if ( !showX && + pb->text() == qApp->translate( "TQMessageBox", mb_texts[TQMessageBox::Cancel] ) ) { + pb->hide(); + showX = TRUE; + } else if ( !showQ && + pb->text() == qApp->tr("Help") ) { + pb->hide(); + showQ = TRUE; + } + ++it; + } + delete list; + if ( showOK || showQ ) { + DWORD ext = GetWindowLong( winId(), GWL_EXSTYLE ); + ext |= showOK ? WS_EX_CAPTIONOKBTN : 0; + ext |= showQ ? WS_EX_CONTEXTHELP: 0; + SetWindowLong( winId(), GWL_EXSTYLE, ext ); + } + if ( !showX ) { + DWORD ext = GetWindowLong( winId(), GWL_STYLE ); + ext &= ~WS_SYSMENU; + SetWindowLong( winId(), GWL_STYLE, ext ); + } +} +#endif + +/*! + \fn int TQDialog::result() const + + Returns the modal dialog's result code, \c Accepted or \c Rejected. + + Do not call this function if the dialog was constructed with the \c + WDestructiveClose flag. +*/ + +/*! + \fn void TQDialog::setResult( int i ) + + Sets the modal dialog's result code to \a i. +*/ + + +/*! + Shows the dialog as a \link #modal modal \endlink dialog, + blocking until the user closes it. The function returns a \l + DialogCode result. + + Users cannot interact with any other window in the same + application until they close the dialog. + + \sa show(), result() +*/ + +int TQDialog::exec() +{ + if ( in_loop ) { + qWarning( "TQDialog::exec: Recursive call detected" ); + return -1; + } + + bool destructiveClose = testWFlags( WDestructiveClose ); + clearWFlags( WDestructiveClose ); + + bool wasShowModal = testWFlags( WShowModal ); + setWFlags( WShowModal ); + setResult( 0 ); + + show(); + + in_loop = TRUE; + qApp->enter_loop(); + + if ( !wasShowModal ) + clearWFlags( WShowModal ); + + int res = result(); + + if ( destructiveClose ) + delete this; + + return res; +} + + +/*! Closes the dialog and sets its result code to \a r. If this dialog + is shown with exec(), done() causes the local event loop to finish, + and exec() to return \a r. + + As with TQWidget::close(), done() deletes the dialog if the \c + WDestructiveClose flag is set. If the dialog is the application's + main widget, the application terminates. If the dialog is the + last window closed, the TQApplication::lastWindowClosed() signal is + emitted. + + \sa accept(), reject(), TQApplication::mainWidget(), TQApplication::tquit() +*/ + +void TQDialog::done( int r ) +{ + hide(); + setResult( r ); + + // emulate TQWidget::close() + bool isMain = qApp->mainWidget() == this; + bool checkLastWindowClosed = isTopLevel() && !isPopup(); + if ( checkLastWindowClosed + && qApp->receivers(SIGNAL(lastWindowClosed())) ) { + /* if there is no non-withdrawn top level window left (except + the desktop, popups, or dialogs with parents), we emit the + lastWindowClosed signal */ + TQWidgetList *list = qApp->topLevelWidgets(); + TQWidget *widget = list->first(); + while ( widget ) { + if ( !widget->isHidden() + && !widget->isDesktop() + && !widget->isPopup() + && (!widget->isDialog() || !widget->parentWidget())) + break; + widget = list->next(); + } + delete list; + if ( widget == 0 ) + emit qApp->lastWindowClosed(); + } + if ( isMain ) + qApp->tquit(); + else if ( testWFlags(WDestructiveClose) ) { + clearWFlags(WDestructiveClose); + deleteLater(); + } +} + +/*! + Hides the modal dialog and sets the result code to \c Accepted. + + \sa reject() done() +*/ + +void TQDialog::accept() +{ + done( Accepted ); +} + +/*! + Hides the modal dialog and sets the result code to \c Rejected. + + \sa accept() done() +*/ + +void TQDialog::reject() +{ + done( Rejected ); +} + +/*! \reimp */ +bool TQDialog::eventFilter( TQObject *o, TQEvent *e ) +{ + return TQWidget::eventFilter( o, e ); +} + +/***************************************************************************** + Event handlers + *****************************************************************************/ + +/*! \reimp */ +void TQDialog::contextMenuEvent( TQContextMenuEvent *e ) +{ +#if !defined(QT_NO_WHATSTHIS) && !defined(QT_NO_POPUPMENU) + TQWidget* w = childAt( e->pos(), TRUE ); + if ( !w ) + return; + TQString s; + while ( s.isEmpty() && w ) { + s = TQWhatsThis::textFor( w, e->pos(), FALSE ); + if ( s.isEmpty() ) + w = w->parentWidget(TRUE); + } + if ( !s.isEmpty() ) { + TQPopupMenu p(0,"qt_whats_this_menu"); + p.insertItem( tr("What's This?"), 42 ); + if ( p.exec( e->globalPos() ) >= 42 ) + TQWhatsThis::display( s, w->mapToGlobal( w->rect().center() ), w ); + } +#endif +} + +/*! \reimp */ +void TQDialog::keyPressEvent( TQKeyEvent *e ) +{ + // Calls reject() if Escape is pressed. Simulates a button + // click for the default button if Enter is pressed. Move focus + // for the arrow keys. Ignore the rest. +#ifdef Q_OS_MAC + if(e->state() == ControlButton && e->key() == Key_Period) { + reject(); + } else +#endif + if ( e->state() == 0 || ( e->state() & Keypad && e->key() == Key_Enter ) ) { + switch ( e->key() ) { + case Key_Enter: + case Key_Return: { +#ifndef QT_NO_PUSHBUTTON + TQObjectList *list = queryList( "TQPushButton" ); + TQObjectListIt it( *list ); + TQPushButton *pb; + while ( (pb = (TQPushButton*)it.current()) ) { + if ( pb->isDefault() && pb->isVisible() ) { + delete list; + if ( pb->isEnabled() ) { + emit pb->clicked(); + } + return; + } + ++it; + } + delete list; +#endif + } + break; + case Key_Escape: + reject(); + break; + case Key_Up: + case Key_Left: + if ( focusWidget() && + ( focusWidget()->focusPolicy() == TQWidget::StrongFocus || + focusWidget()->focusPolicy() == TQWidget::WheelFocus ) ) { + e->ignore(); + break; + } + // call ours, since c++ blocks us from calling the one + // belonging to focusWidget(). + TQFocusEvent::setReason(TQFocusEvent::Backtab); + focusNextPrevChild( FALSE ); + TQFocusEvent::resetReason(); + break; + case Key_Down: + case Key_Right: + if ( focusWidget() && + ( focusWidget()->focusPolicy() == TQWidget::StrongFocus || + focusWidget()->focusPolicy() == TQWidget::WheelFocus ) ) { + e->ignore(); + break; + } + TQFocusEvent::setReason(TQFocusEvent::Tab); + focusNextPrevChild( TRUE ); + TQFocusEvent::resetReason(); + break; + default: + e->ignore(); + return; + } + } else { + e->ignore(); + } +} + +/*! \reimp */ +void TQDialog::closeEvent( TQCloseEvent *e ) +{ +#ifndef QT_NO_WHATSTHIS + if ( isModal() && TQWhatsThis::inWhatsThisMode() ) + TQWhatsThis::leaveWhatsThisMode(); +#endif + if ( isShown() ) + reject(); + if ( isHidden() ) + e->accept(); +} + +#ifdef Q_OS_TEMP +/*! \internal + \reimp +*/ +bool TQDialog::event( TQEvent *e ) +{ + switch ( e->type() ) { + case TQEvent::OkRequest: + case TQEvent::HelpRequest: + { + TQString bName = + (e->type() == TQEvent::OkRequest) + ? qApp->translate( "TQMessageBox", mb_texts[TQMessageBox::Ok] ) + : qApp->tr( "Help" ); + + TQObjectList *list = queryList( "TQPushButton" ); + TQObjectListIt it( *list ); + TQPushButton *pb; + while ( (pb = (TQPushButton*)it.current()) ) { + if ( pb->text() == bName ) { + delete list; + if ( pb->isEnabled() ) + emit pb->clicked(); + return pb->isEnabled(); + } + ++it; + } + delete list; + } + } + return TQWidget::event( e ); +} +#endif + + +/***************************************************************************** + Geometry management. + *****************************************************************************/ + +#if defined(Q_WS_X11) +extern "C" { int XSetTransientForHint( Display *, unsigned long, unsigned long ); } +#include <private/qt_x11_p.h> +#undef FocusIn +// defined in qapplication_x11.cpp +extern Atom qt_net_wm_full_placement; +extern bool qt_net_supports(Atom atom); +#endif // Q_WS_X11 + +/*! + Shows the dialog as a \link #modeless modeless \endlink dialog. + Control returns immediately to the calling code. + + The dialog will be modal or modeless according to the value + of the \l modal property. + + \sa exec(), modal +*/ + +void TQDialog::show() +{ + if ( testWState(WState_Visible) ) + return; + + uint state = windowState(); + + if ( !did_resize ) + adjustSize(); + if( !qt_net_supports( qt_net_wm_full_placement )) { + if ( has_relpos && !did_move ) { + adjustPositionInternal( parentWidget(), TRUE ); + } else if ( !did_move ) { + adjustPositionInternal( parentWidget() ); + } + } + + if (windowState() != state) + setWindowState(state); + +#if defined(Q_WS_X11) + if (!parentWidget() && testWFlags(WShowModal) + && qApp->mainWidget() && qApp->mainWidget()->isVisible() + && !qApp->mainWidget()->isMinimized()) { + // make sure the transient for hint is set properly for modal dialogs + x11SetWindowTransient( qApp->mainWidget()); + } +#endif // Q_WS_X11 + +#ifdef Q_OS_TEMP + hideSpecial(); +#endif + + TQWidget::show(); + showExtension( d->doShowExtension ); +#ifndef QT_NO_PUSHBUTTON + TQWidget *fw = focusWidget(); + TQFocusData *fd = focusData(); + + /* + The following block is to handle a special case, and does not + really follow propper logic in concern of autoDefault and TAB + order. However, it's here to ease usage for the users. If a + dialog has a default TQPushButton, and first widget in the TAB + order also is a TQPushButton, then we give focus to the main + default TQPushButton. This simplifies code for the developers, + and actually catches most cases... If not, then they simply + have to use [widget*]->setFocus() themselves... + */ + if ( !fw || fw->focusPolicy() == NoFocus ) { + fd->home(); // Skip main form + TQWidget *first = fd->next(); // Get first main widget + if ( d->mainDef && + first != d->mainDef && + ::qt_cast<TQPushButton*>(first) ) + d->mainDef->setFocus(); + } + + if ( !d->mainDef && isTopLevel() ) { + if ( !fw || fw->focusPolicy() == NoFocus ) { + focusNextPrevChild( TRUE ); + fw = focusWidget(); + } + if ( fw ) { + fd = focusData(); + TQWidget *home = fd->home(); + TQWidget *candidate = home; + Q_ASSERT( candidate == fw ); + do { + TQPushButton *pb = ::qt_cast<TQPushButton*>(candidate); + if ( pb && pb->autoDefault() ) { + pb->setDefault( TRUE ); + break; + } + candidate = fd->next(); + } while ( candidate != home ); + } + } + if ( fw ) { + TQFocusEvent e( TQEvent::FocusIn ); + TQFocusEvent::setReason( TQFocusEvent::Tab ); + TQApplication::sendEvent( fw, &e ); + TQFocusEvent::resetReason(); + } + +#endif +#if defined(QT_ACCESSIBILITY_SUPPORT) + TQAccessible::updateAccessibility( this, 0, TQAccessible::DialogStart ); +#endif +} + +/*! \internal */ +void TQDialog::adjustPosition( TQWidget* w) +{ + adjustPositionInternal( w ); +} + + +void TQDialog::adjustPositionInternal( TQWidget*w, bool useRelPos) +{ + /* need to make sure these events are already sent to be sure + our information below is correct --sam */ + TQApplication::sendPostedEvents( this, TQEvent::LayoutHint ); + TQApplication::sendPostedEvents( this, TQEvent::Resize ); + + // processing the events might call polish(), which is a nice place + // to restore geometries, so return if the dialog has been positioned + if ( did_move || has_relpos ) + return; + + TQPoint p( 0, 0 ); + int extraw = 0, extrah = 0, scrn = 0; + if ( w ) + w = w->topLevelWidget(); + TQRect desk; + if ( w ) { + // Use mapToGlobal rather than geometry() in case w might + // be embedded in another application + scrn = TQApplication::desktop()->screenNumber( w->mapToGlobal( TQPoint(0,0) ) ); + } else if ( TQApplication::desktop()->isVirtualDesktop() ) { + scrn = TQApplication::desktop()->screenNumber( TQCursor::pos() ); + } else { + scrn = TQApplication::desktop()->screenNumber( this ); + } + desk = TQApplication::desktop()->availableGeometry( scrn ); + + TQWidgetList *list = TQApplication::topLevelWidgets(); + TQWidgetListIt it( *list ); + while ( (extraw == 0 || extrah == 0) && + it.current() != 0 ) { + int framew, frameh; + TQWidget * current = it.current(); + ++it; + if ( ! current->isVisible() ) + continue; + + framew = current->geometry().x() - current->x(); + frameh = current->geometry().y() - current->y(); + + extraw = TQMAX( extraw, framew ); + extrah = TQMAX( extrah, frameh ); + } + delete list; + + // sanity check for decoration frames. With embedding, we + // might get extraordinary values + if ( extraw == 0 || extrah == 0 || extraw >= 10 || extrah >= 40 ) { + extrah = 40; + extraw = 10; + } + + if ( useRelPos && w ) { + p = w->pos() + d->relPos; + } else { +#ifndef Q_OS_TEMP + if ( w ) { + // Use mapToGlobal rather than geometry() in case w might + // be embedded in another application + TQPoint pp = w->mapToGlobal( TQPoint(0,0) ); + p = TQPoint( pp.x() + w->width()/2, + pp.y() + w->height()/ 2 ); + } else { + // p = middle of the desktop + p = TQPoint( desk.x() + desk.width()/2, desk.y() + desk.height()/2 ); + } +#else + p = TQPoint( desk.x() + desk.width()/2, desk.y() + desk.height()/2 ); +#endif + + // p = origin of this + p = TQPoint( p.x()-width()/2 - extraw, + p.y()-height()/2 - extrah ); + } + + + if ( p.x() + extraw + width() > desk.x() + desk.width() ) + p.setX( desk.x() + desk.width() - width() - extraw ); + if ( p.x() < desk.x() ) + p.setX( desk.x() ); + + if ( p.y() + extrah + height() > desk.y() + desk.height() ) + p.setY( desk.y() + desk.height() - height() - extrah ); + if ( p.y() < desk.y() ) + p.setY( desk.y() ); + + move( p ); + did_move = !useRelPos; +} + + +/*! \reimp */ +void TQDialog::hide() +{ + if ( isHidden() ) + return; + +#if defined(QT_ACCESSIBILITY_SUPPORT) + if ( isVisible() ) + TQAccessible::updateAccessibility( this, 0, TQAccessible::DialogEnd ); +#endif + + if ( parentWidget() && !did_move ) { + d->relPos = pos() - parentWidget()->topLevelWidget()->pos(); + has_relpos = 1; + } + + // Reimplemented to exit a modal when the dialog is hidden. + TQWidget::hide(); + if ( in_loop ) { + in_loop = FALSE; + qApp->exit_loop(); + } +} + + +/***************************************************************************** + Detects any widget geometry changes done by the user. + *****************************************************************************/ + +/*! \reimp */ + +void TQDialog::move( int x, int y ) +{ + did_move = TRUE; + TQWidget::move( x, y ); +} + +/*! \reimp */ + +void TQDialog::move( const TQPoint &p ) +{ + did_move = TRUE; + TQWidget::move( p ); +} + +/*! \reimp */ + +void TQDialog::resize( int w, int h ) +{ + did_resize = TRUE; + TQWidget::resize( w, h ); +} + +/*! \reimp */ + +void TQDialog::resize( const TQSize &s ) +{ + did_resize = TRUE; + TQWidget::resize( s ); +} + +/*! \reimp */ + +void TQDialog::setGeometry( int x, int y, int w, int h ) +{ + did_move = TRUE; + did_resize = TRUE; + TQWidget::setGeometry( x, y, w, h ); +} + +/*! \reimp */ + +void TQDialog::setGeometry( const TQRect &r ) +{ + did_move = TRUE; + did_resize = TRUE; + TQWidget::setGeometry( r ); +} + + +/*! + If \a orientation is \c Horizontal, the extension will be displayed + to the right of the dialog's main area. If \a orientation is \c + Vertical, the extension will be displayed below the dialog's main + area. + + \sa orientation(), setExtension() +*/ +void TQDialog::setOrientation( Orientation orientation ) +{ + d->orientation = orientation; +} + +/*! + Returns the dialog's extension orientation. + + \sa setOrientation() +*/ +TQt::Orientation TQDialog::orientation() const +{ + return d->orientation; +} + +/*! + Sets the widget, \a extension, to be the dialog's extension, + deleting any previous extension. The dialog takes ownership of the + extension. Note that if 0 is passed any existing extension will be + deleted. + + This function must only be called while the dialog is hidden. + + \sa showExtension(), setOrientation(), extension() + */ +void TQDialog::setExtension( TQWidget* extension ) +{ + delete d->extension; + d->extension = extension; + + if ( !extension ) + return; + + if ( extension->parentWidget() != this ) + extension->reparent( this, TQPoint(0,0) ); + extension->hide(); +} + +/*! + Returns the dialog's extension or 0 if no extension has been + defined. + + \sa setExtension() + */ +TQWidget* TQDialog::extension() const +{ + return d->extension; +} + + +/*! + If \a showIt is TRUE, the dialog's extension is shown; otherwise the + extension is hidden. + + This slot is usually connected to the \l TQButton::toggled() signal + of a TQPushButton. + + A dialog with a visible extension is not resizeable. + + \sa show(), setExtension(), setOrientation() + */ +void TQDialog::showExtension( bool showIt ) +{ + d->doShowExtension = showIt; + if ( !d->extension ) + return; + if ( !testWState(WState_Visible) ) + return; + if ( d->extension->isVisible() == showIt ) + return; + + if ( showIt ) { + d->size = size(); + d->min = minimumSize(); + d->max = maximumSize(); +#ifndef QT_NO_LAYOUT + if ( layout() ) + layout()->setEnabled( FALSE ); +#endif + TQSize s( d->extension->sizeHint() + .expandedTo( d->extension->minimumSize() ) + .boundedTo( d->extension->maximumSize() ) ); + if ( d->orientation == Horizontal ) { + int h = TQMAX( height(), s.height() ); + d->extension->setGeometry( width(), 0, s.width(), h ); + setFixedSize( width() + s.width(), h ); + } else { + int w = TQMAX( width(), s.width() ); + d->extension->setGeometry( 0, height(), w, s.height() ); + setFixedSize( w, height() + s.height() ); + } + d->extension->show(); + } else { + d->extension->hide(); + // workaround for CDE window manager that won't shrink with (-1,-1) + setMinimumSize( d->min.expandedTo( TQSize( 1, 1 ) ) ); + setMaximumSize( d->max ); + resize( d->size ); +#ifndef QT_NO_LAYOUT + if ( layout() ) + layout()->setEnabled( TRUE ); +#endif + } +} + + +/*! \reimp */ +TQSize TQDialog::sizeHint() const +{ + if ( d->extension ) + if ( d->orientation == Horizontal ) + return TQSize( TQWidget::sizeHint().width(), + TQMAX( TQWidget::sizeHint().height(),d->extension->sizeHint().height() ) ); + else + return TQSize( TQMAX( TQWidget::sizeHint().width(), d->extension->sizeHint().width() ), + TQWidget::sizeHint().height() ); + + return TQWidget::sizeHint(); +} + + +/*! \reimp */ +TQSize TQDialog::minimumSizeHint() const +{ + if ( d->extension ) + if (d->orientation == Horizontal ) + return TQSize( TQWidget::minimumSizeHint().width(), + TQMAX( TQWidget::minimumSizeHint().height(), d->extension->minimumSizeHint().height() ) ); + else + return TQSize( TQMAX( TQWidget::minimumSizeHint().width(), d->extension->minimumSizeHint().width() ), + TQWidget::minimumSizeHint().height() ); + + return TQWidget::minimumSizeHint(); +} + +/*! \property TQDialog::modal + \brief whether show() should pop up the dialog as modal or modeless + + By default, this property is false and show() pops up the dialog as + modeless. + + exec() ignores the value of this property and always pops up the + dialog as modal. + + \sa show(), exec() +*/ + +void TQDialog::setModal( bool modal ) +{ + if ( modal ) + setWFlags( WShowModal ); + else + clearWFlags( WShowModal ); +} + +bool TQDialog::isModal() const +{ + return testWFlags( WShowModal ) != 0; +} + +bool TQDialog::isSizeGripEnabled() const +{ +#ifndef QT_NO_SIZEGRIP + return !!d->resizer; +#else + return FALSE; +#endif +} + + +void TQDialog::setSizeGripEnabled(bool enabled) +{ +#ifndef QT_NO_SIZEGRIP + if ( !enabled != !d->resizer ) { + if ( enabled ) { + d->resizer = new TQSizeGrip( this, "TQDialog::resizer" ); + // adjustSize() processes all events, which is suboptimal + d->resizer->resize( d->resizer->sizeHint() ); + if ( TQApplication::reverseLayout() ) + d->resizer->move( rect().bottomLeft() -d->resizer->rect().bottomLeft() ); + else + d->resizer->move( rect().bottomRight() -d->resizer->rect().bottomRight() ); + d->resizer->raise(); + d->resizer->show(); + } else { + delete d->resizer; + d->resizer = 0; + } + } +#endif //QT_NO_SIZEGRIP +} + + + +/*! \reimp */ +void TQDialog::resizeEvent( TQResizeEvent * ) +{ +#ifndef QT_NO_SIZEGRIP + if ( d->resizer ) { + if ( TQApplication::reverseLayout() ) + d->resizer->move( rect().bottomLeft() -d->resizer->rect().bottomLeft() ); + else + d->resizer->move( rect().bottomRight() -d->resizer->rect().bottomRight() ); + } +#endif +} + +#endif // QT_NO_DIALOG diff --git a/src/dialogs/qdialog.h b/src/dialogs/qdialog.h new file mode 100644 index 000000000..fc224655d --- /dev/null +++ b/src/dialogs/qdialog.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Definition of TQDialog class +** +** Created : 950502 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQDIALOG_H +#define TQDIALOG_H + +#ifndef QT_H +#include "qwidget.h" +#endif // QT_H +#ifndef QT_NO_DIALOG +#if 0 +Q_OBJECT +#endif + +class TQPushButton; +class TQDialogPrivate; + +class Q_EXPORT TQDialog : public TQWidget +{ +friend class TQPushButton; + Q_OBJECT + Q_PROPERTY( bool sizeGripEnabled READ isSizeGripEnabled WRITE setSizeGripEnabled ) + Q_PROPERTY( bool modal READ isModal WRITE setModal ) + +public: + Q_EXPLICIT TQDialog( TQWidget* parent=0, const char* name=0, bool modal=FALSE, + WFlags f=0 ); + ~TQDialog(); + + enum DialogCode { Rejected, Accepted }; + + int result() const { return rescode; } + + void show(); + void hide(); + void move( int x, int y ); + void move( const TQPoint &p ); + void resize( int w, int h ); + void resize( const TQSize & ); + void setGeometry( int x, int y, int w, int h ); + void setGeometry( const TQRect & ); + + void setOrientation( Orientation orientation ); + Orientation orientation() const; + + void setExtension( TQWidget* extension ); + TQWidget* extension() const; + + TQSize sizeHint() const; + TQSize minimumSizeHint() const; + + void setSizeGripEnabled( bool ); + bool isSizeGripEnabled() const; + + void setModal( bool modal ); + bool isModal() const; +#ifdef Q_OS_TEMP + bool event( TQEvent * ); +#endif + +public slots: + int exec(); + +protected slots: + virtual void done( int ); + virtual void accept(); + virtual void reject(); + + void showExtension( bool ); + +protected: + void setResult( int r ) { rescode = r; } + void keyPressEvent( TQKeyEvent * ); + void closeEvent( TQCloseEvent * ); + void resizeEvent( TQResizeEvent * ); + void contextMenuEvent( TQContextMenuEvent * ); + bool eventFilter( TQObject *, TQEvent * ); + void adjustPosition( TQWidget*); + +private: + void setDefault( TQPushButton * ); + void setMainDefault( TQPushButton * ); + void hideDefault(); +#ifdef Q_OS_TEMP + void hideSpecial(); +#endif + + int rescode; + uint did_move : 1; + uint has_relpos : 1; + uint did_resize : 1; + uint in_loop: 1; + void adjustPositionInternal( TQWidget*, bool useRelPos = FALSE ); + TQDialogPrivate* d; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQDialog( const TQDialog & ); + TQDialog &operator=( const TQDialog & ); +#endif +}; + +#endif // QT_NO_DIALOG +#endif // TQDIALOG_H diff --git a/src/dialogs/qerrormessage.cpp b/src/dialogs/qerrormessage.cpp new file mode 100644 index 000000000..b5d747a68 --- /dev/null +++ b/src/dialogs/qerrormessage.cpp @@ -0,0 +1,270 @@ +/**************************************************************************** +** +** Implementation of a nice qInstallMsgHandler() handler +** +** Created : 000527, after Kalle Dalheimer's birthday +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qerrormessage.h" + +#ifndef QT_NO_ERRORMESSAGE + +#include "qapplication.h" +#include "qcheckbox.h" +#include "qdict.h" +#include "qlabel.h" +#include "qlayout.h" +#include "qmessagebox.h" +#include "qpushbutton.h" +#include "qstringlist.h" +#include "qstylesheet.h" +#include "qtextview.h" + +#include <stdio.h> +#include <stdlib.h> + +class TQErrorMessageTextView : public TQTextView +{ +public: + TQErrorMessageTextView( TQWidget *parent, const char *name ) + : TQTextView( parent, name ) { } + + virtual TQSize minimumSizeHint() const; + virtual TQSize sizeHint() const; +}; + +TQSize TQErrorMessageTextView::minimumSizeHint() const +{ + return TQSize( 50, 50 ); +} + +TQSize TQErrorMessageTextView::sizeHint() const +{ + return TQSize( 250, 75 ); +} + +/*! \class TQErrorMessage + + \brief The TQErrorMessage class provides an error message display dialog. + + \ingroup dialogs + \ingroup misc + +This is basically a TQLabel and a "show this message again" checkbox which +remembers what not to show. + +There are two ways to use this class: +\list 1 +\i For production applications. In this context the class can be used to +display messages which you don't need the user to see more than once. To use +TQErrorMessage like this, you create the dialog in the usual way and call the +message() slot, or connect signals to it. + +\i For developers. In this context the static qtHandler() installs +a message handler using qInstallMsgHandler() and creates a TQErrorMessage +that displays qDebug(), qWarning() and qFatal() messages. +\endlist + +In both cases TQErrorMessage will queue pending messages, and display +them (or not) in order, as soon as the user presses Enter or clicks OK +after seeing each message. + +\img qerrormessage.png + +\sa TQMessageBox TQStatusBar::message() +*/ + +static TQErrorMessage * qtMessageHandler = 0; + +static void deleteStaticcTQErrorMessage() // post-routine +{ + if ( qtMessageHandler ) { + delete qtMessageHandler; + qtMessageHandler = 0; + } +} + +static bool metFatal = FALSE; + +void jump( TQtMsgType t, const char * m ) +{ + if ( !qtMessageHandler ) + return; + + TQString rich; + + switch ( t ) { + case TQtDebugMsg: + default: + rich = TQErrorMessage::tr( "Debug Message:" ); + break; + case TQtWarningMsg: + rich = TQErrorMessage::tr( "Warning:" ); + break; + case TQtFatalMsg: + rich = TQErrorMessage::tr( "Fatal Error:" ); + } + rich = TQString( "<p><b>%1</b></p>" ).arg( rich ); + rich += TQStyleSheet::convertFromPlainText( m, + TQStyleSheetItem::WhiteSpaceNormal ); + + // ### work around text engine tquirk + if ( rich.endsWith("</p>") ) + rich.truncate( rich.length() - 4 ); + + if ( !metFatal ) { + qtMessageHandler->message( rich ); + metFatal = ( t == TQtFatalMsg ); + } +} + + +/*! Constructs and installs an error handler window. + The parent \a parent and name \a name are passed on to the TQDialog + constructor. +*/ + +TQErrorMessage::TQErrorMessage( TQWidget * parent, const char * name ) + : TQDialog( parent, name ) +{ + TQGridLayout * grid = new TQGridLayout( this, 3, 2, 11, 6 ); + icon = new TQLabel( this, "qt_icon_lbl" ); +#ifndef QT_NO_MESSAGEBOX + icon->setPixmap( TQMessageBox::standardIcon(TQMessageBox::Information) ); +#endif + grid->addWidget( icon, 0, 0, AlignTop ); + errors = new TQErrorMessageTextView( this, "errors" ); + grid->addWidget( errors, 0, 1 ); + again = new TQCheckBox( tr( "&Show this message again" ), this, "again" ); + again->setChecked( TRUE ); + grid->addWidget( again, 1, 1, AlignTop + AlignAuto ); + ok = new TQPushButton( tr( "&OK" ), this, "ok" ); + connect( ok, SIGNAL(clicked()), this, SLOT(accept()) ); + ok->setFocus(); + grid->addMultiCellWidget( ok, 2, 2, 0, 1, AlignCenter ); + grid->setColStretch( 1, 42 ); + grid->setRowStretch( 0, 42 ); + pending = new TQStringList; + doNotShow = new TQDict<int>; +} + + +/*! Destroys the object and frees any allocated resources. Notably, +the list of "do not show again" messages is deleted. */ + +TQErrorMessage::~TQErrorMessage() +{ + if ( this == qtMessageHandler ) { + qtMessageHandler = 0; + TQtMsgHandler tmp = qInstallMsgHandler( 0 ); + // in case someone else has later stuck in another... + if ( tmp != jump ) + qInstallMsgHandler( tmp ); + } + + delete pending; + delete doNotShow; +} + + +/*! \reimp */ + +void TQErrorMessage::done( int a ) +{ + int dummy = 0; + if ( !again->isChecked() ) + doNotShow->insert( errors->text(), &dummy ); + if ( !nextPending() ) { + TQDialog::done( a ); + if ( this == qtMessageHandler && metFatal ) + exit( 1 ); + } +} + + +/*! Returns a pointer to a TQErrorMessage object that outputs the +default TQt messages. This function creates such an object, if there +isn't one already. +*/ + +TQErrorMessage * TQErrorMessage::qtHandler() +{ + if ( !qtMessageHandler ) { + qtMessageHandler = new TQErrorMessage( 0, "automatic message handler" ); + qAddPostRoutine( deleteStaticcTQErrorMessage ); // clean up +#ifndef QT_NO_WIDGET_TOPEXTRA + if ( qApp->mainWidget() ) + qtMessageHandler->setCaption( qApp->mainWidget()->caption() ); +#endif + qInstallMsgHandler( jump ); + } + return qtMessageHandler; +} + + +/*! \internal */ + +bool TQErrorMessage::nextPending() +{ + while ( !pending->isEmpty() ) { + TQString p = *pending->begin(); + pending->remove( pending->begin() ); + if ( !p.isEmpty() && !doNotShow->find( p ) ) { + errors->setText( p ); + return TRUE; + } + } + return FALSE; +} + + +/*! Shows message \a m and returns immediately. If the user has requested + that \a m not be shown, this function does nothing. + + Normally, \a m is shown at once, but if there are pending messages, + \a m is queued for later display. +*/ + +void TQErrorMessage::message( const TQString & m ) +{ + if ( doNotShow->find( m ) ) + return; + pending->append( m ); + if ( !isVisible() && nextPending() ) + show(); +} + +#endif // QT_NO_ERRORMESSAGE diff --git a/src/dialogs/qerrormessage.h b/src/dialogs/qerrormessage.h new file mode 100644 index 000000000..4fd5212f3 --- /dev/null +++ b/src/dialogs/qerrormessage.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Definition of a nice qInstallErrorMessage() handler +** +** Created : 000527, after Kalle Dalheimer's birthday +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQERRORMESSAGE_H +#define TQERRORMESSAGE_H + +#ifndef QT_H +#include "qdialog.h" +#endif // QT_H + +#ifndef QT_NO_ERRORMESSAGE +class TQPushButton; +class TQCheckBox; +class TQLabel; +class TQTextView; +class TQStringList; +template<class type> class TQDict; + + +class Q_EXPORT TQErrorMessage: public TQDialog { + Q_OBJECT +public: + TQErrorMessage( TQWidget* parent, const char* name=0 ); + ~TQErrorMessage(); + + static TQErrorMessage * qtHandler(); + +public slots: + void message( const TQString & ); + +protected: + void done( int ); + +private: + TQPushButton * ok; + TQCheckBox * again; + TQTextView * errors; + TQLabel * icon; + TQStringList * pending; + TQDict<int> * doNotShow; + + bool nextPending(); + +#if defined(Q_DISABLE_COPY) // Disabled copy constructor and operator= + TQErrorMessage( const TQErrorMessage & ); + TQErrorMessage &operator=( const TQErrorMessage & ); +#endif +}; + +#endif //QT_NO_ERRORMESSAGE + +#endif diff --git a/src/dialogs/qfiledialog.cpp b/src/dialogs/qfiledialog.cpp new file mode 100644 index 000000000..4eeb6621b --- /dev/null +++ b/src/dialogs/qfiledialog.cpp @@ -0,0 +1,6486 @@ +/**************************************************************************** +** +** Implementation of TQFileDialog class +** +** Created : 950429 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qplatformdefs.h" + +// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED. +#if defined(connect) +# undef connect +#endif + +// POSIX Large File Support redefines truncate -> truncate64 +#if defined(truncate) +# undef truncate +#endif + +#include "qfiledialog.h" + +#ifndef QT_NO_FILEDIALOG + +#include "private/qapplication_p.h" +#include "qapplication.h" +#include "qbitmap.h" +#include "qbuttongroup.h" +#include "qcheckbox.h" +#include "qcleanuphandler.h" +#include "qcombobox.h" +#include "qcstring.h" +#include "qcursor.h" +#include "qdragobject.h" +#include "qfile.h" +#include "qguardedptr.h" +#include "qhbox.h" +#include "qheader.h" +#include "qlabel.h" +#include "qlayout.h" +#include "qlibrary.h" +#include "qlineedit.h" +#include "qlistbox.h" +#include "qlistview.h" +#include "qmap.h" +#include "qmessagebox.h" +#include "qmime.h" +#include "qnetworkprotocol.h" +#include "qobjectlist.h" +#include "qpainter.h" +#include "qpopupmenu.h" +#include "qprogressbar.h" +#include "qptrvector.h" +#include "qpushbutton.h" +#include "qregexp.h" +#include "qsemimodal.h" +#include "qsplitter.h" +#include "qstrlist.h" +#include "qstyle.h" +#include "qtimer.h" +#include "qtoolbutton.h" +#include "qtooltip.h" +#include "qvbox.h" +#include "qwidgetstack.h" + +#ifdef Q_WS_X11 +#include "private/qtkdeintegration_x11_p.h" +#endif + +#ifdef Q_WS_WIN +#ifdef QT_THREAD_SUPPORT +# include <private/qmutexpool_p.h> +#endif // QT_THREAD_SUPPORT +#endif // Q_WS_WIN + +#if !defined(Q_OS_TEMP) +#include <time.h> +#else +#include <shellapi.h> +#endif +#include <stdlib.h> +#include <limits.h> +#include <ctype.h> + +#ifdef Q_WS_MAC +#include "qt_mac.h" +extern TQString qt_mac_precomposeFileName(const TQString &); // qglobal.cpp +#undef check +#endif + +/* XPM */ +static const char * const start_xpm[]={ + "16 15 8 1", + "a c #cec6bd", + "# c #000000", + "e c #ffff00", + "b c #999999", + "f c #cccccc", + "d c #dcdcdc", + "c c #ffffff", + ". c None", + ".....######aaaaa", + "...bb#cccc##aaaa", + "..bcc#cccc#d#aaa", + ".bcef#cccc#dd#aa", + ".bcfe#cccc#####a", + ".bcef#ccccccccc#", + "bbbbbbbbbbbbccc#", + "bccccccccccbbcc#", + "bcefefefefee#bc#", + ".bcefefefefef#c#", + ".bcfefefefefe#c#", + "..bcfefefefeeb##", + "..bbbbbbbbbbbbb#", + "...#############", + "................"}; + +/* XPM */ +static const char * const end_xpm[]={ + "16 15 9 1", + "d c #a0a0a0", + "c c #c3c3c3", + "# c #cec6bd", + ". c #000000", + "f c #ffff00", + "e c #999999", + "g c #cccccc", + "b c #ffffff", + "a c None", + "......####aaaaaa", + ".bbbb..###aaaaaa", + ".bbbb.c.##aaaaaa", + ".bbbb....ddeeeea", + ".bbbbbbb.bbbbbe.", + ".bbbbbbb.bcfgfe.", + "eeeeeeeeeeeeefe.", + "ebbbbbbbbbbeege.", + "ebfgfgfgfgff.ee.", + "aebfgfgfgfgfg.e.", + "aebgfgfgfgfgf.e.", + "aaebgfgfgfgffe..", + "aaeeeeeeeeeeeee.", + "aaa.............", + "aaaaaaaaaaaaaaaa"}; + +/* XPM */ +static const char* const open_xpm[]={ + "16 16 6 1", + ". c None", + "b c #ffff00", + "d c #000000", + "* c #999999", + "c c #cccccc", + "a c #ffffff", + "................", + "................", + "...*****........", + "..*aaaaa*.......", + ".*abcbcba******.", + ".*acbcbcaaaaaa*d", + ".*abcbcbcbcbcb*d", + "*************b*d", + "*aaaaaaaaaa**c*d", + "*abcbcbcbcbbd**d", + ".*abcbcbcbcbcd*d", + ".*acbcbcbcbcbd*d", + "..*acbcbcbcbb*dd", + "..*************d", + "...ddddddddddddd", + "................"}; + +/* XPM */ +static const char * const link_dir_xpm[]={ + "16 16 10 1", + "h c #808080", + "g c #a0a0a0", + "d c #000000", + "b c #ffff00", + "f c #303030", + "# c #999999", + "a c #cccccc", + "e c #585858", + "c c #ffffff", + ". c None", + "................", + "................", + "..#####.........", + ".#ababa#........", + "#abababa######..", + "#cccccccccccc#d.", + "#cbababababab#d.", + "#cabababababa#d.", + "#cbababdddddddd.", + "#cababadccccccd.", + "#cbababdcececcd.", + "#cababadcefdfcd.", + "#cbababdccgdhcd.", + "#######dccchccd.", + ".dddddddddddddd.", + "................"}; + +/* XPM */ +static const char * const link_file_xpm[]={ + "16 16 10 1", + "h c #808080", + "g c #a0a0a0", + "d c #c3c3c3", + ". c #7f7f7f", + "c c #000000", + "b c #bfbfbf", + "f c #303030", + "e c #585858", + "a c #ffffff", + "# c None", + "################", + "..........######", + ".aaaaaaaab.#####", + ".aaaaaaaaba.####", + ".aaaaaaaacccc###", + ".aaaaaaaaaabc###", + ".aaaaaaaaaabc###", + ".aaaaaaaaaadc###", + ".aaaaaaaaaadc###", + ".aaaacccccccc###", + ".aaaacaaaaaac###", + ".aaaacaeaeaac###", + ".aaaacaefcfac###", + ".aaaacaagchac###", + ".ddddcaaahaac###", + "ccccccccccccc###"}; + +/* XPM */ +static const char* const file_xpm[]={ + "16 16 5 1", + ". c #7f7f7f", + "# c None", + "c c #000000", + "b c #bfbfbf", + "a c #ffffff", + "################", + "..........######", + ".aaaaaaaab.#####", + ".aaaaaaaaba.####", + ".aaaaaaaacccc###", + ".aaaaaaaaaabc###", + ".aaaaaaaaaabc###", + ".aaaaaaaaaabc###", + ".aaaaaaaaaabc###", + ".aaaaaaaaaabc###", + ".aaaaaaaaaabc###", + ".aaaaaaaaaabc###", + ".aaaaaaaaaabc###", + ".aaaaaaaaaabc###", + ".bbbbbbbbbbbc###", + "ccccccccccccc###"}; + +/* XPM */ +static const char * const closed_xpm[]={ + "16 16 6 1", + ". c None", + "b c #ffff00", + "d c #000000", + "* c #999999", + "a c #cccccc", + "c c #ffffff", + "................", + "................", + "..*****.........", + ".*ababa*........", + "*abababa******..", + "*cccccccccccc*d.", + "*cbababababab*d.", + "*cabababababa*d.", + "*cbababababab*d.", + "*cabababababa*d.", + "*cbababababab*d.", + "*cabababababa*d.", + "*cbababababab*d.", + "**************d.", + ".dddddddddddddd.", + "................"}; + + +/* XPM */ +static const char* const cdtoparent_xpm[]={ + "15 13 3 1", + ". c None", + "* c #000000", + "a c #ffff99", + "..*****........", + ".*aaaaa*.......", + "***************", + "*aaaaaaaaaaaaa*", + "*aaaa*aaaaaaaa*", + "*aaa***aaaaaaa*", + "*aa*****aaaaaa*", + "*aaaa*aaaaaaaa*", + "*aaaa*aaaaaaaa*", + "*aaaa******aaa*", + "*aaaaaaaaaaaaa*", + "*aaaaaaaaaaaaa*", + "***************"}; + + +/* XPM */ +static const char* const newfolder_xpm[] = { + "15 14 4 1", + " c None", + ". c #000000", + "+ c #FFFF00", + "@ c #FFFFFF", + " . ", + " ", + " . ", + " . . ", + " .... . . . ", + " .+@+@. . . ", + ".......... . .", + ".@+@+@+@+@.. ", + ".+@+@+@+@+. . ", + ".@+@+@+@+@. . ", + ".+@+@+@+@+. ", + ".@+@+@+@+@. ", + ".+@+@+@+@+. ", + "........... "}; + +/* XPM */ +static const char* const detailedview_xpm[]={ + "14 11 3 1", + ". c None", + "* c #000000", + "a c #000099", + ".****.***.***.", + "..............", + "aaaaaaaaaaaaaa", + "..............", + ".****.***.***.", + "..............", + ".****.***.***.", + "..............", + ".****.***.***.", + "..............", + ".****.***.***."}; + +/* XPM */ +static const char* const previewinfoview_xpm[]={ + "13 13 4 1", + ". c #00007f", + "a c black", + "# c #cec6bd", + "b c #000000", + "..#####aaaaaa", + ".#.#bb#a#####", + "...####a#bbb#", + "#######a#####", + "#######a#bb##", + "..#####a#####", + ".#.#bb#a#bbb#", + "...####a#####", + "#######a#bb##", + "#######a#####", + "..#####a#bbb#", + ".#.#bb#a#####", + "...####aaaaaa"}; + +/* XPM */ +static const char* const previewcontentsview_xpm[]={ + "14 13 5 1", + ". c #00007f", + "a c black", + "c c #7f007f", + "# c #cec6bd", + "b c #000000", + "..#####aaaaaaa", + ".#.#bb#a#####a", + "...####a#ccc#a", + "#######a#ccc#a", + "#######a#####a", + "..#####a#bbb#a", + ".#.#bb#a#####a", + "...####a#bbb#a", + "#######a#####a", + "#######a#bbb#a", + "..#####a#####a", + ".#.#bb#a#####a", + "...####aaaaaaa"}; + +/* XPM */ +static const char* const mclistview_xpm[]={ + "15 11 4 1", + "* c None", + "b c #000000", + ". c #000099", + "a c #ffffff", + "...*****...****", + ".a.*bbb*.a.*bbb", + "...*****...****", + "***************", + "...*****...****", + ".a.*bbb*.a.*bbb", + "...*****...****", + "***************", + "...*****...****", + ".a.*bbb*.a.*bbb", + "...*****...****"}; + +/* XPM */ +static const char * const back_xpm [] = { + "13 11 3 1", + "a c #00ffff", + "# c #000000", + ". c None", + ".....#.......", + "....##.......", + "...#a#.......", + "..#aa########", + ".#aaaaaaaaaa#", + "#aaaaaaaaaaa#", + ".#aaaaaaaaaa#", + "..#aa########", + "...#a#.......", + "....##.......", + ".....#......."}; + +static TQPixmap * openFolderIcon = 0; +static TQPixmap * closedFolderIcon = 0; +static TQPixmap * detailViewIcon = 0; +static TQPixmap * multiColumnListViewIcon = 0; +static TQPixmap * cdToParentIcon = 0; +static TQPixmap * newFolderIcon = 0; +static TQPixmap * fifteenTransparentPixels = 0; +static TQPixmap * symLinkDirIcon = 0; +static TQPixmap * symLinkFileIcon = 0; +static TQPixmap * fileIcon = 0; +static TQPixmap * startCopyIcon = 0; +static TQPixmap * endCopyIcon = 0; +static TQPixmap * previewContentsViewIcon = 0; +static TQPixmap * previewInfoViewIcon = 0; +static TQPixmap *goBackIcon = 0; +static TQFileIconProvider * fileIconProvider = 0; +static int lastWidth = 0; +static int lastHeight = 0; +static TQString * workingDirectory = 0; + +static bool bShowHiddenFiles = FALSE; +static int sortFilesBy = (int)TQDir::Name; +static bool sortAscending = TRUE; +static bool detailViewMode = FALSE; + +static TQCleanupHandler<TQPixmap> qfd_cleanup_pixmap; +static TQCleanupHandler<TQString> qfd_cleanup_string; + +static TQString toRootIfNotExists( const TQString &path ) +{ + if ( !path.isEmpty() ) + return path; + + const TQFileInfoList *drives = TQDir::drives(); + Q_ASSERT( drives && !drives->isEmpty() ); + return drives->getFirst()->filePath(); +} + +static bool isDirectoryMode( int m ) +{ + return m == TQFileDialog::Directory || m == TQFileDialog::DirectoryOnly; +} + +static void updateLastSize( TQFileDialog *that ) +{ + int extWidth = 0; + int extHeight = 0; + if ( that->extension() && that->extension()->isVisible() ) { + if ( that->orientation() == TQt::Vertical ) + extHeight = that->extension()->height(); + else + extWidth = that->extension()->width(); + } + lastWidth = that->width() - extWidth; + lastHeight = that->height() - extHeight; +} + +// Don't remove the lines below! +// +// resolving the W methods manually is needed, because Windows 95 doesn't include +// these methods in Shell32.lib (not even stubs!), so you'd get an unresolved symbol +// when TQt calls getEsistingDirectory(), etc. +#if defined(Q_WS_WIN) + +typedef UINT (WINAPI *PtrExtractIconEx)(LPCTSTR,int,HICON*,HICON*,UINT); +static PtrExtractIconEx ptrExtractIconEx = 0; + +static void resolveLibs() +{ +#ifndef Q_OS_TEMP + static bool triedResolve = FALSE; + + if ( !triedResolve ) { +#ifdef QT_THREAD_SUPPORT + // protect initialization + TQMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &triedResolve ) : 0 ); + // check triedResolve again, since another thread may have already + // done the initialization + if ( triedResolve ) { + // another thread did initialize the security function pointers, + // so we shouldn't do it again. + return; + } +#endif + triedResolve = TRUE; + if ( qt_winunicode ) { + TQLibrary lib("shell32"); + lib.setAutoUnload( FALSE ); + ptrExtractIconEx = (PtrExtractIconEx) lib.resolve( "ExtractIconExW" ); + } + } +#endif +} +#ifdef Q_OS_TEMP +#define PtrExtractIconEx ExtractIconEx +#endif + +class TQWindowsIconProvider : public TQFileIconProvider +{ +public: + TQWindowsIconProvider( TQObject *parent=0, const char *name=0 ); + ~TQWindowsIconProvider(); + + const TQPixmap * pixmap( const TQFileInfo &fi ); + +private: + TQPixmap defaultFolder; + TQPixmap defaultFile; + TQPixmap defaultExe; + TQPixmap pix; + int pixw, pixh; + TQMap< TQString, TQPixmap > cache; + +}; +#endif + +static void makeVariables() { + if ( !openFolderIcon ) { + workingDirectory = new TQString( ::toRootIfNotExists(TQDir::currentDirPath()) ); + qfd_cleanup_string.add( &workingDirectory ); + + openFolderIcon = new TQPixmap( (const char **)open_xpm); + qfd_cleanup_pixmap.add( &openFolderIcon ); + symLinkDirIcon = new TQPixmap( (const char **)link_dir_xpm); + qfd_cleanup_pixmap.add( &symLinkDirIcon ); + symLinkFileIcon = new TQPixmap( (const char **)link_file_xpm); + qfd_cleanup_pixmap.add( &symLinkFileIcon ); + fileIcon = new TQPixmap( (const char **)file_xpm); + qfd_cleanup_pixmap.add( &fileIcon ); + closedFolderIcon = new TQPixmap( (const char **)closed_xpm); + qfd_cleanup_pixmap.add( &closedFolderIcon ); + detailViewIcon = new TQPixmap( (const char **)detailedview_xpm); + qfd_cleanup_pixmap.add( &detailViewIcon ); + multiColumnListViewIcon = new TQPixmap( (const char **)mclistview_xpm); + qfd_cleanup_pixmap.add( &multiColumnListViewIcon ); + cdToParentIcon = new TQPixmap( (const char **)cdtoparent_xpm); + qfd_cleanup_pixmap.add( &cdToParentIcon ); + newFolderIcon = new TQPixmap( (const char **)newfolder_xpm); + qfd_cleanup_pixmap.add( &newFolderIcon ); + previewInfoViewIcon + = new TQPixmap( (const char **)previewinfoview_xpm ); + qfd_cleanup_pixmap.add( &previewInfoViewIcon ); + previewContentsViewIcon + = new TQPixmap( (const char **)previewcontentsview_xpm ); + qfd_cleanup_pixmap.add( &previewContentsViewIcon ); + startCopyIcon = new TQPixmap( (const char **)start_xpm ); + qfd_cleanup_pixmap.add( &startCopyIcon ); + endCopyIcon = new TQPixmap( (const char **)end_xpm ); + qfd_cleanup_pixmap.add( &endCopyIcon ); + goBackIcon = new TQPixmap( (const char **)back_xpm ); + qfd_cleanup_pixmap.add( &goBackIcon ); + fifteenTransparentPixels = new TQPixmap( closedFolderIcon->width(), 1 ); + qfd_cleanup_pixmap.add( &fifteenTransparentPixels ); + TQBitmap m( fifteenTransparentPixels->width(), 1 ); + m.fill( TQt::color0 ); + fifteenTransparentPixels->setMask( m ); + bShowHiddenFiles = FALSE; + sortFilesBy = (int)TQDir::Name; + detailViewMode = FALSE; +#if defined(Q_WS_WIN) + if ( !fileIconProvider ) + fileIconProvider = new TQWindowsIconProvider( qApp ); +#endif + } +} + +/****************************************************************** + * + * Definitions of view classes + * + ******************************************************************/ + +class TQRenameEdit : public TQLineEdit +{ + Q_OBJECT + +public: + TQRenameEdit( TQWidget *parent ) + : TQLineEdit( parent, "qt_rename_edit" ), doRenameAlreadyEmitted(FALSE) + { + connect( this, SIGNAL(returnPressed()), SLOT(slotReturnPressed()) ); + } + +protected: + void keyPressEvent( TQKeyEvent *e ); + void focusOutEvent( TQFocusEvent *e ); + +signals: + void cancelRename(); + void doRename(); + +private slots: + void slotReturnPressed(); + +private: + bool doRenameAlreadyEmitted; +}; + +class TQFileListBox : public TQListBox +{ + friend class TQFileDialog; + + Q_OBJECT + +private: + TQFileListBox( TQWidget *parent, TQFileDialog *d ); + + void clear(); + void show(); + void startRename( bool check = TRUE ); + void viewportMousePressEvent( TQMouseEvent *e ); + void viewportMouseReleaseEvent( TQMouseEvent *e ); + void viewportMouseDoubleClickEvent( TQMouseEvent *e ); + void viewportMouseMoveEvent( TQMouseEvent *e ); +#ifndef QT_NO_DRAGANDDROP + void viewportDragEnterEvent( TQDragEnterEvent *e ); + void viewportDragMoveEvent( TQDragMoveEvent *e ); + void viewportDragLeaveEvent( TQDragLeaveEvent *e ); + void viewportDropEvent( TQDropEvent *e ); + bool acceptDrop( const TQPoint &pnt, TQWidget *source ); + void setCurrentDropItem( const TQPoint &pnt ); +#endif + void keyPressEvent( TQKeyEvent *e ); + +private slots: + void rename(); + void cancelRename(); + void doubleClickTimeout(); + void changeDirDuringDrag(); + void dragObjDestroyed(); + void contentsMoved( int, int ); + +private: + TQRenameEdit *lined; + TQFileDialog *filedialog; + bool renaming; + TQTimer* renameTimer; + TQListBoxItem *renameItem, *dragItem; + TQPoint pressPos, oldDragPos; + bool mousePressed; + int urls; + TQString startDragDir; + TQListBoxItem *currDropItem; + TQTimer *changeDirTimer; + bool firstMousePressEvent; + TQUrlOperator startDragUrl; + +}; + + +class TQFileDialogTQFileListView : public TQListView +{ + Q_OBJECT + +public: + TQFileDialogTQFileListView( TQWidget *parent, TQFileDialog *d ); + + void clear(); + void startRename( bool check = TRUE ); + void setSorting( int column, bool increasing = TRUE ); + + TQRenameEdit *lined; + bool renaming; + TQListViewItem *renameItem; + +private: + void viewportMousePressEvent( TQMouseEvent *e ); + void viewportMouseDoubleClickEvent( TQMouseEvent *e ); + void keyPressEvent( TQKeyEvent *e ); + void viewportMouseReleaseEvent( TQMouseEvent *e ); + void viewportMouseMoveEvent( TQMouseEvent *e ); +#ifndef QT_NO_DRAGANDDROP + void viewportDragEnterEvent( TQDragEnterEvent *e ); + void viewportDragMoveEvent( TQDragMoveEvent *e ); + void viewportDragLeaveEvent( TQDragLeaveEvent *e ); + void viewportDropEvent( TQDropEvent *e ); + bool acceptDrop( const TQPoint &pnt, TQWidget *source ); + void setCurrentDropItem( const TQPoint &pnt ); +#endif + +private slots: + void rename(); + void cancelRename(); + void changeSortColumn2( int column ); + void doubleClickTimeout(); + void changeDirDuringDrag(); + void dragObjDestroyed(); + void contentsMoved( int, int ); + +private: + TQFileDialog *filedialog; + TQTimer* renameTimer; + TQPoint pressPos, oldDragPos; + bool mousePressed; + int urls; + TQString startDragDir; + TQListViewItem *currDropItem, *dragItem; + TQTimer *changeDirTimer; + bool firstMousePressEvent; + bool ascending; + int sortcolumn; + TQUrlOperator startDragUrl; + +}; + +/**************************************************************************** + * + * Classes for copy progress dialog + * + ****************************************************************************/ + +class TQFDProgressAnimation : public TQWidget +{ + Q_OBJECT + +public: + TQFDProgressAnimation( TQWidget *parent ); + void start(); + +private slots: + void next(); + +protected: + void paintEvent( TQPaintEvent *e ); + +private: + int step; + TQTimer *timer; + +}; + +TQFDProgressAnimation::TQFDProgressAnimation( TQWidget *parent ) + : TQWidget( parent, "qt_progressanimation" ) +{ + setFixedSize( 300, 50 ); + step = -1; + next(); + timer = new TQTimer( this ); + connect( timer, SIGNAL( timeout() ), + this, SLOT( next() ) ); +} + +void TQFDProgressAnimation::start() +{ + timer->start( 150, FALSE ); +} + +void TQFDProgressAnimation::next() +{ + ++step; + if ( step > 10 ) + step = 0; + repaint(); +} + +void TQFDProgressAnimation::paintEvent( TQPaintEvent * ) +{ + erase(); + + TQPainter p; + p.begin( this ); + if ( step == 0 ) { + p.drawPixmap( 5, ( height() - startCopyIcon->height() ) / 2, + *startCopyIcon ); + p.drawPixmap( width() - 5 - openFolderIcon->width(), + ( height() - openFolderIcon->height() ) / 2 , *openFolderIcon ); + } else if ( step == 10 ) { + p.drawPixmap( 5, ( height() - openFolderIcon->height() ) / 2, + *openFolderIcon ); + p.drawPixmap( width() - 5 - endCopyIcon->width(), + ( height() - endCopyIcon->height() ) / 2 , *endCopyIcon ); + } else { + p.drawPixmap( 5, ( height() - openFolderIcon->height() ) / 2, + *openFolderIcon ); + p.drawPixmap( width() - 5 - openFolderIcon->width(), + ( height() - openFolderIcon->height() ) / 2 , *openFolderIcon ); + int x = 10 + openFolderIcon->width(); + int w = width() - 2 * x; + int s = w / 9; + p.drawPixmap( x + s * step, ( height() - fileIcon->height() ) / 2 - fileIcon->height(), + *fileIcon ); + } +} + + +class TQFDProgressDialog : public TQDialog +{ + Q_OBJECT + +public: + TQFDProgressDialog( TQWidget *parent, const TQString &fn, int steps ); + + void setReadProgress( int p ); + void setWriteProgress( int p ); + void setWriteLabel( const TQString &s ); + +signals: + void cancelled(); + +private: + TQProgressBar *readBar; + TQProgressBar *writeBar; + TQLabel *writeLabel; + TQFDProgressAnimation *animation; + +}; + +TQFDProgressDialog::TQFDProgressDialog( TQWidget *parent, const TQString &fn, int steps ) + : TQDialog( parent, "", TRUE ) +{ +#ifndef QT_NO_WIDGET_TOPEXTRA + setCaption( TQFileDialog::tr( "Copy or Move a File" ) ); +#endif + TQVBoxLayout *layout = new TQVBoxLayout( this ); + layout->setSpacing( 5 ); + layout->setMargin( 5 ); + + animation = new TQFDProgressAnimation( this ); + layout->addWidget( animation ); + + layout->addWidget( new TQLabel( TQFileDialog::tr( "Read: %1" ).arg( fn ), + this, "qt_read_lbl" ) ); + readBar = new TQProgressBar( steps, this, "qt_readbar" ); + readBar->reset(); + readBar->setProgress( 0 ); + layout->addWidget( readBar ); + writeLabel = new TQLabel( TQFileDialog::tr( "Write: %1" ).arg( TQString::null ), + this, "qt_write_lbl" ); + layout->addWidget( writeLabel ); + writeBar = new TQProgressBar( steps, this, "qt_writebar" ); + writeBar->reset(); + writeBar->setProgress( 0 ); + layout->addWidget( writeBar ); + + TQPushButton *b = new TQPushButton( TQFileDialog::tr( "Cancel" ), this, + "qt_cancel_btn" ); + b->setFixedSize( b->sizeHint() ); + layout->addWidget( b ); + connect( b, SIGNAL( clicked() ), + this, SIGNAL( cancelled() ) ); + + animation->start(); +} + +void TQFDProgressDialog::setReadProgress( int p ) +{ + readBar->setProgress( p ); +} + +void TQFDProgressDialog::setWriteProgress( int p ) +{ + writeBar->setProgress( p ); +} + +void TQFDProgressDialog::setWriteLabel( const TQString &s ) +{ + writeLabel->setText( TQFileDialog::tr( "Write: %1" ).arg( s ) ); +} + +/************************************************************************ + * + * Private TQFileDialog members + * + ************************************************************************/ + +class TQFileDialogPrivate { +public: + ~TQFileDialogPrivate(); + + TQStringList history; + + bool geometryDirty; + TQComboBox * paths; + TQComboBox * types; + TQLabel * pathL; + TQLabel * fileL; + TQLabel * typeL; + + TQVBoxLayout * topLevelLayout; + TQHBoxLayout *buttonLayout, *leftLayout, *rightLayout; + TQPtrList<TQHBoxLayout> extraWidgetsLayouts; + TQPtrList<TQLabel> extraLabels; + TQPtrList<TQWidget> extraWidgets; + TQPtrList<TQWidget> extraButtons; + TQPtrList<TQButton> toolButtons; + + TQWidgetStack * stack; + + TQToolButton * cdToParent, *newFolder, * detailView, * mcView, + *previewInfo, *previewContents, *goBack; + TQButtonGroup * modeButtons; + + TQString currentFileName; + TQListViewItem *last; + + TQListBoxItem *lastEFSelected; + + struct File: public TQListViewItem { + File( TQFileDialogPrivate * dlgp, + const TQUrlInfo * fi, TQListViewItem * parent ) + : TQListViewItem( parent, dlgp->last ), info( *fi ), d(dlgp), i( 0 ), hasMimePixmap( FALSE ) + { setup(); dlgp->last = this; } + File( TQFileDialogPrivate * dlgp, + const TQUrlInfo * fi, TQListView * parent ) + : TQListViewItem( parent, dlgp->last ), info( *fi ), d(dlgp), i( 0 ), hasMimePixmap( FALSE ) + { setup(); dlgp->last = this; } + File( TQFileDialogPrivate * dlgp, + const TQUrlInfo * fi, TQListView * parent, TQListViewItem * after ) + : TQListViewItem( parent, after ), info( *fi ), d(dlgp), i( 0 ), hasMimePixmap( FALSE ) + { setup(); if ( !nextSibling() ) dlgp->last = this; } + ~File(); + + TQString text( int column ) const; + const TQPixmap * pixmap( int ) const; + + TQUrlInfo info; + TQFileDialogPrivate * d; + TQListBoxItem *i; + bool hasMimePixmap; + }; + + class MCItem: public TQListBoxItem { + public: + MCItem( TQListBox *, TQListViewItem * item ); + MCItem( TQListBox *, TQListViewItem * item, TQListBoxItem *after ); + TQString text() const; + const TQPixmap *pixmap() const; + int height( const TQListBox * ) const; + int width( const TQListBox * ) const; + void paint( TQPainter * ); + TQListViewItem * i; + }; + + class UrlInfoList : public TQPtrList<TQUrlInfo> { + public: + UrlInfoList() { setAutoDelete( TRUE ); } + int compareItems( TQPtrCollection::Item n1, TQPtrCollection::Item n2 ) { + if ( !n1 || !n2 ) + return 0; + + TQUrlInfo *i1 = ( TQUrlInfo *)n1; + TQUrlInfo *i2 = ( TQUrlInfo *)n2; + + if ( i1->isDir() && !i2->isDir() ) + return -1; + if ( !i1->isDir() && i2->isDir() ) + return 1; + + if ( i1->name() == ".." ) + return -1; + if ( i2->name() == ".." ) + return 1; + + if ( sortFilesBy == TQDir::Name ) { +#if defined(Q_OS_WIN32) + TQString name1 = i1->name().lower(); + TQString name2 = i2->name().lower(); + return name1.localeAwareCompare( name2 ); +#else + TQString name1 = i1->name(); + TQString name2 = i2->name(); + return name1.localeAwareCompare( name2 ); +#endif + } + if ( TQUrlInfo::equal( *i1, *i2, sortFilesBy ) ) + return 0; + else if ( TQUrlInfo::greaterThan( *i1, *i2, sortFilesBy ) ) + return 1; + else if ( TQUrlInfo::lessThan( *i1, *i2, sortFilesBy ) ) + return -1; + // can't happen... + return 0; + } + TQUrlInfo *operator[]( int i ) { + return at( i ); + } + }; + + UrlInfoList sortedList; + TQPtrList<File> pendingItems; + + TQFileListBox * moreFiles; + + TQFileDialog::Mode mode; + + TQString rw; + TQString ro; + TQString wo; + TQString inaccessible; + + TQString symLinkToFile; + TQString file; + TQString symLinkToDir; + TQString dir; + TQString symLinkToSpecial; + TQString special; + TQWidgetStack *preview; + bool infoPreview, contentsPreview; + TQSplitter *splitter; + TQUrlOperator url, oldUrl; + TQWidget *infoPreviewWidget, *contentsPreviewWidget; + TQFilePreview *infoPreviewer, *contentsPreviewer; + bool hadDotDot; + + bool ignoreNextKeyPress; + // ignores the next refresh operation in case the user forced a selection + bool ignoreNextRefresh; + TQFDProgressDialog *progressDia; + bool checkForFilter; + bool ignoreStop; + + TQTimer *mimeTypeTimer; + const TQNetworkOperation *currListChildren; + + // this is similar to TQUrl::encode but does encode "*" and + // doesn't encode whitespaces + static TQString encodeFileName( const TQString& fName ) { + + TQString newStr; + TQCString cName = fName.utf8(); + const TQCString sChars( +#ifdef Q_WS_WIN + "#%" +#else + "<>#@\"&%$:,;?={}|^~[]\'`\\*" +#endif + ); + + int len = cName.length(); + if ( !len ) + return TQString::null; + for ( int i = 0; i < len ;++i ) { + uchar inCh = (uchar)cName[ i ]; + if ( inCh >= 128 || sChars.contains(inCh) ) + { + newStr += TQChar( '%' ); + ushort c = inCh / 16; + c += c > 9 ? 'A' - 10 : '0'; + newStr += (char)c; + c = inCh % 16; + c += c > 9 ? 'A' - 10 : '0'; + newStr += (char)c; + } else { + newStr += (char)inCh; + } + } + return newStr; + } + + static bool fileExists( const TQUrlOperator &url, const TQString& name ) + { + TQUrl u( url, TQFileDialogPrivate::encodeFileName(name) ); + if ( u.isLocalFile() ) { + TQFileInfo f( u.path() ); + return f.exists(); + } else { + TQNetworkProtocol *p = TQNetworkProtocol::getNetworkProtocol( url.protocol() ); + if ( p && (p->supportedOperations()&TQNetworkProtocol::OpListChildren) ) { + TQUrlInfo ui( url, name ); + return ui.isValid(); + } + } + return TRUE; + } + +#ifndef Q_NO_CURSOR + bool cursorOverride; // Remember if the cursor was overridden or not. +#endif +#ifdef Q_WS_WIN + int oldPermissionLookup; +#endif +}; + +TQFileDialogPrivate::~TQFileDialogPrivate() +{ + delete modeButtons; +} + + + +/************************************************************************ + * + * Internal class TQRenameEdit + * + ************************************************************************/ + +void TQRenameEdit::keyPressEvent( TQKeyEvent *e ) +{ + if ( e->key() == Key_Escape ) + emit cancelRename(); + else + TQLineEdit::keyPressEvent( e ); + e->accept(); +} + +void TQRenameEdit::focusOutEvent( TQFocusEvent * ) +{ + if ( !doRenameAlreadyEmitted ) + emit doRename(); + else + doRenameAlreadyEmitted = FALSE; +} + +void TQRenameEdit::slotReturnPressed() +{ + doRenameAlreadyEmitted = TRUE; + emit doRename(); +} + +/************************************************************************ + * + * Internal class TQFileListBox + * + ************************************************************************/ + +TQFileListBox::TQFileListBox( TQWidget *parent, TQFileDialog *dlg ) + : TQListBox( parent, "filelistbox" ), filedialog( dlg ), + renaming( FALSE ), renameItem( 0 ), mousePressed( FALSE ), + firstMousePressEvent( TRUE ) +{ + changeDirTimer = new TQTimer( this ); + TQVBox *box = new TQVBox( viewport(), "qt_vbox" ); + box->setFrameStyle( TQFrame::Box | TQFrame::Plain ); + lined = new TQRenameEdit( box ); + lined->setFixedHeight( lined->sizeHint().height() ); + box->hide(); + box->setBackgroundMode( PaletteBase ); + renameTimer = new TQTimer( this ); + connect( lined, SIGNAL( doRename() ), + this, SLOT (rename() ) ); + connect( lined, SIGNAL( cancelRename() ), + this, SLOT( cancelRename() ) ); + connect( renameTimer, SIGNAL( timeout() ), + this, SLOT( doubleClickTimeout() ) ); + connect( changeDirTimer, SIGNAL( timeout() ), + this, SLOT( changeDirDuringDrag() ) ); + connect( this, SIGNAL( contentsMoving(int,int) ), + this, SLOT( contentsMoved(int,int) ) ); + viewport()->setAcceptDrops( TRUE ); + dragItem = 0; +} + +void TQFileListBox::show() +{ + setBackgroundMode( PaletteBase ); + viewport()->setBackgroundMode( PaletteBase ); + TQListBox::show(); +} + +void TQFileListBox::keyPressEvent( TQKeyEvent *e ) +{ + if ( ( e->key() == Key_Enter || + e->key() == Key_Return ) && + renaming ) + return; + + TQString keyPressed = ((TQKeyEvent *)e)->text().lower(); + TQChar keyChar = keyPressed[0]; + bool handled = false; + if ( keyChar.isLetterOrNumber() ) { + TQListBoxItem * i = 0; + if ( currentItem() ) + i = item( currentItem() ); + else + i = firstItem(); + if ( i->next() ) + i = i->next(); + else + i = firstItem(); + while ( i != item( currentItem() ) ) { + TQString it = text( index( i ) ); + if ( it[0].lower() == keyChar ) { + clearSelection(); + setCurrentItem( i ); + handled = true; + e->accept(); + } else { + if ( i->next() ) + i = i->next(); + else + i = firstItem(); + } + } + } + cancelRename(); + if (!handled){ + TQListBox::keyPressEvent( e ); + } +} + +void TQFileListBox::viewportMousePressEvent( TQMouseEvent *e ) +{ + pressPos = e->pos(); + mousePressed = FALSE; + + bool didRename = renaming; + + cancelRename(); + if ( !hasFocus() && !viewport()->hasFocus() ) + setFocus(); + + if ( e->button() != LeftButton ) { + TQListBox::viewportMousePressEvent( e ); + firstMousePressEvent = FALSE; + return; + } + + int i = currentItem(); + bool wasSelected = FALSE; + if ( i != -1 ) + wasSelected = item( i )->isSelected(); + TQListBox::mousePressEvent( e ); + + TQFileDialogPrivate::MCItem *i1 = (TQFileDialogPrivate::MCItem*)item( currentItem() ); + if ( i1 ) + mousePressed = ( !( (TQFileDialogPrivate::File*)i1->i )->info.isDir() ) + || ( filedialog->mode() == TQFileDialog::Directory ) || ( filedialog->mode() == TQFileDialog::DirectoryOnly ); + + if ( itemAt( e->pos() ) != item( i ) ) { + firstMousePressEvent = FALSE; + return; + } + + if ( !firstMousePressEvent && !didRename && i == currentItem() && currentItem() != -1 && + wasSelected && TQUrlInfo( filedialog->d->url, "." ).isWritable() && item( currentItem() )->text() != ".." ) { + renameTimer->start( TQApplication::doubleClickInterval(), TRUE ); + renameItem = item( i ); + } + + firstMousePressEvent = FALSE; +} + +void TQFileListBox::viewportMouseReleaseEvent( TQMouseEvent *e ) +{ + dragItem = 0; + TQListBox::viewportMouseReleaseEvent( e ); + mousePressed = FALSE; +} + +void TQFileListBox::viewportMouseDoubleClickEvent( TQMouseEvent *e ) +{ + renameTimer->stop(); + TQListBox::viewportMouseDoubleClickEvent( e ); +} + +void TQFileListBox::viewportMouseMoveEvent( TQMouseEvent *e ) +{ + if ( !dragItem ) + dragItem = itemAt( e->pos() ); + renameTimer->stop(); +#ifndef QT_NO_DRAGANDDROP + if ( ( pressPos - e->pos() ).manhattanLength() > TQApplication::startDragDistance() && mousePressed ) { + TQListBoxItem *item = dragItem; + dragItem = 0; + if ( item ) { + if ( !itemRect( item ).contains( e->pos() ) ) + return; + TQUriDrag* drag = new TQUriDrag( viewport() ); + TQStringList files; + if ( filedialog->mode() == TQFileDialog::ExistingFiles ) + files = filedialog->selectedFiles(); + else + files = filedialog->selectedFile(); + drag->setFileNames( files ); + + if ( lined->parentWidget()->isVisible() ) + cancelRename(); + + connect( drag, SIGNAL( destroyed() ), + this, SLOT( dragObjDestroyed() ) ); + drag->drag(); + + mousePressed = FALSE; + } + } else +#endif + { + TQListBox::viewportMouseMoveEvent( e ); + } + +} + +void TQFileListBox::dragObjDestroyed() +{ +#ifndef QT_NO_DRAGANDDROP + //####### + //filedialog->rereadDir(); +#endif +} + +#ifndef QT_NO_DRAGANDDROP +void TQFileListBox::viewportDragEnterEvent( TQDragEnterEvent *e ) +{ + startDragUrl = filedialog->d->url; + startDragDir = filedialog->dirPath(); + currDropItem = 0; + + if ( !TQUriDrag::canDecode( e ) ) { + e->ignore(); + return; + } + + TQStringList l; + TQUriDrag::decodeLocalFiles( e, l ); + urls = (int)l.count(); + + if ( acceptDrop( e->pos(), e->source() ) ) { + e->accept(); + setCurrentDropItem( e->pos() ); + } else { + e->ignore(); + setCurrentDropItem( TQPoint( -1, -1 ) ); + } + + oldDragPos = e->pos(); +} + +void TQFileListBox::viewportDragMoveEvent( TQDragMoveEvent *e ) +{ + if ( acceptDrop( e->pos(), e->source() ) ) { + switch ( e->action() ) { + case TQDropEvent::Copy: + e->acceptAction(); + break; + case TQDropEvent::Move: + e->acceptAction(); + break; + case TQDropEvent::Link: + break; + default: + break; + } + if ( oldDragPos != e->pos() ) + setCurrentDropItem( e->pos() ); + } else { + changeDirTimer->stop(); + e->ignore(); + setCurrentDropItem( TQPoint( -1, -1 ) ); + } + + oldDragPos = e->pos(); +} + +void TQFileListBox::viewportDragLeaveEvent( TQDragLeaveEvent * ) +{ + changeDirTimer->stop(); + setCurrentDropItem( TQPoint( -1, -1 ) ); +//######## +// if ( startDragDir != filedialog->d->url ) +// filedialog->setUrl( startDragUrl ); +} + +void TQFileListBox::viewportDropEvent( TQDropEvent *e ) +{ + changeDirTimer->stop(); + + if ( !TQUriDrag::canDecode( e ) ) { + e->ignore(); + return; + } + + uint i; + TQStrList l; + TQUriDrag::decode( e, l ); + + bool move = e->action() == TQDropEvent::Move; +// bool supportAction = move || e->action() == TQDropEvent::Copy; + + TQUrlOperator dest; + if ( currDropItem ) + dest = TQUrlOperator( filedialog->d->url, TQFileDialogPrivate::encodeFileName( currDropItem->text() ) ); + else + dest = filedialog->d->url; + TQStringList lst; + for ( i = 0; i < l.count(); ++i ) { + lst << l.at( i ); + } + + // make sure that we can write to the destination before performing the action + bool exists = false; + TQString name = (currDropItem ? TQFileDialogPrivate::encodeFileName(currDropItem->text()) : TQString(".")); + TQUrlInfo info(filedialog->d->url, name); + for ( i = 0; i < lst.count(); ++i ) { + int slash = lst[i].findRev('/'); + TQString filename = lst[i].right(lst[i].length() - slash - 1); + exists = exists || TQFileDialogPrivate::fileExists( dest, filename); + } + if (info.isWritable() && !exists) + filedialog->d->url.copy( lst, dest, move ); + + // ##### what is supportAction for? + e->acceptAction(); + currDropItem = 0; +} + +bool TQFileListBox::acceptDrop( const TQPoint &pnt, TQWidget *source ) +{ + TQListBoxItem *item = itemAt( pnt ); + if ( !item || item && !itemRect( item ).contains( pnt ) ) { + if ( source == viewport() && startDragDir == filedialog->dirPath() ) + return FALSE; + return TRUE; + } + + TQUrlInfo fi( filedialog->d->url, item->text() ); + + if ( fi.isDir() && itemRect( item ).contains( pnt ) ) + return TRUE; + return FALSE; +} + +void TQFileListBox::setCurrentDropItem( const TQPoint &pnt ) +{ + changeDirTimer->stop(); + + TQListBoxItem *item = 0; + if ( pnt != TQPoint( -1, -1 ) ) + item = itemAt( pnt ); + if ( item && !TQUrlInfo( filedialog->d->url, item->text() ).isDir() ) + item = 0; + if ( item && !itemRect( item ).contains( pnt ) ) + item = 0; + + currDropItem = item; + if ( currDropItem ) + setCurrentItem( currDropItem ); + changeDirTimer->start( 750 ); +} +#endif // QT_NO_DRAGANDDROP + +void TQFileListBox::changeDirDuringDrag() +{ +#ifndef QT_NO_DRAGANDDROP + if ( !currDropItem ) + return; + changeDirTimer->stop(); + TQUrl u( filedialog->d->url, TQFileDialogPrivate::encodeFileName(currDropItem->text()) ); + filedialog->setDir( u ); + currDropItem = 0; +#endif +} + +void TQFileListBox::doubleClickTimeout() +{ + startRename(); + renameTimer->stop(); +} + +void TQFileListBox::startRename( bool check ) +{ + if ( check && ( !renameItem || renameItem != item( currentItem() ) ) ) + return; + + int i = currentItem(); + setSelected( i, TRUE ); + TQRect r = itemRect( item( i ) ); + int bdr = item( i )->pixmap() ? + item( i )->pixmap()->width() : 16; + int x = r.x() + bdr; + int y = r.y(); + int w = item( i )->width( this ) - bdr; + int h = TQMAX( lined->height() + 2, r.height() ); + y = y + r.height() / 2 - h / 2; + + lined->parentWidget()->setGeometry( x, y, w + 6, h ); + lined->setFocus(); + lined->setText( item( i )->text() ); + lined->selectAll(); + lined->setFrame( FALSE ); + lined->parentWidget()->show(); + viewport()->setFocusProxy( lined ); + renaming = TRUE; +} + +void TQFileListBox::clear() +{ + cancelRename(); + TQListBox::clear(); +} + +void TQFileListBox::rename() +{ + if ( !lined->text().isEmpty() ) { + TQString file = currentText(); + + if ( lined->text() != file ) + filedialog->d->url.rename( file, lined->text() ); + } + cancelRename(); +} + +void TQFileListBox::cancelRename() +{ + renameItem = 0; + lined->parentWidget()->hide(); + viewport()->setFocusProxy( this ); + renaming = FALSE; + updateItem( currentItem() ); + if ( lined->hasFocus() ) + viewport()->setFocus(); +} + +void TQFileListBox::contentsMoved( int, int ) +{ + changeDirTimer->stop(); +#ifndef QT_NO_DRAGANDDROP + setCurrentDropItem( TQPoint( -1, -1 ) ); +#endif +} + +/************************************************************************ + * + * Internal class TQFileListView + * + ************************************************************************/ + +TQFileDialogTQFileListView::TQFileDialogTQFileListView( TQWidget *parent, TQFileDialog *dlg ) + : TQListView( parent, "qt_filedlg_listview" ), renaming( FALSE ), renameItem( 0 ), + filedialog( dlg ), mousePressed( FALSE ), + firstMousePressEvent( TRUE ) +{ + changeDirTimer = new TQTimer( this ); + TQVBox *box = new TQVBox( viewport(), "qt_vbox" ); + box->setFrameStyle( TQFrame::Box | TQFrame::Plain ); + lined = new TQRenameEdit( box ); + lined->setFixedHeight( lined->sizeHint().height() ); + box->hide(); + box->setBackgroundMode( PaletteBase ); + renameTimer = new TQTimer( this ); + connect( lined, SIGNAL( doRename() ), + this, SLOT (rename() ) ); + connect( lined, SIGNAL( cancelRename() ), + this, SLOT( cancelRename() ) ); + header()->setMovingEnabled( FALSE ); + connect( renameTimer, SIGNAL( timeout() ), + this, SLOT( doubleClickTimeout() ) ); + connect( changeDirTimer, SIGNAL( timeout() ), + this, SLOT( changeDirDuringDrag() ) ); + disconnect( header(), SIGNAL( sectionClicked(int) ), + this, SLOT( changeSortColumn(int) ) ); + connect( header(), SIGNAL( sectionClicked(int) ), + this, SLOT( changeSortColumn2(int) ) ); + connect( this, SIGNAL( contentsMoving(int,int) ), + this, SLOT( contentsMoved(int,int) ) ); + + viewport()->setAcceptDrops( TRUE ); + sortcolumn = 0; + ascending = TRUE; + dragItem = 0; +} + +void TQFileDialogTQFileListView::setSorting( int column, bool increasing ) +{ + if ( column == -1 ) { + TQListView::setSorting( column, increasing ); + return; + } + + sortAscending = ascending = increasing; + sortcolumn = column; + switch ( column ) { + case 0: + sortFilesBy = TQDir::Name; + break; + case 1: + sortFilesBy = TQDir::Size; + break; + case 3: + sortFilesBy = TQDir::Time; + break; + default: + sortFilesBy = TQDir::Name; // #### ??? + break; + } + + filedialog->resortDir(); +} + +void TQFileDialogTQFileListView::changeSortColumn2( int column ) +{ + int lcol = header()->mapToLogical( column ); + setSorting( lcol, sortcolumn == lcol ? !ascending : TRUE ); +} + +void TQFileDialogTQFileListView::keyPressEvent( TQKeyEvent *e ) +{ + if ( ( e->key() == Key_Enter || + e->key() == Key_Return ) && + renaming ) + return; + + TQString keyPressed = e->text().lower(); + TQChar keyChar = keyPressed[0]; + if ( keyChar.isLetterOrNumber() ) { + TQListViewItem * i = 0; + if ( currentItem() ) + i = currentItem(); + else + i = firstChild(); + if ( i->nextSibling() ) + i = i->nextSibling(); + else + i = firstChild(); + while ( i != currentItem() ) { + TQString it = i->text(0); + if ( it[0].lower() == keyChar ) { + clearSelection(); + ensureItemVisible( i ); + setCurrentItem( i ); + } else { + if ( i->nextSibling() ) + i = i->nextSibling(); + else + i = firstChild(); + } + } + return; + } + + cancelRename(); + TQListView::keyPressEvent( e ); +} + +void TQFileDialogTQFileListView::viewportMousePressEvent( TQMouseEvent *e ) +{ + pressPos = e->pos(); + mousePressed = FALSE; + + bool didRename = renaming; + cancelRename(); + if ( !hasFocus() && !viewport()->hasFocus() ) + setFocus(); + + if ( e->button() != LeftButton ) { + TQListView::viewportMousePressEvent( e ); + firstMousePressEvent = FALSE; + return; + } + + TQListViewItem *i = currentItem(); + TQListView::viewportMousePressEvent( e ); + + TQFileDialogPrivate::File *i1 = (TQFileDialogPrivate::File*)currentItem(); + if ( i1 ) + mousePressed = !i1->info.isDir() || ( filedialog->mode() == TQFileDialog::Directory ) || ( filedialog->mode() == TQFileDialog::DirectoryOnly ); + + + if ( itemAt( e->pos() ) != i || + e->x() + contentsX() > columnWidth( 0 ) ) { + firstMousePressEvent = FALSE; + return; + } + + if ( !firstMousePressEvent && !didRename && i == currentItem() && currentItem() && + TQUrlInfo( filedialog->d->url, "." ).isWritable() && currentItem()->text( 0 ) != ".." ) { + renameTimer->start( TQApplication::doubleClickInterval(), TRUE ); + renameItem = currentItem(); + } + + firstMousePressEvent = FALSE; +} + +void TQFileDialogTQFileListView::viewportMouseDoubleClickEvent( TQMouseEvent *e ) +{ + renameTimer->stop(); + TQListView::viewportMouseDoubleClickEvent( e ); +} + +void TQFileDialogTQFileListView::viewportMouseReleaseEvent( TQMouseEvent *e ) +{ + TQListView::viewportMouseReleaseEvent( e ); + mousePressed = FALSE; + dragItem = 0; +} + +void TQFileDialogTQFileListView::viewportMouseMoveEvent( TQMouseEvent *e ) +{ + renameTimer->stop(); + if ( !dragItem ) + dragItem = itemAt( e->pos() ); +#ifndef QT_NO_DRAGANDDROP + if ( ( pressPos - e->pos() ).manhattanLength() > TQApplication::startDragDistance() && mousePressed ) { + TQListViewItem *item = dragItem; + dragItem = 0; + if ( item ) { + TQUriDrag* drag = new TQUriDrag( viewport() ); + TQStringList files; + if ( filedialog->mode() == TQFileDialog::ExistingFiles ) + files = filedialog->selectedFiles(); + else + files = filedialog->selectedFile(); + drag->setFileNames( files ); + + if ( lined->isVisible() ) + cancelRename(); + + connect( drag, SIGNAL( destroyed() ), + this, SLOT( dragObjDestroyed() ) ); + drag->drag(); + + mousePressed = FALSE; + } + } +#endif +} + +void TQFileDialogTQFileListView::dragObjDestroyed() +{ +#ifndef QT_NO_DRAGANDDROP + //###### + //filedialog->rereadDir(); +#endif +} + +#ifndef QT_NO_DRAGANDDROP +void TQFileDialogTQFileListView::viewportDragEnterEvent( TQDragEnterEvent *e ) +{ + startDragUrl = filedialog->d->url; + startDragDir = filedialog->dirPath(); + currDropItem = 0; + + if ( !TQUriDrag::canDecode( e ) ) { + e->ignore(); + return; + } + + TQStringList l; + TQUriDrag::decodeLocalFiles( e, l ); + urls = (int)l.count(); + + if ( acceptDrop( e->pos(), e->source() ) ) { + e->accept(); + setCurrentDropItem( e->pos() ); + } else { + e->ignore(); + setCurrentDropItem( TQPoint( -1, -1 ) ); + } + + oldDragPos = e->pos(); +} + +void TQFileDialogTQFileListView::viewportDragMoveEvent( TQDragMoveEvent *e ) +{ + if ( acceptDrop( e->pos(), e->source() ) ) { + if ( oldDragPos != e->pos() ) + setCurrentDropItem( e->pos() ); + switch ( e->action() ) { + case TQDropEvent::Copy: + e->acceptAction(); + break; + case TQDropEvent::Move: + e->acceptAction(); + break; + case TQDropEvent::Link: + break; + default: + break; + } + } else { + changeDirTimer->stop(); + e->ignore(); + setCurrentDropItem( TQPoint( -1, -1 ) ); + } + + oldDragPos = e->pos(); +} + +void TQFileDialogTQFileListView::viewportDragLeaveEvent( TQDragLeaveEvent * ) +{ + changeDirTimer->stop(); + setCurrentDropItem( TQPoint( -1, -1 ) ); +//######## +// if ( startDragDir != filedialog->d->url ) +// filedialog->setUrl( startDragUrl ); +} + +void TQFileDialogTQFileListView::viewportDropEvent( TQDropEvent *e ) +{ + changeDirTimer->stop(); + + if ( !TQUriDrag::canDecode( e ) ) { + e->ignore(); + return; + } + + TQStringList l; + TQUriDrag::decodeToUnicodeUris( e, l ); + + bool move = e->action() == TQDropEvent::Move; +// bool supportAction = move || e->action() == TQDropEvent::Copy; + + TQUrlOperator dest; + if ( currDropItem ) + dest = TQUrlOperator( filedialog->d->url, TQFileDialogPrivate::encodeFileName( currDropItem->text( 0 ) ) ); + else + dest = filedialog->d->url; + + // make sure that we can write to the destination before performing the action + bool exists = false; + TQString name = (currDropItem ? TQFileDialogPrivate::encodeFileName(currDropItem->text(0)) : TQString(".")); + TQUrlInfo info(filedialog->d->url, name); + for (uint i = 0; i < l.count(); ++i) { + int slash = l[i].findRev('/'); + TQString filename = l[i].right(l[i].length() - slash - 1); + exists = exists || TQFileDialogPrivate::fileExists(dest, filename); + } + if (info.isWritable() && !exists) + filedialog->d->url.copy( l, dest, move ); + + // ##### what is supportAction for? + e->acceptAction(); + currDropItem = 0; +} + +bool TQFileDialogTQFileListView::acceptDrop( const TQPoint &pnt, TQWidget *source ) +{ + TQListViewItem *item = itemAt( pnt ); + if ( !item || item && !itemRect( item ).contains( pnt ) ) { + if ( source == viewport() && startDragDir == filedialog->dirPath() ) + return FALSE; + return TRUE; + } + + TQUrlInfo fi( filedialog->d->url, item->text( 0 ) ); + + if ( fi.isDir() && itemRect( item ).contains( pnt ) ) + return TRUE; + return FALSE; +} + +void TQFileDialogTQFileListView::setCurrentDropItem( const TQPoint &pnt ) +{ + changeDirTimer->stop(); + + TQListViewItem *item = itemAt( pnt ); + if ( pnt == TQPoint( -1, -1 ) ) + item = 0; + if ( item && !TQUrlInfo( filedialog->d->url, item->text( 0 ) ).isDir() ) + item = 0; + + if ( item && !itemRect( item ).contains( pnt ) ) + item = 0; + + currDropItem = item; + + if ( currDropItem ) + setCurrentItem( currDropItem ); + + changeDirTimer->start( 750 ); +} +#endif // QT_NO_DRAGANDDROP + +void TQFileDialogTQFileListView::changeDirDuringDrag() +{ +#ifndef QT_NO_DRAGANDDROP + if ( !currDropItem ) + return; + changeDirTimer->stop(); + TQUrl u( filedialog->d->url, TQFileDialogPrivate::encodeFileName(currDropItem->text( 0 ) ) ); + filedialog->setDir( u ); + currDropItem = 0; +#endif // QT_NO_DRAGANDDROP +} + + +void TQFileDialogTQFileListView::doubleClickTimeout() +{ + startRename(); + renameTimer->stop(); +} + +void TQFileDialogTQFileListView::startRename( bool check ) +{ + if ( check && ( !renameItem || renameItem != currentItem() ) ) + return; + + TQListViewItem *i = currentItem(); + setSelected( i, TRUE ); + + TQRect r = itemRect( i ); + int bdr = i->pixmap( 0 ) ? + i->pixmap( 0 )->width() : 16; + int x = r.x() + bdr; + int y = r.y(); + int w = columnWidth( 0 ) - bdr; + int h = TQMAX( lined->height() + 2, r.height() ); + y = y + r.height() / 2 - h / 2; + + lined->parentWidget()->setGeometry( x, y, w + 6, h ); + lined->setFocus(); + lined->setText( i->text( 0 ) ); + lined->selectAll(); + lined->setFrame( FALSE ); + lined->parentWidget()->show(); + viewport()->setFocusProxy( lined ); + renaming = TRUE; +} + +void TQFileDialogTQFileListView::clear() +{ + cancelRename(); + TQListView::clear(); +} + +void TQFileDialogTQFileListView::rename() +{ + if ( !lined->text().isEmpty() ) { + TQString file = currentItem()->text( 0 ); + + if ( lined->text() != file ) + filedialog->d->url.rename( file, lined->text() ); + } + cancelRename(); +} + +void TQFileDialogTQFileListView::cancelRename() +{ + renameItem = 0; + lined->parentWidget()->hide(); + viewport()->setFocusProxy( this ); + renaming = FALSE; + if ( currentItem() ) + currentItem()->repaint(); + if ( lined->hasFocus() ) + viewport()->setFocus(); +} + +void TQFileDialogTQFileListView::contentsMoved( int, int ) +{ + changeDirTimer->stop(); +#ifndef QT_NO_DRAGANDDROP + setCurrentDropItem( TQPoint( -1, -1 ) ); +#endif +} + + +TQFileDialogPrivate::File::~File() +{ + if ( d->pendingItems.findRef( this ) ) + d->pendingItems.removeRef( this ); +} + +TQString TQFileDialogPrivate::File::text( int column ) const +{ + makeVariables(); + + switch( column ) { + case 0: + return info.name(); + case 1: + if ( info.isFile() ) { +#if (QT_VERSION-0 >= 0x040000) +#error "clean up Large File Support" +#elif defined(QT_ABI_QT4) + TQIODevice::Offset size = info.size(); +#else + uint size = info.size(); +#endif +#if defined(QT_LARGEFILE_SUPPORT) && defined(Q_OS_UNIX) + // ### the following code should not be needed as soon + // ### as TQUrlInfo::size() can return 64-bit + if ( size > INT_MAX ) { + struct stat buffer; + if ( ::stat( TQFile::encodeName(info.name()), &buffer ) == 0 ) { + Q_ULLONG size64 = (Q_ULLONG)buffer.st_size; + return TQString::number(size64); + } + } +#endif + return TQString::number(size); + } else { + return TQString::fromLatin1(""); + } + case 2: + if ( info.isFile() && info.isSymLink() ) { + return d->symLinkToFile; + } else if ( info.isFile() ) { + return d->file; + } else if ( info.isDir() && info.isSymLink() ) { + return d->symLinkToDir; + } else if ( info.isDir() ) { + return d->dir; + } else if ( info.isSymLink() ) { + return d->symLinkToSpecial; + } else { + return d->special; + } + case 3: { + return info.lastModified().toString( TQt::LocalDate ); + } + case 4: + if ( info.isReadable() ) + return info.isWritable() ? d->rw : d->ro; + else + return info.isWritable() ? d->wo : d->inaccessible; + } + + return TQString::fromLatin1("<--->"); +} + +const TQPixmap * TQFileDialogPrivate::File::pixmap( int column ) const +{ + if ( column ) { + return 0; + } else if ( TQListViewItem::pixmap( column ) ) { + return TQListViewItem::pixmap( column ); + } else if ( info.isSymLink() ) { + if ( info.isFile() ) + return symLinkFileIcon; + else + return symLinkDirIcon; + } else if ( info.isDir() ) { + return closedFolderIcon; + } else if ( info.isFile() ) { + return fileIcon; + } else { + return fifteenTransparentPixels; + } +} + +TQFileDialogPrivate::MCItem::MCItem( TQListBox * lb, TQListViewItem * item ) + : TQListBoxItem() +{ + i = item; + if ( lb ) + lb->insertItem( this ); +} + +TQFileDialogPrivate::MCItem::MCItem( TQListBox * lb, TQListViewItem * item, TQListBoxItem *after ) + : TQListBoxItem() +{ + i = item; + if ( lb ) + lb->insertItem( this, after ); +} + +TQString TQFileDialogPrivate::MCItem::text() const +{ + return i->text( 0 ); +} + + +const TQPixmap *TQFileDialogPrivate::MCItem::pixmap() const +{ + return i->pixmap( 0 ); +} + + +int TQFileDialogPrivate::MCItem::height( const TQListBox * lb ) const +{ + int hf = lb->fontMetrics().height(); + int hp = pixmap() ? pixmap()->height() : 0; + return TQMAX(hf, hp) + 2; +} + + +int TQFileDialogPrivate::MCItem::width( const TQListBox * lb ) const +{ + TQFontMetrics fm = lb->fontMetrics(); + int w = 2; + if ( pixmap() ) + w += pixmap()->width() + 4; + else + w += 18; + w += fm.width( text() ); + w += -fm.minLeftBearing(); + w += -fm.minRightBearing(); + w += 6; + return w; +} + + +void TQFileDialogPrivate::MCItem::paint( TQPainter * ptr ) +{ + TQFontMetrics fm = ptr->fontMetrics(); + + int h; + + if ( pixmap() ) + h = TQMAX( fm.height(), pixmap()->height()) + 2; + else + h = fm.height() + 2; + + const TQPixmap * pm = pixmap(); + if ( pm ) + ptr->drawPixmap( 2, 1, *pm ); + + ptr->drawText( pm ? pm->width() + 4 : 22, h - fm.descent() - 2, + text() ); +} + +static TQStringList makeFiltersList( const TQString &filter ) +{ + if ( filter.isEmpty() ) + return TQStringList(); + + int i = filter.find( ";;", 0 ); + TQString sep( ";;" ); + if ( i == -1 ) { + if ( filter.find( "\n", 0 ) != -1 ) { + sep = "\n"; + i = filter.find( sep, 0 ); + } + } + + return TQStringList::split( sep, filter ); +} + +/*! + \class TQFileDialog qfiledialog.h + \brief The TQFileDialog class provides dialogs that allow users to select files or directories. + \ingroup dialogs + \mainclass + + The TQFileDialog class enables a user to traverse their file system in + order to select one or many files or a directory. + + The easiest way to create a TQFileDialog is to use the static + functions. On Windows, these static functions will call the native + Windows file dialog and on Mac OS X, these static function will call + the native Mac OS X file dialog. + + \code + TQString s = TQFileDialog::getOpenFileName( + "/home", + "Images (*.png *.xpm *.jpg)", + this, + "open file dialog", + "Choose a file" ); + \endcode + + In the above example, a modal TQFileDialog is created using a static + function. The startup directory is set to "/home". The file filter + is set to "Images (*.png *.xpm *.jpg)". The parent of the file dialog + is set to \e this and it is given the identification name - "open file + dialog". The caption at the top of file dialog is set to "Choose a + file". If you want to use multiple filters, separate each one with + \e two semi-colons, e.g. + \code + "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)" + \endcode + + You can create your own TQFileDialog without using the static + functions. By calling setMode(), you can set what can be returned by + the TQFileDialog. + + \code + TQFileDialog* fd = new TQFileDialog( this, "file dialog", TRUE ); + fd->setMode( TQFileDialog::AnyFile ); + \endcode + + In the above example, the mode of the file dialog is set to \c + AnyFile, meaning that the user can select any file, or even specify a + file that doesn't exist. This mode is useful for creating a "File Save + As" file dialog. Use \c ExistingFile if the user must select an + existing file or \c Directory if only a directory may be selected. + (See the \l TQFileDialog::Mode enum for the complete list of modes.) + + You can retrieve the dialog's mode with mode(). Use setFilter() to set + the dialog's file filter, e.g. + + \code + fd->setFilter( "Images (*.png *.xpm *.jpg)" ); + \endcode + + In the above example, the filter is set to "Images (*.png *.xpm + *.jpg)", this means that only files with the extension \c png, \c xpm + or \c jpg will be shown in the TQFileDialog. You can apply + several filters by using setFilters() and add additional filters with + addFilter(). Use setSelectedFilter() to select one of the filters + you've given as the file dialog's default filter. Whenever the user + changes the filter the filterSelected() signal is emitted. + + The file dialog has two view modes, TQFileDialog::List which simply + lists file and directory names and TQFileDialog::Detail which + displays additional information alongside each name, e.g. file size, + modification date, etc. Set the mode with setViewMode(). + + \code + fd->setViewMode( TQFileDialog::Detail ); + \endcode + + The last important function you will need to use when creating your + own file dialog is selectedFile(). + + \code + TQString fileName; + if ( fd->exec() == TQDialog::Accepted ) + fileName = fd->selectedFile(); + \endcode + + In the above example, a modal file dialog is created and shown. If + the user clicked OK, then the file they selected is put in \c + fileName. + + If you are using the \c ExistingFiles mode then you will need to use + selectedFiles() which will return the selected files in a TQStringList. + + The dialog's working directory can be set with setDir(). The display + of hidden files is controlled with setShowHiddenFiles(). The dialog + can be forced to re-read the directory with rereadDir() and re-sort + the directory with resortDir(). All the files in the current directory + can be selected with selectAll(). + + \section1 Creating and using preview widgets + + There are two kinds of preview widgets that can be used with + TQFileDialogs: \e content preview widgets and \e information preview + widgets. They are created and used in the same way except that the + function names differ, e.g. setContentsPreview() and setInfoPreview(). + + A preview widget is a widget that is placed inside a TQFileDialog so + that the user can see either the contents of the file, or information + about the file. + + \code + class Preview : public TQLabel, public TQFilePreview + { + public: + Preview( TQWidget *parent=0 ) : TQLabel( parent ) {} + + void previewUrl( const TQUrl &u ) + { + TQString path = u.path(); + TQPixmap pix( path ); + if ( pix.isNull() ) + setText( "This is not a pixmap" ); + else + setPixmap( pix ); + } + }; + \endcode + + In the above snippet, we create a preview widget which inherits from + TQLabel and TQFilePreview. File preview widgets \e must inherit from + TQFilePreview. + + Inside the class we reimplement TQFilePreview::previewUrl(), this is + where we determine what happens when a file is selected. In the + above example we only show a preview of the file if it is a valid + pixmap. Here's how to make a file dialog use a preview widget: + + \code + Preview* p = new Preview; + + TQFileDialog* fd = new TQFileDialog( this ); + fd->setContentsPreviewEnabled( TRUE ); + fd->setContentsPreview( p, p ); + fd->setPreviewMode( TQFileDialog::Contents ); + fd->show(); + \endcode + + The first line creates an instance of our preview widget. We then + create our file dialog and call setContentsPreviewEnabled( TRUE ), + this tell the file dialog to preview the contents of the currently + selected file. We then call setContentsPreview() -- note that we pass + the same preview widget twice. Finally, before showing the file + dialog, we call setPreviewMode() setting the mode to \e Contents which + will show the contents preview of the file that the user has selected. + + If you create another preview widget that is used for displaying + information about a file, create it in the same way as the contents + preview widget and call setInfoPreviewEnabled(), and + setInfoPreview(). Then the user will be able to switch between the + two preview modes. + + For more information about creating a TQFilePreview widget see + \l{TQFilePreview}. + + <img src=qfiledlg-m.png> <img src=qfiledlg-w.png> + +*/ + + +/*! \enum TQFileDialog::Mode + + This enum is used to indicate what the user may select in the file + dialog, i.e. what the dialog will return if the user clicks OK. + + \value AnyFile The name of a file, whether it exists or not. + \value ExistingFile The name of a single existing file. + \value Directory The name of a directory. Both files and directories + are displayed. + \value DirectoryOnly The name of a directory. The file dialog will only display directories. + \value ExistingFiles The names of zero or more existing files. + + See setMode(). +*/ + +/*! + \enum TQFileDialog::ViewMode + + This enum describes the view mode of the file dialog, i.e. what + information about each file will be displayed. + + \value List Display file and directory names with icons. + \value Detail Display file and directory names with icons plus + additional information, such as file size and modification date. + + See setViewMode(). +*/ + +/*! + \enum TQFileDialog::PreviewMode + + This enum describes the preview mode of the file dialog. + + \value NoPreview No preview is shown at all. + \value Contents Show a preview of the contents of the current file + using the contents preview widget. + \value Info Show information about the current file using the + info preview widget. + + See setPreviewMode(), setContentsPreview() and setInfoPreview(). +*/ + +/*! + \fn void TQFileDialog::detailViewSelectionChanged() + \internal +*/ + +/*! + \fn void TQFileDialog::listBoxSelectionChanged() + \internal +*/ + +extern const char qt_file_dialog_filter_reg_exp[] = + "([a-zA-Z0-9 ]*)\\(([a-zA-Z0-9_.*? +;#\\[\\]]*)\\)$"; + +/*! + Constructs a file dialog called \a name, with the parent, \a parent. + If \a modal is TRUE then the file dialog is modal; otherwise it is + modeless. +*/ + +TQFileDialog::TQFileDialog( TQWidget *parent, const char *name, bool modal ) + : TQDialog( parent, name, modal, + (modal ? + (WStyle_Customize | WStyle_DialogBorder | WStyle_Title | WStyle_SysMenu) : 0) ) +{ + init(); + d->mode = ExistingFile; + d->types->insertItem( tr( "All Files (*)" ) ); + d->cursorOverride = FALSE; + emit dirEntered( d->url.dirPath() ); + rereadDir(); +} + + +/*! + Constructs a file dialog called \a name with the parent, \a parent. + If \a modal is TRUE then the file dialog is modal; otherwise it is + modeless. + + If \a dirName is specified then it will be used as the dialog's + working directory, i.e. it will be the directory that is shown when + the dialog appears. If \a filter is specified it will be used as the + dialog's file filter. + +*/ + +TQFileDialog::TQFileDialog( const TQString& dirName, const TQString & filter, + TQWidget *parent, const char *name, bool modal ) + : TQDialog( parent, name, modal, + (modal ? + (WStyle_Customize | WStyle_DialogBorder | WStyle_Title | WStyle_SysMenu) : 0) ) +{ + init(); + d->mode = ExistingFile; + rereadDir(); + TQUrlOperator u( dirName ); + if ( !dirName.isEmpty() && ( !u.isLocalFile() || TQDir( dirName ).exists() ) ) + setSelection( dirName ); + else if ( workingDirectory && !workingDirectory->isEmpty() ) + setDir( *workingDirectory ); + + if ( !filter.isEmpty() ) { + setFilters( filter ); + if ( !dirName.isEmpty() ) { + int dotpos = dirName.find( TQChar('.'), 0, FALSE ); + if ( dotpos != -1 ) { + for ( int b=0 ; b<d->types->count() ; b++ ) { + if ( d->types->text(b).contains( dirName.right( dirName.length() - dotpos ) ) ) { + d->types->setCurrentItem( b ); + setFilter( d->types->text( b ) ); + return; + } + } + } + } + } else { + d->types->insertItem( tr( "All Files (*)" ) ); + } +} + + +#if defined(Q_WS_WIN) +extern int qt_ntfs_permission_lookup; +#endif + +/*! + \internal + Initializes the file dialog. +*/ + +void TQFileDialog::init() +{ + setSizeGripEnabled( TRUE ); + d = new TQFileDialogPrivate(); + d->mode = AnyFile; + d->last = 0; + d->lastEFSelected = 0; + d->moreFiles = 0; + d->infoPreview = FALSE; + d->contentsPreview = FALSE; + d->hadDotDot = FALSE; + d->ignoreNextKeyPress = FALSE; + d->progressDia = 0; + d->checkForFilter = FALSE; + d->ignoreNextRefresh = FALSE; + d->ignoreStop = FALSE; + d->pendingItems.setAutoDelete( FALSE ); + d->mimeTypeTimer = new TQTimer( this ); + d->cursorOverride = FALSE; +#if defined(Q_WS_WIN) + d->oldPermissionLookup = qt_ntfs_permission_lookup; +#endif + connect( d->mimeTypeTimer, SIGNAL( timeout() ), + this, SLOT( doMimeTypeLookup() ) ); + + d->url = TQUrlOperator( ::toRootIfNotExists( TQDir::currentDirPath() ) ); + d->oldUrl = d->url; + d->currListChildren = 0; + + connect( &d->url, SIGNAL( start(TQNetworkOperation*) ), + this, SLOT( urlStart(TQNetworkOperation*) ) ); + connect( &d->url, SIGNAL( finished(TQNetworkOperation*) ), + this, SLOT( urlFinished(TQNetworkOperation*) ) ); + connect( &d->url, SIGNAL( newChildren(const TQValueList<TQUrlInfo>&,TQNetworkOperation*) ), + this, SLOT( insertEntry(const TQValueList<TQUrlInfo>&,TQNetworkOperation*) ) ); + connect( &d->url, SIGNAL( removed(TQNetworkOperation*) ), + this, SLOT( removeEntry(TQNetworkOperation*) ) ); + connect( &d->url, SIGNAL( createdDirectory(const TQUrlInfo&,TQNetworkOperation*) ), + this, SLOT( createdDirectory(const TQUrlInfo&,TQNetworkOperation*) ) ); + connect( &d->url, SIGNAL( itemChanged(TQNetworkOperation*) ), + this, SLOT( itemChanged(TQNetworkOperation*) ) ); + connect( &d->url, SIGNAL( dataTransferProgress(int,int,TQNetworkOperation*) ), + this, SLOT( dataTransferProgress(int,int,TQNetworkOperation*) ) ); + + nameEdit = new TQLineEdit( this, "name/filter editor" ); + nameEdit->setMaxLength( 255 ); //_POSIX_MAX_PATH + connect( nameEdit, SIGNAL(textChanged(const TQString&)), + this, SLOT(fileNameEditDone()) ); + nameEdit->installEventFilter( this ); + + d->splitter = new TQSplitter( this, "qt_splitter" ); + + d->stack = new TQWidgetStack( d->splitter, "files and more files" ); + + d->splitter->setSizePolicy( TQSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Expanding ) ); + + files = new TQFileDialogTQFileListView( d->stack, this ); + TQFontMetrics fm = fontMetrics(); + files->addColumn( tr("Name") ); + files->addColumn( tr("Size") ); + files->setColumnAlignment( 1, AlignRight ); + files->addColumn( tr("Type") ); + files->addColumn( tr("Date") ); + files->addColumn( tr("Attributes") ); + files->header()->setStretchEnabled( TRUE, 0 ); + + files->setMinimumSize( 50, 25 + 2*fm.lineSpacing() ); + + connect( files, SIGNAL( selectionChanged() ), + this, SLOT( detailViewSelectionChanged() ) ); + connect( files, SIGNAL(currentChanged(TQListViewItem*)), + this, SLOT(updateFileNameEdit(TQListViewItem*)) ); + connect( files, SIGNAL(doubleClicked(TQListViewItem*)), + this, SLOT(selectDirectoryOrFile(TQListViewItem*)) ); + connect( files, SIGNAL(returnPressed(TQListViewItem*)), + this, SLOT(selectDirectoryOrFile(TQListViewItem*)) ); + connect( files, SIGNAL(rightButtonPressed(TQListViewItem*,const TQPoint&,int)), + this, SLOT(popupContextMenu(TQListViewItem*,const TQPoint&,int)) ); + + files->installEventFilter( this ); + files->viewport()->installEventFilter( this ); + + d->moreFiles = new TQFileListBox( d->stack, this ); + d->moreFiles->setRowMode( TQListBox::FitToHeight ); + d->moreFiles->setVariableWidth( TRUE ); + + connect( d->moreFiles, SIGNAL(selected(TQListBoxItem*)), + this, SLOT(selectDirectoryOrFile(TQListBoxItem*)) ); + connect( d->moreFiles, SIGNAL( selectionChanged() ), + this, SLOT( listBoxSelectionChanged() ) ); + connect( d->moreFiles, SIGNAL(highlighted(TQListBoxItem*)), + this, SLOT(updateFileNameEdit(TQListBoxItem*)) ); + connect( d->moreFiles, SIGNAL( rightButtonPressed(TQListBoxItem*,const TQPoint&) ), + this, SLOT( popupContextMenu(TQListBoxItem*,const TQPoint&) ) ); + + d->moreFiles->installEventFilter( this ); + d->moreFiles->viewport()->installEventFilter( this ); + + okB = new TQPushButton( tr("&OK"), this, "OK" ); //### Or "Save (see other "OK") + okB->setDefault( TRUE ); + okB->setEnabled( FALSE ); + connect( okB, SIGNAL(clicked()), this, SLOT(okClicked()) ); + cancelB = new TQPushButton( tr("Cancel") , this, "Cancel" ); + connect( cancelB, SIGNAL(clicked()), this, SLOT(cancelClicked()) ); + + d->paths = new TQComboBox( TRUE, this, "directory history/editor" ); + d->paths->setDuplicatesEnabled( FALSE ); + d->paths->setInsertionPolicy( TQComboBox::NoInsertion ); + const TQFileInfoList * rootDrives = TQDir::drives(); + TQFileInfoListIterator it( *rootDrives ); + TQFileInfo *fi; + makeVariables(); + + while ( (fi = it.current()) != 0 ) { + ++it; + d->paths->insertItem( *openFolderIcon, fi->absFilePath() ); + } + + if ( !!TQDir::homeDirPath() ) { + if ( !d->paths->listBox()->findItem( TQDir::homeDirPath() ) ) + d->paths->insertItem( *openFolderIcon, TQDir::homeDirPath() ); + } + + connect( d->paths, SIGNAL(activated(const TQString&)), + this, SLOT(setDir(const TQString&)) ); + + d->paths->installEventFilter( this ); + TQObjectList *ol = d->paths->queryList( "TQLineEdit" ); + if ( ol && ol->first() ) + ( (TQLineEdit*)ol->first() )->installEventFilter( this ); + delete ol; + + d->geometryDirty = TRUE; + d->types = new TQComboBox( TRUE, this, "file types" ); + d->types->setDuplicatesEnabled( FALSE ); + d->types->setEditable( FALSE ); + connect( d->types, SIGNAL(activated(const TQString&)), + this, SLOT(setFilter(const TQString&)) ); + connect( d->types, SIGNAL(activated(const TQString&)), + this, SIGNAL(filterSelected(const TQString&)) ); + + d->pathL = new TQLabel( d->paths, tr("Look &in:"), this, "qt_looin_lbl" ); + d->fileL = new TQLabel( nameEdit, tr("File &name:"), this, "qt_filename_lbl" ); + d->typeL = new TQLabel( d->types, tr("File &type:"), this, "qt_filetype_lbl" ); + + d->goBack = new TQToolButton( this, "go back" ); + d->goBack->setEnabled( FALSE ); + d->goBack->setFocusPolicy( TabFocus ); + connect( d->goBack, SIGNAL( clicked() ), this, SLOT( goBack() ) ); +#ifndef QT_NO_TOOLTIP + TQToolTip::add( d->goBack, tr( "Back" ) ); +#endif + d->goBack->setIconSet( *goBackIcon ); + + d->cdToParent = new TQToolButton( this, "cd to parent" ); + d->cdToParent->setFocusPolicy( TabFocus ); +#ifndef QT_NO_TOOLTIP + TQToolTip::add( d->cdToParent, tr( "One directory up" ) ); +#endif + d->cdToParent->setIconSet( *cdToParentIcon ); + connect( d->cdToParent, SIGNAL(clicked()), + this, SLOT(cdUpClicked()) ); + + d->newFolder = new TQToolButton( this, "new folder" ); + d->newFolder->setFocusPolicy( TabFocus ); +#ifndef QT_NO_TOOLTIP + TQToolTip::add( d->newFolder, tr( "Create New Folder" ) ); +#endif + d->newFolder->setIconSet( *newFolderIcon ); + connect( d->newFolder, SIGNAL(clicked()), + this, SLOT(newFolderClicked()) ); + + d->modeButtons = new TQButtonGroup( 0, "invisible group" ); + connect( d->modeButtons, SIGNAL(destroyed()), + this, SLOT(modeButtonsDestroyed()) ); + d->modeButtons->setExclusive( TRUE ); + connect( d->modeButtons, SIGNAL(clicked(int)), + d->stack, SLOT(raiseWidget(int)) ); + connect( d->modeButtons, SIGNAL(clicked(int)), + this, SLOT(changeMode(int)) ); + + d->mcView = new TQToolButton( this, "mclistbox view" ); + d->mcView->setFocusPolicy( TabFocus ); +#ifndef QT_NO_TOOLTIP + TQToolTip::add( d->mcView, tr( "List View" ) ); +#endif + d->mcView->setIconSet( *multiColumnListViewIcon ); + d->mcView->setToggleButton( TRUE ); + d->stack->addWidget( d->moreFiles, d->modeButtons->insert( d->mcView ) ); + d->detailView = new TQToolButton( this, "list view" ); + d->detailView->setFocusPolicy( TabFocus ); +#ifndef QT_NO_TOOLTIP + TQToolTip::add( d->detailView, tr( "Detail View" ) ); +#endif + d->detailView->setIconSet( *detailViewIcon ); + d->detailView->setToggleButton( TRUE ); + d->stack->addWidget( files, d->modeButtons->insert( d->detailView ) ); + + d->previewInfo = new TQToolButton( this, "preview info view" ); + d->previewInfo->setFocusPolicy( TabFocus ); +#ifndef QT_NO_TOOLTIP + TQToolTip::add( d->previewInfo, tr( "Preview File Info" ) ); +#endif + d->previewInfo->setIconSet( *previewInfoViewIcon ); + d->previewInfo->setToggleButton( TRUE ); + d->modeButtons->insert( d->previewInfo ); + + d->previewContents = new TQToolButton( this, "preview info view" ); +#if defined(Q_WS_WIN) && !defined(Q_OS_TEMP) + if ( (qt_winver & WV_NT_based) > TQt::WV_NT ) +#else + if ( !qstrcmp(style().className(), "TQWindowsStyle") ) +#endif + { + d->goBack->setAutoRaise( TRUE ); + d->cdToParent->setAutoRaise( TRUE ); + d->newFolder->setAutoRaise( TRUE ); + d->mcView->setAutoRaise( TRUE ); + d->detailView->setAutoRaise( TRUE ); + d->previewInfo->setAutoRaise( TRUE ); + d->previewContents->setAutoRaise( TRUE ); + } + d->previewContents->setFocusPolicy( TabFocus ); +#ifndef QT_NO_TOOLTIP + TQToolTip::add( d->previewContents, tr( "Preview File Contents" ) ); +#endif + d->previewContents->setIconSet( *previewContentsViewIcon ); + d->previewContents->setToggleButton( TRUE ); + d->modeButtons->insert( d->previewContents ); + + connect( d->detailView, SIGNAL( clicked() ), + d->moreFiles, SLOT( cancelRename() ) ); + connect( d->detailView, SIGNAL( clicked() ), + files, SLOT( cancelRename() ) ); + connect( d->mcView, SIGNAL( clicked() ), + d->moreFiles, SLOT( cancelRename() ) ); + connect( d->mcView, SIGNAL( clicked() ), + files, SLOT( cancelRename() ) ); + + d->stack->raiseWidget( d->moreFiles ); + d->mcView->setOn( TRUE ); + + TQHBoxLayout *lay = new TQHBoxLayout( this ); + lay->setMargin( 6 ); + d->leftLayout = new TQHBoxLayout( lay, 5 ); + d->topLevelLayout = new TQVBoxLayout( (TQWidget*)0, 5 ); + lay->addLayout( d->topLevelLayout, 1 ); + d->extraWidgetsLayouts.setAutoDelete( FALSE ); + d->extraLabels.setAutoDelete( FALSE ); + d->extraWidgets.setAutoDelete( FALSE ); + d->extraButtons.setAutoDelete( FALSE ); + d->toolButtons.setAutoDelete( FALSE ); + + TQHBoxLayout * h; + + d->preview = new TQWidgetStack( d->splitter, "qt_preview" ); + + d->infoPreviewWidget = new TQWidget( d->preview, "qt_preview_info" ); + d->contentsPreviewWidget = new TQWidget( d->preview, "qt_preview_contents" ); + d->infoPreviewer = d->contentsPreviewer = 0; + + h = new TQHBoxLayout( 0 ); + d->buttonLayout = h; + d->topLevelLayout->addLayout( h ); + h->addWidget( d->pathL ); + h->addSpacing( 8 ); + h->addWidget( d->paths ); + h->addSpacing( 8 ); + if ( d->goBack ) + h->addWidget( d->goBack ); + h->addWidget( d->cdToParent ); + h->addSpacing( 2 ); + h->addWidget( d->newFolder ); + h->addSpacing( 4 ); + h->addWidget( d->mcView ); + h->addWidget( d->detailView ); + h->addWidget( d->previewInfo ); + h->addWidget( d->previewContents ); + + d->topLevelLayout->addWidget( d->splitter ); + + h = new TQHBoxLayout(); + d->topLevelLayout->addLayout( h ); + h->addWidget( d->fileL ); + h->addWidget( nameEdit ); + h->addSpacing( 15 ); + h->addWidget( okB ); + + h = new TQHBoxLayout(); + d->topLevelLayout->addLayout( h ); + h->addWidget( d->typeL ); + h->addWidget( d->types ); + h->addSpacing( 15 ); + h->addWidget( cancelB ); + + d->rightLayout = new TQHBoxLayout( lay, 5 ); + d->topLevelLayout->setStretchFactor( d->mcView, 1 ); + d->topLevelLayout->setStretchFactor( files, 1 ); + + updateGeometries(); + + if ( d->goBack ) { + setTabOrder( d->paths, d->goBack ); + setTabOrder( d->goBack, d->cdToParent ); + } else { + setTabOrder( d->paths, d->cdToParent ); + } + setTabOrder( d->cdToParent, d->newFolder ); + setTabOrder( d->newFolder, d->mcView ); + setTabOrder( d->mcView, d->detailView ); + setTabOrder( d->detailView, d->moreFiles ); + setTabOrder( d->moreFiles, files ); + setTabOrder( files, nameEdit ); + setTabOrder( nameEdit, d->types ); + setTabOrder( d->types, okB ); + setTabOrder( okB, cancelB ); + + d->rw = tr( "Read-write" ); + d->ro = tr( "Read-only" ); + d->wo = tr( "Write-only" ); + d->inaccessible = tr( "Inaccessible" ); + + d->symLinkToFile = tr( "Symlink to File" ); + d->symLinkToDir = tr( "Symlink to Directory" ); + d->symLinkToSpecial = tr( "Symlink to Special" ); + d->file = tr( "File" ); + d->dir = tr( "Dir" ); + d->special = tr( "Special" ); + + if ( lastWidth == 0 ) { + TQRect screen = TQApplication::desktop()->screenGeometry( pos() ); + if ( screen.width() < 1024 || screen.height() < 768 ) { + resize( TQMIN(screen.width(), 420), TQMIN(screen.height(), 236) ); + } else { + TQSize s = files->sizeHint(); + s = TQSize( s.width() + 300, s.height() + 82 ); + + if ( s.width() * 3 > screen.width() * 2 ) + s.setWidth( screen.width() * 2 / 3 ); + + if ( s.height() * 3 > screen.height() * 2 ) + s.setHeight( screen.height() * 2 / 3 ); + else if ( s.height() * 3 < screen.height() ) + s.setHeight( screen.height() / 3 ); + + resize( s ); + } + updateLastSize(this); + } else { + resize( lastWidth, lastHeight ); + } + + if ( detailViewMode ) { + d->stack->raiseWidget( files ); + d->mcView->setOn( FALSE ); + d->detailView->setOn( TRUE ); + } + + d->preview->hide(); + nameEdit->setFocus(); + + connect( nameEdit, SIGNAL( returnPressed() ), + this, SLOT( fileNameEditReturnPressed() ) ); +} + +/*! + \internal +*/ + +void TQFileDialog::fileNameEditReturnPressed() +{ + d->oldUrl = d->url; + if ( !isDirectoryMode( d->mode ) ) { + okClicked(); + } else { + d->currentFileName = TQString::null; + if ( nameEdit->text().isEmpty() ) { + emit fileSelected( selectedFile() ); + accept(); + } else { + TQUrlInfo f; + TQFileDialogPrivate::File * c + = (TQFileDialogPrivate::File *)files->currentItem(); + if ( c && files->isSelected(c) ) + f = c->info; + else + f = TQUrlInfo( d->url, nameEdit->text() ); + if ( f.isDir() ) { + setUrl( TQUrlOperator( d->url, + TQFileDialogPrivate::encodeFileName(nameEdit->text() + "/" ) ) ); + d->checkForFilter = TRUE; + trySetSelection( TRUE, d->url, TRUE ); + d->checkForFilter = FALSE; + } + } + nameEdit->setText( TQString::null ); + } +} + +/*! + \internal + Update the info and content preview widgets to display \a u. +*/ + +void TQFileDialog::updatePreviews( const TQUrl &u ) +{ + if ( d->infoPreviewer ) + d->infoPreviewer->previewUrl( u ); + if ( d->contentsPreviewer ) + d->contentsPreviewer->previewUrl( u ); +} + +/*! + \internal + Changes the preview mode to the mode specified at \a id. +*/ + +void TQFileDialog::changeMode( int id ) +{ + if ( !d->infoPreview && !d->contentsPreview ) + return; + + TQButton *btn = (TQButton*)d->modeButtons->find( id ); + if ( !btn ) + return; + + if ( btn == d->previewContents && !d->contentsPreview ) + return; + if ( btn == d->previewInfo && !d->infoPreview ) + return; + + if ( btn != d->previewContents && btn != d->previewInfo ) { + d->preview->hide(); + } else { + if ( files->currentItem() ) + updatePreviews( TQUrl( d->url, files->currentItem()->text( 0 ) ) ); + if ( btn == d->previewInfo ) + d->preview->raiseWidget( d->infoPreviewWidget ); + else + d->preview->raiseWidget( d->contentsPreviewWidget ); + d->preview->show(); + } +} + +/*! + Destroys the file dialog. +*/ + +TQFileDialog::~TQFileDialog() +{ + // since clear might call setContentsPos which would emit + // a signal and thus cause a recompute of sizes... + files->blockSignals( TRUE ); + d->moreFiles->blockSignals( TRUE ); + files->clear(); + d->moreFiles->clear(); + d->moreFiles->blockSignals( FALSE ); + files->blockSignals( FALSE ); + +#ifndef QT_NO_CURSOR + if ( d->cursorOverride ) + TQApplication::restoreOverrideCursor(); +#endif + + delete d; + d = 0; +} + + +/*! + \property TQFileDialog::selectedFile + + \brief the name of the selected file + + If a file was selected selectedFile contains the file's name including + its absolute path; otherwise selectedFile is empty. + + \sa TQString::isEmpty(), selectedFiles, selectedFilter +*/ + +TQString TQFileDialog::selectedFile() const +{ + TQString s = d->currentFileName; + // remove the protocol because we do not want to encode it... + TQString prot = TQUrl( s ).protocol(); + if ( !prot.isEmpty() ) { + prot += ":"; + s.remove( 0, prot.length() ); + } + TQUrl u( prot + TQFileDialogPrivate::encodeFileName( s ) ); + if ( u.isLocalFile() ) { + TQString s = u.toString(); + if ( s.left( 5 ) == "file:" ) + s.remove( (uint)0, 5 ); + return s; + } + return d->currentFileName; +} + +/*! + \property TQFileDialog::selectedFilter + + \brief the filter which the user has selected in the file dialog + + \sa filterSelected(), selectedFiles, selectedFile +*/ + +TQString TQFileDialog::selectedFilter() const +{ + return d->types->currentText(); +} + +/*! \overload + + Sets the current filter selected in the file dialog to the + \a{n}-th filter in the filter list. + + \sa filterSelected(), selectedFilter(), selectedFiles(), selectedFile() +*/ + +void TQFileDialog::setSelectedFilter( int n ) +{ + d->types->setCurrentItem( n ); + TQString f = d->types->currentText(); + TQRegExp r( TQString::fromLatin1(qt_file_dialog_filter_reg_exp) ); + int index = r.search( f ); + if ( index >= 0 ) + f = r.cap( 2 ); + d->url.setNameFilter( f ); + rereadDir(); +} + +/*! + Sets the current filter selected in the file dialog to the first + one that contains the text \a mask. +*/ + +void TQFileDialog::setSelectedFilter( const TQString& mask ) +{ + int n; + + for ( n = 0; n < d->types->count(); n++ ) { + if ( d->types->text( n ).contains( mask, FALSE ) ) { + d->types->setCurrentItem( n ); + TQString f = mask; + TQRegExp r( TQString::fromLatin1(qt_file_dialog_filter_reg_exp) ); + int index = r.search( f ); + if ( index >= 0 ) + f = r.cap( 2 ); + d->url.setNameFilter( f ); + rereadDir(); + return; + } + } +} + +/*! + \property TQFileDialog::selectedFiles + + \brief the list of selected files + + If one or more files are selected, selectedFiles contains their + names including their absolute paths. If no files are selected or + the mode isn't ExistingFiles selectedFiles is an empty list. + + It is more convenient to use selectedFile() if the mode is + \c ExistingFile, \c Directory or \c DirectoryOnly. + + Note that if you want to iterate over the list, you should + iterate over a copy, e.g. + \code + TQStringList list = myFileDialog.selectedFiles(); + TQStringList::Iterator it = list.begin(); + while( it != list.end() ) { + myProcessing( *it ); + ++it; + } + \endcode + + \sa selectedFile, selectedFilter, TQValueList::empty() +*/ + +TQStringList TQFileDialog::selectedFiles() const +{ + TQStringList lst; + + if ( mode() == ExistingFiles ) { + TQStringList selectedLst; + TQString selectedFiles = nameEdit->text(); + if (selectedFiles.findRev('\"') == -1) { + //probably because Enter was pressed on the nameEdit, so we have one file + //not in "" but raw + selectedLst.append(selectedFiles); + } else { + selectedFiles.truncate( selectedFiles.findRev( '\"' ) ); + selectedLst = selectedLst.split( TQString("\" "), selectedFiles ); + } + for ( TQStringList::Iterator it = selectedLst.begin(); it != selectedLst.end(); ++it ) { + TQUrl u; + if ( (*it)[0] == '\"' ) { + u = TQUrl( d->url, TQFileDialogPrivate::encodeFileName( (*it).mid(1) ) ); + } else { + u = TQUrl( d->url, TQFileDialogPrivate::encodeFileName( (*it) ) ); + } + if ( u.isLocalFile() ) { + TQString s = u.toString(); + if ( s.left( 5 ) == "file:" ) + s.remove( (uint)0, 5 ); + lst << s; + } else { + lst << u.toString(); + } + } + } + + return lst; +} + +/*! + Sets the default selection to \a filename. If \a filename is + absolute, setDir() is also called to set the file dialog's working + directory to the filename's directory. + + \omit + Only for external use. Not useful inside TQFileDialog. + \endomit +*/ + +void TQFileDialog::setSelection( const TQString & filename ) +{ + d->oldUrl = d->url; + TQString nf = d->url.nameFilter(); + if ( TQUrl::isRelativeUrl( filename ) ) + d->url = TQUrlOperator( d->url, TQFileDialogPrivate::encodeFileName( filename ) ); + else + d->url = TQUrlOperator( filename ); + d->url.setNameFilter( nf ); + d->checkForFilter = TRUE; + bool isDirOk; + bool isDir = d->url.isDir( &isDirOk ); + if ( !isDirOk ) + isDir = d->url.path().right( 1 ) == "/"; + if ( !isDir ) { + TQUrlOperator u( d->url ); + d->url.setPath( d->url.dirPath() ); + trySetSelection( FALSE, u, TRUE ); + d->ignoreNextRefresh = TRUE; + nameEdit->selectAll(); + rereadDir(); + emit dirEntered( d->url.dirPath() ); + } else { + if ( !d->url.path().isEmpty() && + d->url.path().right( 1 ) != "/" ) { + TQString p = d->url.path(); + p += "/"; + d->url.setPath( p ); + } + trySetSelection( TRUE, d->url, FALSE ); + rereadDir(); + emit dirEntered( d->url.dirPath() ); + nameEdit->setText( TQString::fromLatin1("") ); + } + d->checkForFilter = FALSE; +} + +/*! + \property TQFileDialog::dirPath + + \brief the file dialog's working directory + + \sa dir(), setDir() +*/ + +TQString TQFileDialog::dirPath() const +{ + return d->url.dirPath(); +} + + +/*! + + Sets the filter used in the file dialog to \a newFilter. + + If \a newFilter contains a pair of parentheses containing one or more + of <em><b>anything*something</b></em> separated by spaces or by + semi-colons then only the text contained in the parentheses is used as + the filter. This means that these calls are all equivalent: + + \code + fd->setFilter( "All C++ files (*.cpp *.cc *.C *.cxx *.c++)" ); + fd->setFilter( "*.cpp *.cc *.C *.cxx *.c++" ); + fd->setFilter( "All C++ files (*.cpp;*.cc;*.C;*.cxx;*.c++)" ); + fd->setFilter( "*.cpp;*.cc;*.C;*.cxx;*.c++" ); + \endcode + + \sa setFilters() +*/ + +void TQFileDialog::setFilter( const TQString & newFilter ) +{ + if ( newFilter.isEmpty() ) + return; + TQString f = newFilter; + TQRegExp r( TQString::fromLatin1(qt_file_dialog_filter_reg_exp) ); + int index = r.search( f ); + if ( index >= 0 ) + f = r.cap( 2 ); + d->url.setNameFilter( f ); + if ( d->types->count() == 1 ) { + d->types->clear(); + d->types->insertItem( newFilter ); + } else { + for ( int i = 0; i < d->types->count(); ++i ) { + if ( d->types->text( i ).left( newFilter.length() ) == newFilter || + d->types->text( i ).left( f.length() ) == f ) { + d->types->setCurrentItem( i ); + break; + } + } + } + rereadDir(); +} + + +/*! \overload + Sets the file dialog's working directory to \a pathstr. + + \sa dir() +*/ + +void TQFileDialog::setDir( const TQString & pathstr ) +{ + TQString dr = pathstr; + if ( dr.isEmpty() ) + return; + +#if defined(Q_OS_UNIX) + if ( dr.length() && dr[0] == '~' ) { + int i = 0; + while( i < (int)dr.length() && dr[i] != '/' ) + i++; + TQCString user; + if ( i == 1 ) { +#if defined(QT_THREAD_SUPPORT) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) + +# ifndef _POSIX_LOGIN_NAME_MAX +# define _POSIX_LOGIN_NAME_MAX 9 +# endif + + char name[_POSIX_LOGIN_NAME_MAX]; + if ( ::getlogin_r( name, _POSIX_LOGIN_NAME_MAX ) == 0 ) + user = name; + else +#else + user = ::getlogin(); + if ( !user ) +#endif + user = getenv( "LOGNAME" ); + } else + user = dr.mid( 1, i-1 ).local8Bit(); + dr = dr.mid( i, dr.length() ); + struct passwd *pw; +#if defined(QT_THREAD_SUPPORT) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_FREEBSD) && !defined(Q_OS_OPENBSD) + struct passwd mt_pw; + char buffer[2048]; + if ( ::getpwnam_r( user, &mt_pw, buffer, 2048, &pw ) == 0 && pw == &mt_pw ) +#else + pw = ::getpwnam( user ); + if ( pw ) +#endif + dr.prepend( TQString::fromLocal8Bit(pw->pw_dir) ); + } +#endif + + setUrl( dr ); +} + +/*! + Returns the current directory shown in the file dialog. + + The ownership of the TQDir pointer is transferred to the caller, so + it must be deleted by the caller when no longer retquired. + + \sa setDir() +*/ + +const TQDir *TQFileDialog::dir() const +{ + if ( d->url.isLocalFile() ) + return new TQDir( d->url.path() ); + else + return 0; +} + +/*! + Sets the file dialog's working directory to \a dir. + \sa dir() +*/ + +void TQFileDialog::setDir( const TQDir &dir ) +{ + d->oldUrl = d->url; + TQString nf( d->url.nameFilter() ); + d->url = dir.canonicalPath(); + d->url.setNameFilter( nf ); + TQUrlInfo i( d->url, nameEdit->text() ); + d->checkForFilter = TRUE; + trySetSelection( i.isDir(), TQUrlOperator( d->url, TQFileDialogPrivate::encodeFileName(nameEdit->text() ) ), FALSE ); + d->checkForFilter = FALSE; + rereadDir(); + emit dirEntered( d->url.path() ); +} + +/*! + Sets the file dialog's working directory to the directory specified at \a url. + + \sa url() +*/ + +void TQFileDialog::setUrl( const TQUrlOperator &url ) +{ + d->oldUrl = d->url; + TQString nf = d->url.nameFilter(); + + TQString operatorPath = url.toString( FALSE, FALSE ); + if ( TQUrl::isRelativeUrl( operatorPath ) ) { + d->url = TQUrl( d->url, operatorPath ); + } else { + d->url = url; + } + d->url.setNameFilter( nf ); + + d->checkForFilter = TRUE; + if ( !d->url.isDir() ) { + TQUrlOperator u = d->url; + d->url.setPath( d->url.dirPath() ); + trySetSelection( FALSE, u, FALSE ); + rereadDir(); + emit dirEntered( d->url.dirPath() ); + TQString fn = u.fileName(); + nameEdit->setText( fn ); + } else { + trySetSelection( TRUE, d->url, FALSE ); + rereadDir(); + emit dirEntered( d->url.dirPath() ); + } + d->checkForFilter = FALSE; +} + +/*! + \property TQFileDialog::showHiddenFiles + + \brief whether hidden files are shown in the file dialog + + The default is FALSE, i.e. don't show hidden files. +*/ + +void TQFileDialog::setShowHiddenFiles( bool s ) +{ + if ( s == bShowHiddenFiles ) + return; + + bShowHiddenFiles = s; + rereadDir(); +} + +bool TQFileDialog::showHiddenFiles() const +{ + return bShowHiddenFiles; +} + +/*! + Rereads the current directory shown in the file dialog. + + The only time you will need to call this function is if the contents of + the directory change and you wish to refresh the file dialog to reflect + the change. + + \sa resortDir() +*/ + +void TQFileDialog::rereadDir() +{ +#ifndef QT_NO_CURSOR + if ( !d->cursorOverride ) { + TQApplication::setOverrideCursor( TQCursor( TQt::WaitCursor ) ); + d->cursorOverride = TRUE; + } +#endif + d->pendingItems.clear(); + if ( d->mimeTypeTimer->isActive() ) + d->mimeTypeTimer->stop(); + d->currListChildren = d->url.listChildren(); +#ifndef QT_NO_CURSOR + if ( d->cursorOverride ) { + TQApplication::restoreOverrideCursor(); + d->cursorOverride = FALSE; + } +#endif +} + + +/*! + \fn void TQFileDialog::fileHighlighted( const TQString& ) + + This signal is emitted when the user highlights a file, i.e. makes + it the current file. + + \sa fileSelected(), filesSelected() +*/ + +/*! + \fn void TQFileDialog::fileSelected( const TQString& ) + + This signal is emitted when the user selects a file. + + \sa filesSelected(), fileHighlighted(), selectedFile() +*/ + +/*! + \fn void TQFileDialog::filesSelected( const TQStringList& ) + + This signal is emitted when the user selects one or more files in \e + ExistingFiles mode. + + \sa fileSelected(), fileHighlighted(), selectedFiles() +*/ + +/*! + \fn void TQFileDialog::dirEntered( const TQString& ) + + This signal is emitted when the user enters a directory. + + \sa dir() +*/ + +/*! + \fn void TQFileDialog::filterSelected( const TQString& ) + + This signal is emitted when the user selects a filter. + + \sa selectedFilter() +*/ + +extern bool qt_resolve_symlinks; // defined in qapplication.cpp +bool Q_EXPORT qt_use_native_dialogs = TRUE; + +/*! + This is a convenience static function that returns an existing file + selected by the user. If the user pressed Cancel, it returns a null + string. + + \code + TQString s = TQFileDialog::getOpenFileName( + "/home", + "Images (*.png *.xpm *.jpg)", + this, + "open file dialog", + "Choose a file to open" ); + \endcode + + The function creates a modal file dialog called \a name, with + parent, \a parent. If a parent is not 0, the dialog will be shown + centered over the parent. + + The file dialog's working directory will be set to \a startWith. If \a + startWith includes a file name, the file will be selected. The filter + is set to \a filter so that only those files which match the filter + are shown. The filter selected is set to \a selectedFilter. The parameters + \a startWith, \a selectedFilter and \a filter may be TQString::null. + + The dialog's caption is set to \a caption. If \a caption is not + specified then a default caption will be used. + + Under Windows and Mac OS X, this static function will use the native + file dialog and not a TQFileDialog, unless the style of the application + is set to something other than the native style (Note that on Windows the + dialog will spin a blocking modal event loop that will not dispatch any + TQTimers and if parent is not 0 then it will position the dialog just under + the parent's titlebar). + + Under Unix/X11, the normal behavior of the file dialog is to resolve + and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp, + the file dialog will change to /var/tmp after entering /usr/tmp. + If \a resolveSymlinks is FALSE, the file dialog will treat + symlinks as regular directories. + + \sa getOpenFileNames(), getSaveFileName(), getExistingDirectory() +*/ + +TQString TQFileDialog::getOpenFileName( const TQString & startWith, + const TQString& filter, + TQWidget *parent, const char* name, + const TQString& caption, + TQString *selectedFilter, + bool resolveSymlinks ) +{ + bool save_qt_resolve_symlinks = qt_resolve_symlinks; + qt_resolve_symlinks = resolveSymlinks; + + TQStringList filters; + if ( !filter.isEmpty() ) + filters = makeFiltersList( filter ); + + makeVariables(); + TQString initialSelection; + //### Problem with the logic here: If a startWith is given and a file + // with that name exists in D->URL, the box will be opened at D->URL instead of + // the last directory used ('workingDirectory'). + // + // hm... isn't that problem exactly the documented behaviour? the + // documented behaviour sounds meaningful. + if ( !startWith.isEmpty() ) { + TQUrlOperator u( TQFileDialogPrivate::encodeFileName( startWith ) ); + if ( u.isLocalFile() && TQFileInfo( u.path() ).isDir() ) { + *workingDirectory = startWith; + } else { + if ( u.isLocalFile() ) { + TQFileInfo fi( u.dirPath() ); + if ( fi.exists() ) { + *workingDirectory = u.dirPath(); + initialSelection = u.fileName(); + } + } else { + *workingDirectory = u.toString(); + initialSelection = TQString::null;//u.fileName(); + } + } + } + + if ( workingDirectory->isNull() ) + *workingDirectory = ::toRootIfNotExists( TQDir::currentDirPath() ); + +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::getOpenFileNames( filter, workingDirectory, parent, name, + caption, selectedFilter, false ).first(); +#elif defined(Q_WS_WIN) + if ( qt_use_native_dialogs && qApp->style().styleHint( TQStyle::SH_GUIStyle ) == WindowsStyle ) + return winGetOpenFileName( initialSelection, filter, workingDirectory, + parent, name, caption, selectedFilter ); +#elif defined(Q_WS_MAC) + if (qt_use_native_dialogs && (qApp->style().inherits(TQMAC_DEFAULT_STYLE) + || qApp->style().inherits("TQMacStyle"))) + return qt_mac_precomposeFileName(macGetOpenFileNames(filter, + startWith.isEmpty() ? 0 : workingDirectory, + parent, name, caption, selectedFilter, FALSE).first()); +#endif + + TQFileDialog *dlg = new TQFileDialog( *workingDirectory, TQString::null, parent, name ? name : "qt_filedlg_gofn", TRUE ); + + Q_CHECK_PTR( dlg ); +#ifndef QT_NO_WIDGET_TOPEXTRA + if ( !caption.isNull() ) + dlg->setCaption( caption ); + else + dlg->setCaption( TQFileDialog::tr( "Open" ) ); +#endif + + dlg->setFilters( filters ); + if ( selectedFilter ) + dlg->setFilter( *selectedFilter ); + dlg->setMode( TQFileDialog::ExistingFile ); + TQString result; + if ( !initialSelection.isEmpty() ) + dlg->setSelection( initialSelection ); + if ( dlg->exec() == TQDialog::Accepted ) { + result = dlg->selectedFile(); + *workingDirectory = dlg->d->url; + if ( selectedFilter ) + *selectedFilter = dlg->selectedFilter(); + } + delete dlg; + + qt_resolve_symlinks = save_qt_resolve_symlinks; + + return result; +} + +/*! + This is a convenience static function that will return a file name + selected by the user. The file does not have to exist. + + It creates a modal file dialog called \a name, with parent, \a parent. + If a parent is not 0, the dialog will be shown centered over the + parent. + + \code + TQString s = TQFileDialog::getSaveFileName( + "/home", + "Images (*.png *.xpm *.jpg)", + this, + "save file dialog", + "Choose a filename to save under" ); + \endcode + + The file dialog's working directory will be set to \a startWith. If \a + startWith includes a file name, the file will be selected. The filter + is set to \a filter so that only those files which match the filter + are shown. The filter selected is set to \a selectedFilter. The parameters + \a startWith, \a selectedFilter and \a filter may be TQString::null. + + The dialog's caption is set to \a caption. If \a caption is not + specified then a default caption will be used. + + Under Windows and Mac OS X, this static function will use the native + file dialog and not a TQFileDialog, unless the style of the application + is set to something other than the native style. (Note that on Windows the + dialog will spin a blocking modal event loop that will not dispatch any + TQTimers and if parent is not 0 then it will position the dialog just under + the parent's titlebar. + + Under Unix/X11, the normal behavior of the file dialog is to resolve + and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp, + the file dialog will change to /var/tmp after entering /usr/tmp. + If \a resolveSymlinks is FALSE, the file dialog will treat + symlinks as regular directories. + + \sa getOpenFileName(), getOpenFileNames(), getExistingDirectory() +*/ + +TQString TQFileDialog::getSaveFileName( const TQString & startWith, + const TQString& filter, + TQWidget *parent, const char* name, + const TQString& caption, + TQString *selectedFilter, + bool resolveSymlinks) +{ + bool save_qt_resolve_symlinks = qt_resolve_symlinks; + qt_resolve_symlinks = resolveSymlinks; + + TQStringList filters; + if ( !filter.isEmpty() ) + filters = makeFiltersList( filter ); + + makeVariables(); + TQString initialSelection; + if ( !startWith.isEmpty() ) { + TQUrlOperator u( TQFileDialogPrivate::encodeFileName( startWith ) ); + if ( u.isLocalFile() && TQFileInfo( u.path() ).isDir() ) { + *workingDirectory = startWith; + } else { + if ( u.isLocalFile() ) { + TQFileInfo fi( u.dirPath() ); + if ( fi.exists() ) { + *workingDirectory = u.dirPath(); + initialSelection = u.fileName(); + } + } else { + *workingDirectory = u.toString(); + initialSelection = TQString::null;//u.fileName(); + } + } + } + + if ( workingDirectory->isNull() ) + *workingDirectory = ::toRootIfNotExists( TQDir::currentDirPath() ); + +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::getSaveFileName( initialSelection, filter, workingDirectory, + parent, name, caption, selectedFilter ); +#elif defined(Q_WS_WIN) + if ( qt_use_native_dialogs && qApp->style().styleHint( TQStyle::SH_GUIStyle ) == WindowsStyle ) + return winGetSaveFileName( initialSelection, filter, workingDirectory, + parent, name, caption, selectedFilter ); +#elif defined(Q_WS_MAC) + if (qt_use_native_dialogs && (qApp->style().inherits(TQMAC_DEFAULT_STYLE) + || qApp->style().inherits("TQMacStyle"))) + return qt_mac_precomposeFileName(macGetSaveFileName(initialSelection, filter, + startWith.isEmpty() ? 0 : workingDirectory, parent, name, + caption, selectedFilter)); +#endif + + TQFileDialog *dlg = new TQFileDialog( *workingDirectory, TQString::null, parent, name ? name : "qt_filedlg_gsfn", TRUE ); + + Q_CHECK_PTR( dlg ); +#ifndef QT_NO_WIDGET_TOPEXTRA + if ( !caption.isNull() ) + dlg->setCaption( caption ); + else + dlg->setCaption( TQFileDialog::tr( "Save As" ) ); +#endif + + TQString result; + dlg->setFilters( filters ); + if ( selectedFilter ) + dlg->setFilter( *selectedFilter ); + dlg->setMode( TQFileDialog::AnyFile ); + if ( !initialSelection.isEmpty() ) + dlg->setSelection( initialSelection ); + if ( dlg->exec() == TQDialog::Accepted ) { + result = dlg->selectedFile(); + *workingDirectory = dlg->d->url; + if ( selectedFilter ) + *selectedFilter = dlg->selectedFilter(); + } + delete dlg; + + qt_resolve_symlinks = save_qt_resolve_symlinks; + + return result; +} + +/*! + \internal + Activated when the "OK" button is clicked. +*/ + +void TQFileDialog::okClicked() +{ + TQString fn( nameEdit->text() ); + +#if defined(Q_WS_WIN) + TQFileInfo fi( d->url.path() + fn ); + if ( fi.isSymLink() ) { + nameEdit->setText( fi.readLink() ); + } +#endif + + if ( fn.contains("*") ) { + addFilter( fn ); + nameEdit->blockSignals( TRUE ); + nameEdit->setText( TQString::fromLatin1("") ); + nameEdit->blockSignals( FALSE ); + return; + } + + *workingDirectory = d->url; + detailViewMode = files->isVisible(); + updateLastSize(this); + + if ( isDirectoryMode( d->mode ) ) { + TQUrlInfo f( d->url, nameEdit->text() ); + if ( f.isDir() ) { + d->currentFileName = d->url; + if ( d->currentFileName.right(1) != "/" ) + d->currentFileName += '/'; + if ( f.name() != "." ) + d->currentFileName += f.name(); + accept(); + return; + } + // Since it's not a directory and we clicked ok, we + // don't really want to do anything else + return; + } + + // if we're in multi-selection mode and something is selected, + // accept it and be done. + if ( mode() == ExistingFiles ) { + if ( ! nameEdit->text().isEmpty() ) { + TQStringList sf = selectedFiles(); + bool isdir = FALSE; + if ( sf.count() == 1 ) { + TQUrlOperator u( d->url, sf[0] ); + bool ok; + isdir = u.isDir(&ok) && ok; + } + if ( !isdir ) { + emit filesSelected( sf ); + accept(); + return; + } + } + } + + if ( mode() == AnyFile ) { + TQUrlOperator u( d->url, TQFileDialogPrivate::encodeFileName(nameEdit->text()) ); + if ( !u.isDir() ) { + d->currentFileName = u; + emit fileSelected( selectedFile() ); + accept(); + return; + } + } + + if ( mode() == ExistingFile ) { + if ( !TQFileDialogPrivate::fileExists( d->url, nameEdit->text() ) ) + return; + } + + // If selection is valid, return it, else try + // using selection as a directory to change to. + if ( !d->currentFileName.isNull() && !d->currentFileName.contains( "*" ) ) { + emit fileSelected( selectedFile() ); + accept(); + } else { + TQUrlInfo f; + TQFileDialogPrivate::File * c + = (TQFileDialogPrivate::File *)files->currentItem(); + TQFileDialogPrivate::MCItem * m + = (TQFileDialogPrivate::MCItem *)d->moreFiles->item( d->moreFiles->currentItem() ); + if ( c && files->isVisible() && files->hasFocus() || + m && d->moreFiles->isVisible() && d->moreFiles->hasFocus() ) { + if ( c && files->isVisible() ) + f = c->info; + else + f = ( (TQFileDialogPrivate::File*)m->i )->info; + } else { + f = TQUrlInfo( d->url, nameEdit->text() ); + } + if ( f.isDir() ) { + setUrl( TQUrlOperator( d->url, TQFileDialogPrivate::encodeFileName(f.name() + "/" ) ) ); + d->checkForFilter = TRUE; + trySetSelection( TRUE, d->url, TRUE ); + d->checkForFilter = FALSE; + } else { + if ( !nameEdit->text().contains( "/" ) && + !nameEdit->text().contains( "\\" ) +#if defined(Q_OS_WIN32) + && nameEdit->text()[ 1 ] != ':' +#endif + ) + addFilter( nameEdit->text() ); + else if ( nameEdit->text()[ 0 ] == '/' || + nameEdit->text()[ 0 ] == '\\' +#if defined(Q_OS_WIN32) + || nameEdit->text()[ 1 ] == ':' +#endif + ) + setDir( nameEdit->text() ); + else if ( nameEdit->text().left( 3 ) == "../" || nameEdit->text().left( 3 ) == "..\\" ) + setDir( TQUrl( d->url.toString(), TQFileDialogPrivate::encodeFileName(nameEdit->text() ) ).toString() ); + } + nameEdit->setText( "" ); + } +} + +/*! + \internal + Activated when the "Filter" button is clicked. +*/ + +void TQFileDialog::filterClicked() +{ + // unused +} + +/*! + \internal + Activated when the "Cancel" button is clicked. +*/ + +void TQFileDialog::cancelClicked() +{ + *workingDirectory = d->url; + detailViewMode = files->isVisible(); + updateLastSize(this); + reject(); +} + + +/*!\reimp +*/ + +void TQFileDialog::resizeEvent( TQResizeEvent * e ) +{ + TQDialog::resizeEvent( e ); + updateGeometries(); +} + +/* + \internal + The only correct way to try to set currentFileName +*/ +bool TQFileDialog::trySetSelection( bool isDir, const TQUrlOperator &u, bool updatelined ) +{ + if ( !isDir && !u.path().isEmpty() && u.path().right( 1 ) == "/" ) + isDir = TRUE; + if ( u.fileName().contains( "*") && d->checkForFilter ) { + TQString fn( u.fileName() ); + if ( fn.contains( "*" ) ) { + addFilter( fn ); + d->currentFileName = TQString::null; + d->url.setFileName( TQString::null ); + nameEdit->setText( TQString::fromLatin1("") ); + return FALSE; + } + } + + if ( d->preview && d->preview->isVisible() ) + updatePreviews( u ); + + TQString old = d->currentFileName; + + if ( isDirectoryMode( mode() ) ) { + if ( isDir ) + d->currentFileName = u; + else + d->currentFileName = TQString::null; + } else if ( !isDir && mode() == ExistingFiles ) { + d->currentFileName = u; + } else if ( !isDir || ( mode() == AnyFile && !isDir ) ) { + d->currentFileName = u; + } else { + d->currentFileName = TQString::null; + } + if ( updatelined && !d->currentFileName.isEmpty() ) { + // If the selection is valid, or if its a directory, allow OK. + if ( !d->currentFileName.isNull() || isDir ) { + if ( u.fileName() != ".." ) { + TQString fn = u.fileName(); + nameEdit->setText( fn ); + } else { + nameEdit->setText(""); + } + } else + nameEdit->setText( TQString::fromLatin1("") ); + } + + if ( !d->currentFileName.isNull() || isDir ) { + okB->setEnabled( TRUE ); + } else if ( !isDirectoryMode( d->mode ) ) { + okB->setEnabled( FALSE ); + } + + if ( d->currentFileName.length() && old != d->currentFileName ) + emit fileHighlighted( selectedFile() ); + + return !d->currentFileName.isNull(); +} + + +/*! Make sure the minimum and maximum sizes of everything are sane. +*/ + +void TQFileDialog::updateGeometries() +{ + if ( !d || !d->geometryDirty ) + return; + + d->geometryDirty = FALSE; + + TQSize r, t; + + // we really should have a TQSize::unite() +#define RM r.setWidth( TQMAX(r.width(),t.width()) ); \ +r.setHeight( TQMAX(r.height(),t.height()) ) + + // labels first + r = d->pathL->sizeHint(); + t = d->fileL->sizeHint(); + RM; + t = d->typeL->sizeHint(); + RM; + d->pathL->setFixedSize( d->pathL->sizeHint() ); + d->fileL->setFixedSize( r ); + d->typeL->setFixedSize( r ); + + // single-line input areas + r = d->paths->sizeHint(); + t = nameEdit->sizeHint(); + RM; + t = d->types->sizeHint(); + RM; + r.setWidth( t.width() * 2 / 3 ); + t.setWidth( TQWIDGETSIZE_MAX ); + t.setHeight( r.height() ); + d->paths->setMinimumSize( r ); + d->paths->setMaximumSize( t ); + nameEdit->setMinimumSize( r ); + nameEdit->setMaximumSize( t ); + d->types->setMinimumSize( r ); + d->types->setMaximumSize( t ); + + // buttons on top row + r = TQSize( 0, d->paths->minimumSize().height() ); + t = TQSize( 21, 20 ); + RM; + if ( r.height()+1 > r.width() ) + r.setWidth( r.height()+1 ); + if ( d->goBack ) + d->goBack->setFixedSize( r ); + d->cdToParent->setFixedSize( r ); + d->newFolder->setFixedSize( r ); + d->mcView->setFixedSize( r ); + d->detailView->setFixedSize( r ); + + TQButton *b = 0; + if ( !d->toolButtons.isEmpty() ) { + for ( b = d->toolButtons.first(); b; b = d->toolButtons.next() ) + b->setFixedSize( b->sizeHint().width(), r.height() ); + } + + if ( d->infoPreview ) { + d->previewInfo->show(); + d->previewInfo->setFixedSize( r ); + } else { + d->previewInfo->hide(); + d->previewInfo->setFixedSize( TQSize( 0, 0 ) ); + } + + if ( d->contentsPreview ) { + d->previewContents->show(); + d->previewContents->setFixedSize( r ); + } else { + d->previewContents->hide(); + d->previewContents->setFixedSize( TQSize( 0, 0 ) ); + } + + // open/save, cancel + r = TQSize( 75, 20 ); + t = okB->sizeHint(); + RM; + t = cancelB->sizeHint(); + RM; + + okB->setFixedSize( r ); + cancelB->setFixedSize( r ); + + d->topLevelLayout->activate(); + +#undef RM +} + + +/*! Updates the file name edit box to \a newItem in the file dialog + when the cursor moves in the listview. +*/ + +void TQFileDialog::updateFileNameEdit( TQListViewItem * newItem ) +{ + if ( !newItem ) + return; + + if ( mode() == ExistingFiles ) { + detailViewSelectionChanged(); + TQUrl u( d->url, TQFileDialogPrivate::encodeFileName( ((TQFileDialogPrivate::File*)files->currentItem())->info.name() ) ); + TQFileInfo fi( u.toString( FALSE, FALSE ) ); + if ( !fi.isDir() ) + emit fileHighlighted( u.toString( FALSE, FALSE ) ); + } else if ( files->isSelected( newItem ) ) { + TQFileDialogPrivate::File * i = (TQFileDialogPrivate::File *)newItem; + if ( i && i->i && !i->i->isSelected() ) { + d->moreFiles->blockSignals( TRUE ); + d->moreFiles->setSelected( i->i, TRUE ); + d->moreFiles->blockSignals( FALSE ); + } + // Encode the filename in case it had any special characters in it + TQString encFile = TQFileDialogPrivate::encodeFileName( newItem->text( 0 ) ); + trySetSelection( i->info.isDir(), TQUrlOperator( d->url, encFile ), TRUE ); + } +} + +void TQFileDialog::detailViewSelectionChanged() +{ + if ( d->mode != ExistingFiles ) + return; + + nameEdit->clear(); + TQString str; + TQListViewItem * i = files->firstChild(); + d->moreFiles->blockSignals( TRUE ); + while( i ) { + if ( d->moreFiles && isVisible() ) { + TQFileDialogPrivate::File *f = (TQFileDialogPrivate::File *)i; + if ( f->i && f->i->isSelected() != i->isSelected() ) + d->moreFiles->setSelected( f->i, i->isSelected() ); + } + if ( i->isSelected() && !( (TQFileDialogPrivate::File *)i )->info.isDir() ) + str += TQString( "\"%1\" " ).arg( i->text( 0 ) ); + i = i->nextSibling(); + } + d->moreFiles->blockSignals( FALSE ); + nameEdit->setText( str ); + nameEdit->setCursorPosition( str.length() ); + okB->setEnabled( TRUE ); + if ( d->preview && d->preview->isVisible() && files->currentItem() ) { + TQUrl u = TQUrl( d->url, TQFileDialogPrivate::encodeFileName( ((TQFileDialogPrivate::File*)files->currentItem())->info.name() ) ); + updatePreviews( u ); + } +} + +void TQFileDialog::listBoxSelectionChanged() +{ + if ( d->mode != ExistingFiles ) + return; + + if ( d->ignoreNextRefresh ) { + d->ignoreNextRefresh = FALSE; + return; + } + + nameEdit->clear(); + TQString str; + TQListBoxItem * i = d->moreFiles->item( 0 ); + TQListBoxItem * j = 0; + int index = 0; + files->blockSignals( TRUE ); + while( i ) { + TQFileDialogPrivate::MCItem *mcitem = (TQFileDialogPrivate::MCItem *)i; + if ( files && isVisible() ) { + if ( mcitem->i->isSelected() != mcitem->isSelected() ) { + files->setSelected( mcitem->i, mcitem->isSelected() ); + + // What happens here is that we want to emit signal highlighted for + // newly added items. But TQListBox apparently emits selectionChanged even + // when a user clicks on the same item twice. So, basically emulate the behaivor + // we have in the "Details" view which only emits highlighted the first time we + // click on the item. Perhaps at some point we should have a call to + // updateFileNameEdit(TQListViewItem) which also emits fileHighlighted() for + // ExistingFiles. For better or for worse, this clones the behaivor of the + // "Details" view tquite well. + if ( mcitem->isSelected() && i != d->lastEFSelected ) { + TQUrl u( d->url, TQFileDialogPrivate::encodeFileName( ((TQFileDialogPrivate::File*)(mcitem)->i)->info.name()) ); + d->lastEFSelected = i; + emit fileHighlighted( u.toString(FALSE, FALSE) ); + } + } + } + if ( d->moreFiles->isSelected( i ) + && !( (TQFileDialogPrivate::File*)(mcitem)->i )->info.isDir() ) { + str += TQString( "\"%1\" " ).arg( i->text() ); + if ( j == 0 ) + j = i; + } + i = d->moreFiles->item( ++index ); + } + + files->blockSignals( FALSE ); + nameEdit->setText( str ); + nameEdit->setCursorPosition( str.length() ); + okB->setEnabled( TRUE ); + if ( d->preview && d->preview->isVisible() && j ) { + TQUrl u = TQUrl( d->url, + TQFileDialogPrivate::encodeFileName( ( (TQFileDialogPrivate::File*)( (TQFileDialogPrivate::MCItem*)j )->i )->info.name() ) ); + updatePreviews( u ); + } +} + +/*! \overload */ + +void TQFileDialog::updateFileNameEdit( TQListBoxItem * newItem ) +{ + if ( !newItem ) + return; + TQFileDialogPrivate::MCItem * i = (TQFileDialogPrivate::MCItem *)newItem; + if ( i->i ) { + i->i->listView()->setSelected( i->i, i->isSelected() ); + updateFileNameEdit( i->i ); + } +} + + +/*! Updates the dialog when the file name edit changes. */ + +void TQFileDialog::fileNameEditDone() +{ + TQUrlInfo f( d->url, nameEdit->text() ); + if ( mode() != TQFileDialog::ExistingFiles ) { + TQUrlOperator u( d->url, TQFileDialogPrivate::encodeFileName( nameEdit->text() ) ); + trySetSelection( f.isDir(), u, FALSE ); + if ( d->preview && d->preview->isVisible() ) + updatePreviews( u ); + } +} + + + +/*! This private slot reacts to double-clicks in the list view. The item that +was double-clicked is specified in \a newItem */ + +void TQFileDialog::selectDirectoryOrFile( TQListViewItem * newItem ) +{ + + *workingDirectory = d->url; + detailViewMode = files->isVisible(); + updateLastSize(this); + + if ( !newItem ) + return; + + if ( d->url.isLocalFile() ) { + TQFileInfo fi( d->url.path() + newItem->text(0) ); +#if defined(Q_WS_WIN) + if ( fi.isSymLink() ) { + nameEdit->setText( fi.readLink() ); + okClicked(); + return; + } +#endif + } + + TQFileDialogPrivate::File * i = (TQFileDialogPrivate::File *)newItem; + + TQString oldName = nameEdit->text(); + if ( i->info.isDir() ) { + setUrl( TQUrlOperator( d->url, TQFileDialogPrivate::encodeFileName( i->info.name() ) + "/" ) ); + if ( isDirectoryMode( mode() ) ) { + TQUrlInfo f ( d->url, TQString::fromLatin1( "." ) ); + trySetSelection( f.isDir(), d->url, TRUE ); + } + } else if ( newItem->isSelectable() && + trySetSelection( i->info.isDir(), TQUrlOperator( d->url, TQFileDialogPrivate::encodeFileName( i->info.name() ) ), TRUE ) ) { + if ( !isDirectoryMode( mode() ) ) { + if ( mode() == ExistingFile ) { + if ( TQFileDialogPrivate::fileExists( d->url, nameEdit->text() ) ) { + emit fileSelected( selectedFile() ); + accept(); + } + } else { + emit fileSelected( selectedFile() ); + accept(); + } + } + } else if ( isDirectoryMode( d->mode ) ) { + d->currentFileName = d->url; + accept(); + } + if ( !oldName.isEmpty() && !isDirectoryMode( mode() ) ) + nameEdit->setText( oldName ); +} + + +void TQFileDialog::selectDirectoryOrFile( TQListBoxItem * newItem ) +{ + if ( !newItem ) + return; + + TQFileDialogPrivate::MCItem * i = (TQFileDialogPrivate::MCItem *)newItem; + if ( i->i ) { + i->i->listView()->setSelected( i->i, i->isSelected() ); + selectDirectoryOrFile( i->i ); + } +} + + +void TQFileDialog::popupContextMenu( TQListViewItem *item, const TQPoint &p, + int ) +{ + if ( item ) { + files->setCurrentItem( item ); + files->setSelected( item, TRUE ); + } + + PopupAction action; + popupContextMenu( item ? item->text( 0 ) : TQString::null, TRUE, action, p ); + + if ( action == PA_Open ) + selectDirectoryOrFile( item ); + else if ( action == PA_Rename ) + files->startRename( FALSE ); + else if ( action == PA_Delete ) + deleteFile( item ? item->text( 0 ) : TQString::null ); + else if ( action == PA_Reload ) + rereadDir(); + else if ( action == PA_Hidden ) { + bShowHiddenFiles = !bShowHiddenFiles; + rereadDir(); + } else if ( action == PA_SortName ) { + sortFilesBy = (int)TQDir::Name; + sortAscending = TRUE; + resortDir(); + } else if ( action == PA_SortSize ) { + sortFilesBy = (int)TQDir::Size; + sortAscending = TRUE; + resortDir(); + } else if ( action == PA_SortDate ) { + sortFilesBy = (int)TQDir::Time; + sortAscending = TRUE; + resortDir(); + } else if ( action == PA_SortUnsorted ) { + sortFilesBy = (int)TQDir::Unsorted; + sortAscending = TRUE; + resortDir(); + } + +} + +void TQFileDialog::popupContextMenu( TQListBoxItem *item, const TQPoint & p ) +{ + PopupAction action; + popupContextMenu( item ? item->text() : TQString::null, FALSE, action, p ); + + if ( action == PA_Open ) + selectDirectoryOrFile( item ); + else if ( action == PA_Rename ) + d->moreFiles->startRename( FALSE ); + else if ( action == PA_Delete ) + deleteFile( item->text() ); + else if ( action == PA_Reload ) + rereadDir(); + else if ( action == PA_Hidden ) { + bShowHiddenFiles = !bShowHiddenFiles; + rereadDir(); + } else if ( action == PA_SortName ) { + sortFilesBy = (int)TQDir::Name; + sortAscending = TRUE; + resortDir(); + } else if ( action == PA_SortSize ) { + sortFilesBy = (int)TQDir::Size; + sortAscending = TRUE; + resortDir(); + } else if ( action == PA_SortDate ) { + sortFilesBy = (int)TQDir::Time; + sortAscending = TRUE; + resortDir(); + } else if ( action == PA_SortUnsorted ) { + sortFilesBy = (int)TQDir::Unsorted; + sortAscending = TRUE; + resortDir(); + } +} + +void TQFileDialog::popupContextMenu( const TQString &filename, bool, + PopupAction &action, const TQPoint &p ) +{ + action = PA_Cancel; + + bool glob = filename.isEmpty(); + + TQPopupMenu m( 0, "file dialog context menu" ); + m.setCheckable( TRUE ); + + if ( !glob ) { + TQString okt; + if ( TQUrlInfo( d->url, filename ).isDir() ) { + okt = tr( "&Open" ); + } else { + if ( mode() == AnyFile ) + okt = tr( "&Save" ); + else + okt = tr( "&Open" ); + } + int ok = m.insertItem( okt ); + + m.insertSeparator(); + int rename = m.insertItem( tr( "&Rename" ) ); + int del = m.insertItem( tr( "&Delete" ) ); + + if ( filename.isEmpty() || !TQUrlInfo( d->url, filename ).isWritable() || + filename == ".." ) { + if ( filename.isEmpty() || !TQUrlInfo( d->url, filename ).isReadable() ) + m.setItemEnabled( ok, FALSE ); + m.setItemEnabled( rename, FALSE ); + m.setItemEnabled( del, FALSE ); + } + + m.move( p ); + int res = m.exec(); + + if ( res == ok ) + action = PA_Open; + else if ( res == rename ) + action = PA_Rename; + else if ( res == del ) + action = PA_Delete; + } else { + int reload = m.insertItem( tr( "R&eload" ) ); + + TQPopupMenu m2( 0, "sort menu" ); + + int sname = m2.insertItem( tr( "Sort by &Name" ) ); + //int stype = m2.insertItem( tr( "Sort by &Type" ) ); + int ssize = m2.insertItem( tr( "Sort by &Size" ) ); + int sdate = m2.insertItem( tr( "Sort by &Date" ) ); + m2.insertSeparator(); + int sunsorted = m2.insertItem( tr( "&Unsorted" ) ); + + //m2.setItemEnabled( stype, FALSE ); + + if ( sortFilesBy == (int)TQDir::Name ) + m2.setItemChecked( sname, TRUE ); + else if ( sortFilesBy == (int)TQDir::Size ) + m2.setItemChecked( ssize, TRUE ); +// else if ( sortFilesBy == 0x16 ) +// m2.setItemChecked( stype, TRUE ); + else if ( sortFilesBy == (int)TQDir::Time ) + m2.setItemChecked( sdate, TRUE ); + else if ( sortFilesBy == (int)TQDir::Unsorted ) + m2.setItemChecked( sunsorted, TRUE ); + + m.insertItem( tr( "Sort" ), &m2 ); + + m.insertSeparator(); + + int hidden = m.insertItem( tr( "Show &hidden files" ) ); + m.setItemChecked( hidden, bShowHiddenFiles ); + + m.move( p ); + int res = m.exec(); + + if ( res == reload ) + action = PA_Reload; + else if ( res == hidden ) + action = PA_Hidden; + else if ( res == sname ) + action = PA_SortName; +// else if ( res == stype ) +// action = PA_SortType; + else if ( res == sdate ) + action = PA_SortDate; + else if ( res == ssize ) + action = PA_SortSize; + else if ( res == sunsorted ) + action = PA_SortUnsorted; + } + +} + +void TQFileDialog::deleteFile( const TQString &filename ) +{ + if ( filename.isEmpty() ) + return; + + TQUrlInfo fi( d->url, TQFileDialogPrivate::encodeFileName( filename ) ); + TQString t = tr( "the file" ); + if ( fi.isDir() ) + t = tr( "the directory" ); + if ( fi.isSymLink() ) + t = tr( "the symlink" ); + + if ( TQMessageBox::warning( this, + tr( "Delete %1" ).arg( t ), + tr( "<qt>Are you sure you wish to delete %1 \"%2\"?</qt>" ) + .arg( t ).arg(filename), + tr( "&Yes" ), tr( "&No" ), TQString::null, 1 ) == 0 ) + d->url.remove( TQFileDialogPrivate::encodeFileName( filename ) ); + +} + +void TQFileDialog::fileSelected( int ) +{ + // unused +} + +void TQFileDialog::fileHighlighted( int ) +{ + // unused +} + +void TQFileDialog::dirSelected( int ) +{ + // unused +} + +void TQFileDialog::pathSelected( int ) +{ + // unused +} + + +void TQFileDialog::cdUpClicked() +{ + TQString oldName = nameEdit->text(); + setUrl( TQUrlOperator( d->url, ".." ) ); + if ( !oldName.isEmpty() ) + nameEdit->setText( oldName ); +} + +void TQFileDialog::newFolderClicked() +{ + TQString foldername( tr( "New Folder 1" ) ); + int i = 0; + TQStringList lst; + TQListViewItemIterator it( files ); + for ( ; it.current(); ++it ) + if ( it.current()->text( 0 ).contains( tr( "New Folder" ) ) ) + lst.append( it.current()->text( 0 ) ); + + if ( !lst.count() == 0 ) + while ( lst.contains( foldername ) ) + foldername = tr( "New Folder %1" ).arg( ++i ); + + d->url.mkdir( foldername ); +} + +void TQFileDialog::createdDirectory( const TQUrlInfo &info, TQNetworkOperation * ) +{ + resortDir(); + if ( d->moreFiles->isVisible() ) { + for ( uint i = 0; i < d->moreFiles->count(); ++i ) { + if ( d->moreFiles->text( i ) == info.name() ) { + d->moreFiles->setCurrentItem( i ); + d->moreFiles->startRename( FALSE ); + break; + } + } + } else { + TQListViewItem *item = files->firstChild(); + while ( item ) { + if ( item->text( 0 ) == info.name() ) { + files->setSelected( item, TRUE ); + files->setCurrentItem( item ); + files->startRename( FALSE ); + break; + } + item = item->nextSibling(); + } + } +} + + +/*! + This is a convenience static function that will return an existing directory + selected by the user. + + \code + TQString s = TQFileDialog::getExistingDirectory( + "/home", + this, + "get existing directory", + "Choose a directory", + TRUE ); + \endcode + + This function creates a modal file dialog called \a name, with + parent, \a parent. If parent is not 0, the dialog will be shown + centered over the parent. + + The dialog's working directory is set to \a dir, and the caption is + set to \a caption. Either of these may be TQString::null in which case + the current directory and a default caption will be used respectively. + + Note on Windows that if \a dir is TQString::null then the dialog's working + directory will be set to the user's My Documents directory. + + If \a dirOnly is TRUE, then only directories will be shown in + the file dialog; otherwise both directories and files will be shown. + + Under Unix/X11, the normal behavior of the file dialog is to resolve + and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp, + the file dialog will change to /var/tmp after entering /usr/tmp. + If \a resolveSymlinks is FALSE, the file dialog will treat + symlinks as regular directories. + + Under Windows and Mac OS X, this static function will use the native + file dialog and not a TQFileDialog, unless the style of the application + is set to something other than the native style. (Note that on Windows the + dialog will spin a blocking modal event loop that will not dispatch any + TQTimers and if parent is not 0 then it will position the dialog just under + the parent's titlebar). + + \sa getOpenFileName(), getOpenFileNames(), getSaveFileName() +*/ + +TQString TQFileDialog::getExistingDirectory( const TQString & dir, + TQWidget *parent, + const char* name, + const TQString& caption, + bool dirOnly, + bool resolveSymlinks) +{ + bool save_qt_resolve_symlinks = qt_resolve_symlinks; + qt_resolve_symlinks = resolveSymlinks; + + makeVariables(); + TQString wd; + if ( workingDirectory ) + wd = *workingDirectory; + +#if defined(Q_WS_X11) + TQString initialDir; + if ( !dir.isEmpty() ) { + TQUrlOperator u( dir ); + if ( TQFileInfo( u.path() ).isDir() ) + initialDir = dir; + } else + initialDir = TQString::null; + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::getExistingDirectory( initialDir, parent, name, caption ); +#elif defined(Q_WS_WIN) + TQString initialDir; + if ( !dir.isEmpty() ) { + TQUrlOperator u( dir ); + if ( TQFileInfo( u.path() ).isDir() ) + initialDir = dir; + } else + initialDir = TQString::null; + if ( qt_use_native_dialogs && qApp->style().styleHint( TQStyle::SH_GUIStyle ) == WindowsStyle && dirOnly ) + return winGetExistingDirectory( initialDir, parent, name, caption ); +#endif +#if defined(Q_WS_MAC) + TQString *initialDir = 0; + if (!dir.isEmpty()) { + TQUrlOperator u(dir); + if (TQFileInfo(u.path()).isDir()) + initialDir = (TQString *)&dir; + } + if( qt_use_native_dialogs && (qApp->style().inherits(TQMAC_DEFAULT_STYLE) + || qApp->style().inherits("TQMacStyle"))) + return qt_mac_precomposeFileName(macGetOpenFileNames("", initialDir, parent, name, + caption, 0, FALSE, TRUE).first()); +#endif + + TQFileDialog *dlg = new TQFileDialog( parent, name ? name : "qt_filedlg_ged", TRUE ); + + Q_CHECK_PTR( dlg ); +#ifndef QT_NO_WIDGET_TOPEXTRA + if ( !caption.isNull() ) + dlg->setCaption( caption ); + else + dlg->setCaption( TQFileDialog::tr("Find Directory") ); +#endif + + dlg->setMode( dirOnly ? DirectoryOnly : Directory ); + + dlg->d->types->clear(); + dlg->d->types->insertItem( TQFileDialog::tr("Directories") ); + dlg->d->types->setEnabled( FALSE ); + + TQString dir_( dir ); + dir_ = dir_.simplifyWhiteSpace(); + if ( dir_.isEmpty() && !wd.isEmpty() ) + dir_ = wd; + TQUrlOperator u( dir_ ); + if ( u.isLocalFile() ) { + if ( !dir_.isEmpty() ) { + TQFileInfo f( u.path() ); + if ( f.exists() ) + if ( f.isDir() ) { + dlg->setDir( dir_ ); + wd = dir_; + } + } else if ( !wd.isEmpty() ) { + TQUrl tempUrl( wd ); + TQFileInfo f( tempUrl.path() ); + if ( f.isDir() ) { + dlg->setDir( wd ); + } + } else { + TQString theDir = dir_; + if ( theDir.isEmpty() ) { + theDir = ::toRootIfNotExists( TQDir::currentDirPath() ); + } if ( !theDir.isEmpty() ) { + TQUrl tempUrl( theDir ); + TQFileInfo f( tempUrl.path() ); + if ( f.isDir() ) { + wd = theDir; + dlg->setDir( theDir ); + } + } + } + } else { + dlg->setUrl( dir_ ); + } + + TQString result; + dlg->setSelection( dlg->d->url.toString() ); + + if ( dlg->exec() == TQDialog::Accepted ) { + result = dlg->selectedFile(); + wd = result; + } + delete dlg; + + if ( !result.isEmpty() && result.right( 1 ) != "/" ) + result += "/"; + + qt_resolve_symlinks = save_qt_resolve_symlinks; + + return result; +} + + +/*! + \property TQFileDialog::mode + \brief the file dialog's mode + + The default mode is \c ExistingFile. +*/ + +void TQFileDialog::setMode( Mode newMode ) +{ + if ( d->mode != newMode ) { + d->mode = newMode; + TQString sel = d->currentFileName; + int maxnamelen = 255; // _POSIX_MAX_PATH + if ( isDirectoryMode( newMode ) ) { + files->setSelectionMode( TQListView::Single ); + d->moreFiles->setSelectionMode( TQListBox::Single ); + if ( sel.isNull() ) + sel = TQString::fromLatin1("."); + d->types->setEnabled( FALSE ); + } else if ( newMode == ExistingFiles ) { + maxnamelen = INT_MAX; + files->setSelectionMode( TQListView::Extended ); + d->moreFiles->setSelectionMode( TQListBox::Extended ); + d->types->setEnabled( TRUE ); + } else { + files->setSelectionMode( TQListView::Single ); + d->moreFiles->setSelectionMode( TQListBox::Single ); + d->types->setEnabled( TRUE ); + } + nameEdit->setMaxLength(maxnamelen); + rereadDir(); + TQUrlInfo f( d->url, "." ); + trySetSelection( f.isDir(), d->url, FALSE ); + } + + TQString okt; + bool changeFilters = FALSE; + if ( mode() == AnyFile ) { + okt = tr("&Save"); + d->fileL->setText( tr("File &name:") ); + if ( d->types->count() == 1 ) { + d->types->setCurrentItem( 0 ); + if ( d->types->currentText() == "Directories" ) { + changeFilters = TRUE; + } + } + } + else if ( mode() == Directory || mode() == DirectoryOnly ) { + okt = tr("&OK"); + d->fileL->setText( tr("Directory:") ); + d->types->clear(); + d->types->insertItem( tr("Directories") ); + } + else { + okt = tr("&Open"); + d->fileL->setText( tr("File &name:") ); + if ( d->types->count() == 1 ) { + d->types->setCurrentItem( 0 ); + if ( d->types->currentText() == "Directories" ) { + changeFilters = TRUE; + } + } + } + + if ( changeFilters ) { + d->types->clear(); + d->types->insertItem( tr("All Files (*)") ); + } + + okB->setText( okt ); +} + +TQFileDialog::Mode TQFileDialog::mode() const +{ + return d->mode; +} + +/*! \reimp +*/ + +void TQFileDialog::done( int i ) +{ + if ( i == TQDialog::Accepted && (d->mode == ExistingFile || d->mode == ExistingFiles) ) { + TQStringList selection = selectedFiles(); + for ( uint f = 0; f < selection.count(); f++ ) { + TQString file = selection[f]; + if ( file.isNull() ) + continue; + if ( d->url.isLocalFile() && !TQFile::exists( file ) ) { + TQMessageBox::information( this, tr("Error"), + tr("%1\nFile not found.\nCheck path and filename.").arg( file ) ); + return; + } + } + } + TQDialog::done( i ); +} + +/*! + \property TQFileDialog::viewMode + + \brief the file dialog's view mode + + If you set the view mode to be \e Detail (the default), then you + will see the file's details, such as the size of the file and the + date the file was last modified in addition to the file's name. + + If you set the view mode to be \e List, then you will just + see a list of the files and folders. + + See \l TQFileDialog::ViewMode +*/ + + +TQFileDialog::ViewMode TQFileDialog::viewMode() const +{ + if ( detailViewMode ) + return Detail; + else + return List; +} + +void TQFileDialog::setViewMode( ViewMode m ) +{ + if ( m == Detail ) { + detailViewMode = TRUE; + d->stack->raiseWidget( files ); + d->detailView->setOn( TRUE ); + d->mcView->setOn( FALSE ); + } else if ( m == List ) { + detailViewMode = FALSE; + d->stack->raiseWidget( d->moreFiles ); + d->detailView->setOn( FALSE ); + d->mcView->setOn( TRUE ); + } +} + + +/*! + \property TQFileDialog::previewMode + + \brief the preview mode for the file dialog + + If you set the mode to be a mode other than \e NoPreview, you must + use setInfoPreview() or setContentsPreview() to set the dialog's + preview widget to your preview widget and enable the preview + widget(s) with setInfoPreviewEnabled() or + setContentsPreviewEnabled(). + + \sa infoPreview, contentsPreview, viewMode +*/ + +void TQFileDialog::setPreviewMode( PreviewMode m ) +{ + if ( m == NoPreview ) { + d->previewInfo->setOn( FALSE ); + d->previewContents->setOn( FALSE ); + } else if ( m == Info && d->infoPreview ) { + d->previewInfo->setOn( TRUE ); + d->previewContents->setOn( FALSE ); + changeMode( d->modeButtons->id( d->previewInfo ) ); + } else if ( m == Contents && d->contentsPreview ) { + d->previewInfo->setOn( FALSE ); + d->previewContents->setOn( TRUE ); + changeMode( d->modeButtons->id( d->previewContents ) ); + } +} +TQFileDialog::PreviewMode TQFileDialog::previewMode() const +{ + if ( d->infoPreview && d->infoPreviewWidget->isVisible() ) + return Info; + else if ( d->contentsPreview && d->contentsPreviewWidget->isVisible() ) + return Contents; + + return NoPreview; +} + + +/*! + Adds the specified widgets to the bottom of the file dialog. The + label \a l is placed underneath the "file name" and the "file types" + labels. The widget \a w is placed underneath the file types combobox. + The button \a b is placed underneath the Cancel pushbutton. + + \code + MyFileDialog::MyFileDialog( TQWidget* parent, const char* name ) : + TQFileDialog( parent, name ) + { + TQLabel* label = new TQLabel( "Added widgets", this ); + TQLineEdit* lineedit = new TQLineEdit( this ); + TQPushButton* pushbutton = new TQPushButton( this ); + + addWidgets( label, lineedit, pushbutton ); + } + \endcode + + If you don't want to have one of the widgets added, pass 0 in that + widget's position. + + Every time you call this function, a new row of widgets will be added + to the bottom of the file dialog. + + \sa addToolButton(), addLeftWidget(), addRightWidget() +*/ + +void TQFileDialog::addWidgets( TQLabel * l, TQWidget * w, TQPushButton * b ) +{ + if ( !l && !w && !b ) + return; + + d->geometryDirty = TRUE; + + TQHBoxLayout *lay = new TQHBoxLayout(); + d->extraWidgetsLayouts.append( lay ); + d->topLevelLayout->addLayout( lay ); + + if ( !l ) + l = new TQLabel( this, "qt_intern_lbl" ); + d->extraLabels.append( l ); + lay->addWidget( l ); + + if ( !w ) + w = new TQWidget( this, "qt_intern_widget" ); + d->extraWidgets.append( w ); + lay->addWidget( w ); + lay->addSpacing( 15 ); + + if ( b ) { + d->extraButtons.append( b ); + lay->addWidget( b ); + } else { + TQWidget *wid = new TQWidget( this, "qt_extrabuttons_widget" ); + d->extraButtons.append( wid ); + lay->addWidget( wid ); + } + + updateGeometries(); +} + +/*! + Adds the tool button \a b to the row of tool buttons at the top of the + file dialog. The button is appended to the right of + this row. If \a separator is TRUE, a small space is inserted between the + last button of the row and the new button \a b. + + \sa addWidgets(), addLeftWidget(), addRightWidget() +*/ + +void TQFileDialog::addToolButton( TQButton *b, bool separator ) +{ + if ( !b || !d->buttonLayout ) + return; + + d->geometryDirty = TRUE; + + d->toolButtons.append( b ); + if ( separator ) + d->buttonLayout->addSpacing( 8 ); + d->buttonLayout->addWidget( b ); + + updateGeometries(); +} + +/*! + Adds the widget \a w to the left-hand side of the file dialog. + + \sa addRightWidget(), addWidgets(), addToolButton() +*/ + +void TQFileDialog::addLeftWidget( TQWidget *w ) +{ + if ( !w ) + return; + d->geometryDirty = TRUE; + + d->leftLayout->addWidget( w ); + d->leftLayout->addSpacing( 5 ); + + updateGeometries(); +} + +/*! + Adds the widget \a w to the right-hand side of the file dialog. + + \sa addLeftWidget(), addWidgets(), addToolButton() +*/ + +void TQFileDialog::addRightWidget( TQWidget *w ) +{ + if ( !w ) + return; + d->geometryDirty = TRUE; + + d->rightLayout->addSpacing( 5 ); + d->rightLayout->addWidget( w ); + + updateGeometries(); +} + +/*! \reimp */ + +void TQFileDialog::keyPressEvent( TQKeyEvent * ke ) +{ + if ( !d->ignoreNextKeyPress && + ke && ( ke->key() == Key_Enter || + ke->key() == Key_Return ) ) { + ke->ignore(); + if ( d->paths->hasFocus() ) { + ke->accept(); + if ( d->url == TQUrl(d->paths->currentText()) ) + nameEdit->setFocus(); + } else if ( d->types->hasFocus() ) { + ke->accept(); + // ### is there a suitable condition for this? only valid + // wildcards? + nameEdit->setFocus(); + } else if ( nameEdit->hasFocus() ) { + if ( d->currentFileName.isNull() ) { + // maybe change directory + TQUrlInfo i( d->url, nameEdit->text() ); + if ( i.isDir() ) { + nameEdit->setText( TQString::fromLatin1("") ); + setDir( TQUrlOperator( d->url, TQFileDialogPrivate::encodeFileName(i.name()) ) ); + } + ke->accept(); + } else if ( mode() == ExistingFiles ) { + TQUrlInfo i( d->url, nameEdit->text() ); + if ( i.isFile() ) { + TQListViewItem * i = files->firstChild(); + while ( i && nameEdit->text() != i->text( 0 ) ) + i = i->nextSibling(); + if ( i ) + files->setSelected( i, TRUE ); + else + ke->accept(); // strangely, means to ignore that event + } + } + } else if ( files->hasFocus() || d->moreFiles->hasFocus() ) { + ke->accept(); + } + } else if ( ke->key() == Key_Escape ) { + ke->ignore(); + } + + d->ignoreNextKeyPress = FALSE; + + if ( !ke->isAccepted() ) { + TQDialog::keyPressEvent( ke ); + } +} + + +/*! \class TQFileIconProvider qfiledialog.h + + \brief The TQFileIconProvider class provides icons for TQFileDialog to + use. + + \ingroup misc + + By default TQFileIconProvider is not used, but any application or + library can subclass it, reimplement pixmap() to return a suitable + icon, and make all TQFileDialog objects use it by calling the static + function TQFileDialog::setIconProvider(). + + It is advisable to make all the icons that TQFileIconProvider returns be + the same size or at least the same width. This makes the list view + look much better. + + \sa TQFileDialog +*/ + + +/*! Constructs an empty file icon provider called \a name, with the + parent \a parent. +*/ + +TQFileIconProvider::TQFileIconProvider( TQObject * parent, const char* name ) + : TQObject( parent, name ) +{ + // nothing necessary +} + + +/*! + Returns a pointer to a pixmap that should be used to + signify the file with the information \a info. + + If pixmap() returns 0, TQFileDialog draws the default pixmap. + + The default implementation returns particular icons for files, directories, + link-files and link-directories. It returns a blank "icon" for other types. + + If you return a pixmap here, it should measure 16x16 pixels. +*/ + +const TQPixmap * TQFileIconProvider::pixmap( const TQFileInfo & info ) +{ + if ( info.isSymLink() ) { + if ( info.isFile() ) + return symLinkFileIcon; + else + return symLinkDirIcon; + } else if ( info.isDir() ) { + return closedFolderIcon; + } else if ( info.isFile() ) { + return fileIcon; + } else { + return fifteenTransparentPixels; + } +} + +/*! + Sets the TQFileIconProvider used by the file dialog to \a provider. + + The default is that there is no TQFileIconProvider and TQFileDialog + just draws a folder icon next to each directory and nothing next + to files. + + \sa TQFileIconProvider, iconProvider() +*/ + +void TQFileDialog::setIconProvider( TQFileIconProvider * provider ) +{ + fileIconProvider = provider; +} + + +/*! + Returns a pointer to the icon provider currently set on the file dialog. + By default there is no icon provider, and this function returns 0. + + \sa setIconProvider(), TQFileIconProvider +*/ + +TQFileIconProvider * TQFileDialog::iconProvider() +{ + return fileIconProvider; +} + + +#if defined(Q_WS_WIN) + +// ### FIXME: this code is duplicated in qdns.cpp +static TQString getWindowsRegString( HKEY key, const TQString &subKey ) +{ + TQString s; + QT_WA( { + char buf[1024]; + DWORD bsz = sizeof(buf); + int r = RegQueryValueEx( key, (TCHAR*)subKey.ucs2(), 0, 0, (LPBYTE)buf, &bsz ); + if ( r == ERROR_SUCCESS ) { + s = TQString::fromUcs2( (unsigned short *)buf ); + } else if ( r == ERROR_MORE_DATA ) { + char *ptr = new char[bsz+1]; + r = RegQueryValueEx( key, (TCHAR*)subKey.ucs2(), 0, 0, (LPBYTE)ptr, &bsz ); + if ( r == ERROR_SUCCESS ) + s = ptr; + delete [] ptr; + } + } , { + char buf[512]; + DWORD bsz = sizeof(buf); + int r = RegQueryValueExA( key, subKey.local8Bit(), 0, 0, (LPBYTE)buf, &bsz ); + if ( r == ERROR_SUCCESS ) { + s = buf; + } else if ( r == ERROR_MORE_DATA ) { + char *ptr = new char[bsz+1]; + r = RegQueryValueExA( key, subKey.local8Bit(), 0, 0, (LPBYTE)ptr, &bsz ); + if ( r == ERROR_SUCCESS ) + s = ptr; + delete [] ptr; + } + } ); + return s; +} + +static void initPixmap( TQPixmap &pm ) +{ + pm.fill( TQt::white ); +} + + +TQWindowsIconProvider::TQWindowsIconProvider( TQObject *parent, const char *name ) + : TQFileIconProvider( parent, name ) +{ + pixw = GetSystemMetrics( SM_CXSMICON ); + pixh = GetSystemMetrics( SM_CYSMICON ); + + HKEY k; + HICON si; + int r; + TQString s; + UINT res = 0; + + // ---------- get default folder pixmap + const wchar_t iconFolder[] = L"folder\\DefaultIcon"; // workaround for Borland + QT_WA( { + r = RegOpenKeyEx( HKEY_CLASSES_ROOT, + iconFolder, + 0, KEY_READ, &k ); + } , { + r = RegOpenKeyExA( HKEY_CLASSES_ROOT, + "folder\\DefaultIcon", + 0, KEY_READ, &k ); + } ); + resolveLibs(); + if ( r == ERROR_SUCCESS ) { + s = getWindowsRegString( k, TQString::null ); + RegCloseKey( k ); + + TQStringList lst = TQStringList::split( ",", s ); + + if (lst.count() >= 2) { // don't just assume that lst has two entries +#ifndef Q_OS_TEMP + QT_WA( { + res = ptrExtractIconEx( (TCHAR*)lst[ 0 ].simplifyWhiteSpace().ucs2(), + lst[ 1 ].simplifyWhiteSpace().toInt(), + 0, &si, 1 ); + } , { + res = ExtractIconExA( lst[ 0 ].simplifyWhiteSpace().local8Bit(), + lst[ 1 ].simplifyWhiteSpace().toInt(), + 0, &si, 1 ); + } ); +#else + res = (UINT)ExtractIconEx( (TCHAR*)lst[ 0 ].simplifyWhiteSpace().ucs2(), + lst[ 1 ].simplifyWhiteSpace().toInt(), + 0, &si, 1 ); +#endif + } + if ( res ) { + defaultFolder.resize( pixw, pixh ); + initPixmap( defaultFolder ); + TQPainter p( &defaultFolder ); + DrawIconEx( p.handle(), 0, 0, si, pixw, pixh, 0, 0, DI_NORMAL ); + p.end(); + defaultFolder.setMask( defaultFolder.createHeuristicMask() ); + *closedFolderIcon = defaultFolder; + DestroyIcon( si ); + } else { + defaultFolder = *closedFolderIcon; + } + } else { + RegCloseKey( k ); + } + + //------------------------------- get default file pixmap +#ifndef Q_OS_TEMP + QT_WA( { + res = ptrExtractIconEx( L"shell32.dll", + 0, 0, &si, 1 ); + } , { + res = ExtractIconExA( "shell32.dll", + 0, 0, &si, 1 ); + } ); +#else + res = (UINT)ExtractIconEx( L"shell32.dll", + 0, 0, &si, 1 ); +#endif + + if ( res ) { + defaultFile.resize( pixw, pixh ); + initPixmap( defaultFile ); + TQPainter p( &defaultFile ); + DrawIconEx( p.handle(), 0, 0, si, pixw, pixh, 0, 0, DI_NORMAL ); + p.end(); + defaultFile.setMask( defaultFile.createHeuristicMask() ); + *fileIcon = defaultFile; + DestroyIcon( si ); + } else { + defaultFile = *fileIcon; + } + + //------------------------------- get default exe pixmap +#ifndef Q_OS_TEMP + QT_WA( { + res = ptrExtractIconEx( L"shell32.dll", + 2, 0, &si, 1 ); + } , { + res = ExtractIconExA( "shell32.dll", + 2, 0, &si, 1 ); + } ); +#else + res = (UINT)ExtractIconEx( L"ceshell.dll", + 10, 0, &si, 1 ); +#endif + + if ( res ) { + defaultExe.resize( pixw, pixh ); + initPixmap( defaultExe ); + TQPainter p( &defaultExe ); + DrawIconEx( p.handle(), 0, 0, si, pixw, pixh, 0, 0, DI_NORMAL ); + p.end(); + defaultExe.setMask( defaultExe.createHeuristicMask() ); + DestroyIcon( si ); + } else { + defaultExe = *fileIcon; + } +} + +TQWindowsIconProvider::~TQWindowsIconProvider() +{ + if ( this == fileIconProvider ) + fileIconProvider = 0; +} + +const TQPixmap * TQWindowsIconProvider::pixmap( const TQFileInfo &fi ) +{ + if (fi.isSymLink()) { + TQString real = fi.readLink(); + if (!real.isEmpty()) + return pixmap(TQFileInfo(real)); + } + + TQString ext = fi.extension( FALSE ).upper(); + TQString key = ext; + ext.prepend( "." ); + TQMap< TQString, TQPixmap >::Iterator it; + + if ( fi.isDir() ) { + return &defaultFolder; + } else if ( ext != ".EXE" ) { + it = cache.find( key ); + if ( it != cache.end() ) + return &( *it ); + + HKEY k, k2; + int r; + QT_WA( { + r = RegOpenKeyEx( HKEY_CLASSES_ROOT, (TCHAR*)ext.ucs2(), + 0, KEY_READ, &k ); + } , { + r = RegOpenKeyExA( HKEY_CLASSES_ROOT, ext.local8Bit(), + 0, KEY_READ, &k ); + } ); + TQString s; + if ( r == ERROR_SUCCESS ) { + s = getWindowsRegString( k, TQString::null ); + } else { + cache[ key ] = defaultFile; + RegCloseKey( k ); + return &defaultFile; + } + RegCloseKey( k ); + + QT_WA( { + r = RegOpenKeyEx( HKEY_CLASSES_ROOT, (TCHAR*)TQString( s + "\\DefaultIcon" ).ucs2(), + 0, KEY_READ, &k2 ); + } , { + r = RegOpenKeyExA( HKEY_CLASSES_ROOT, TQString( s + "\\DefaultIcon" ).local8Bit() , + 0, KEY_READ, &k2 ); + } ); + if ( r == ERROR_SUCCESS ) { + s = getWindowsRegString( k2, TQString::null ); + } else { + cache[ key ] = defaultFile; + RegCloseKey( k2 ); + return &defaultFile; + } + RegCloseKey( k2 ); + + TQStringList lst = TQStringList::split( ",", s ); + + HICON si; + UINT res = 0; + if (lst.count() >= 2) { // don't just assume that lst has two entries + TQString filepath = lst[ 0 ].stripWhiteSpace(); + if ( !filepath.isEmpty() ) { + if ( filepath.find("%1") != -1 ) { + filepath = filepath.arg( fi.filePath() ); + if ( ext == ".DLL" ) { + pix = defaultFile; + return &pix; + } + } + if ( filepath[0] == '"' && filepath[(int)filepath.length()-1] == '"' ) + filepath = filepath.mid( 1, filepath.length()-2 ); + + resolveLibs(); +#ifndef Q_OS_TEMP + QT_WA( { + res = ptrExtractIconEx( (TCHAR*)filepath.ucs2(), lst[ 1 ].stripWhiteSpace().toInt(), + 0, &si, 1 ); + } , { + res = ExtractIconExA( filepath.local8Bit(), lst[ 1 ].stripWhiteSpace().toInt(), + 0, &si, 1 ); + } ); +#else + res = (UINT)ExtractIconEx( (TCHAR*)filepath.ucs2(), lst[ 1 ].stripWhiteSpace().toInt(), + 0, &si, 1 ); +#endif + } + } + + if ( res ) { + pix.resize( pixw, pixh ); + initPixmap( pix ); + TQPainter p( &pix ); + DrawIconEx( p.handle(), 0, 0, si, pixw, pixh, 0, 0, DI_NORMAL ); + p.end(); + pix.setMask( pix.createHeuristicMask() ); + DestroyIcon( si ); + } else { + pix = defaultFile; + } + + cache[ key ] = pix; + return &pix; + } else { + HICON si; + UINT res = 0; + if ( !fi.absFilePath().isEmpty() ) { +#ifndef Q_OS_TEMP + QT_WA( { + res = ptrExtractIconEx( (TCHAR*)fi.absFilePath().ucs2(), -1, + 0, 0, 1 ); + } , { + res = ExtractIconExA( fi.absFilePath().local8Bit(), -1, + 0, 0, 1 ); + } ); + + if ( res ) { + QT_WA( { + res = ptrExtractIconEx( (TCHAR*)fi.absFilePath().ucs2(), res - 1, + 0, &si, 1 ); + } , { + res = ExtractIconExA( fi.absFilePath().local8Bit(), res - 1, + 0, &si, 1 ); + } ); + } +#else + res = (UINT)ExtractIconEx( (TCHAR*)fi.absFilePath().ucs2(), -1, + 0, 0, 1 ); + if ( res ) + res = (UINT)ExtractIconEx( (TCHAR*)fi.absFilePath().ucs2(), res - 1, + 0, &si, 1 ); +#endif + + } + + if ( res ) { + pix.resize( pixw, pixh ); + initPixmap( pix ); + TQPainter p( &pix ); + DrawIconEx( p.handle(), 0, 0, si, pixw, pixh, 0, 0, DI_NORMAL ); + p.end(); + pix.setMask( pix.createHeuristicMask() ); + DestroyIcon( si ); + } else { + pix = defaultExe; + } + + return &pix; + } + + // can't happen! + return 0; +} +#endif + + + +/*! + \reimp +*/ +bool TQFileDialog::eventFilter( TQObject * o, TQEvent * e ) +{ + if ( e->type() == TQEvent::KeyPress && ( (TQKeyEvent*)e )->key() == Key_F5 ) { + rereadDir(); + ((TQKeyEvent *)e)->accept(); + return TRUE; + } else if ( e->type() == TQEvent::KeyPress && ( (TQKeyEvent*)e )->key() == Key_F2 && + ( o == files || o == files->viewport() ) ) { + if ( files->isVisible() && files->currentItem() ) { + if ( TQUrlInfo( d->url, "." ).isWritable() && files->currentItem()->text( 0 ) != ".." ) { + files->renameItem = files->currentItem(); + files->startRename( TRUE ); + } + } + ((TQKeyEvent *)e)->accept(); + return TRUE; + } else if ( e->type() == TQEvent::KeyPress && ( (TQKeyEvent*)e )->key() == Key_F2 && + ( o == d->moreFiles || o == d->moreFiles->viewport() ) ) { + if ( d->moreFiles->isVisible() && d->moreFiles->currentItem() != -1 ) { + if ( TQUrlInfo( d->url, "." ).isWritable() && + d->moreFiles->item( d->moreFiles->currentItem() )->text() != ".." ) { + d->moreFiles->renameItem = d->moreFiles->item( d->moreFiles->currentItem() ); + d->moreFiles->startRename( TRUE ); + } + } + ((TQKeyEvent *)e)->accept(); + return TRUE; + } else if ( e->type() == TQEvent::KeyPress && d->moreFiles->renaming ) { + d->moreFiles->lined->setFocus(); + TQApplication::sendEvent( d->moreFiles->lined, e ); + ((TQKeyEvent *)e)->accept(); + return TRUE; + } else if ( e->type() == TQEvent::KeyPress && files->renaming ) { + files->lined->setFocus(); + TQApplication::sendEvent( files->lined, e ); + ((TQKeyEvent *)e)->accept(); + return TRUE; + } else if ( e->type() == TQEvent::KeyPress && + ((TQKeyEvent *)e)->key() == Key_Backspace && + ( o == files || + o == d->moreFiles || + o == files->viewport() || + o == d->moreFiles->viewport() ) ) { + cdUpClicked(); + ((TQKeyEvent *)e)->accept(); + return TRUE; + } else if ( e->type() == TQEvent::KeyPress && + ((TQKeyEvent *)e)->key() == Key_Delete && + ( o == files || + o == files->viewport() ) ) { + if ( files->currentItem() ) + deleteFile( files->currentItem()->text( 0 ) ); + ((TQKeyEvent *)e)->accept(); + return TRUE; + } else if ( e->type() == TQEvent::KeyPress && + ((TQKeyEvent *)e)->key() == Key_Delete && + ( o == d->moreFiles || + o == d->moreFiles->viewport() ) ) { + int c = d->moreFiles->currentItem(); + if ( c >= 0 ) + deleteFile( d->moreFiles->item( c )->text() ); + ((TQKeyEvent *)e)->accept(); + return TRUE; + } else if ( o == files && e->type() == TQEvent::FocusOut && files->currentItem() ) { + } else if ( o == files && e->type() == TQEvent::KeyPress ) { + TQTimer::singleShot( 0, this, SLOT(fixupNameEdit()) ); + } else if ( o == nameEdit && e->type() == TQEvent::KeyPress && d->mode != AnyFile ) { + if ( ( nameEdit->cursorPosition() == (int)nameEdit->text().length() || nameEdit->hasSelectedText() ) && + isprint(((TQKeyEvent *)e)->ascii()) ) { +#if defined(Q_WS_WIN) + TQString nt( nameEdit->text().lower() ); +#else + TQString nt( nameEdit->text() ); +#endif + nt.truncate( nameEdit->cursorPosition() ); + nt += (char)(((TQKeyEvent *)e)->ascii()); + TQListViewItem * i = files->firstChild(); +#if defined(Q_WS_WIN) + while( i && i->text( 0 ).left(nt.length()).lower() != nt ) +#else + while( i && i->text( 0 ).left(nt.length()) != nt ) +#endif + i = i->nextSibling(); + if ( i ) { + nt = i->text( 0 ); + int cp = nameEdit->cursorPosition()+1; + nameEdit->validateAndSet( nt, cp, cp, nt.length() ); + return TRUE; + } + } + } else if ( o == nameEdit && e->type() == TQEvent::FocusIn ) { + fileNameEditDone(); + } else if ( d->moreFiles->renaming && o != d->moreFiles->lined && e->type() == TQEvent::FocusIn ) { + d->moreFiles->lined->setFocus(); + return TRUE; + } else if ( files->renaming && o != files->lined && e->type() == TQEvent::FocusIn ) { + files->lined->setFocus(); + return TRUE; + } else if ( ( o == d->moreFiles || o == d->moreFiles->viewport() ) && + e->type() == TQEvent::FocusIn ) { + if ( o == d->moreFiles->viewport() && !d->moreFiles->viewport()->hasFocus() || + o == d->moreFiles && !d->moreFiles->hasFocus() ) + ((TQWidget*)o)->setFocus(); + return FALSE; + } + + return TQDialog::eventFilter( o, e ); +} + +/*! + Sets the filters used in the file dialog to \a filters. Each group + of filters must be separated by \c{;;} (\e two semi-colons). + + \code + TQString types("Image files (*.png *.xpm *.jpg);;" + "Text files (*.txt);;" + "Any files (*)"); + TQFileDialog fd = new TQFileDialog( this ); + fd->setFilters( types ); + fd->show(); + \endcode + +*/ + +void TQFileDialog::setFilters( const TQString &filters ) +{ + TQStringList lst = makeFiltersList( filters ); + setFilters( lst ); +} + +/*! + \overload + + \a types must be a null-terminated list of strings. + +*/ + +void TQFileDialog::setFilters( const char ** types ) +{ + if ( !types || !*types ) + return; + + d->types->clear(); + while( types && *types ) { + d->types->insertItem( TQString::fromLatin1(*types) ); + types++; + } + d->types->setCurrentItem( 0 ); + setFilter( d->types->text( 0 ) ); +} + + +/*! \overload void TQFileDialog::setFilters( const TQStringList & ) +*/ + +void TQFileDialog::setFilters( const TQStringList & types ) +{ + if ( types.count() < 1 ) + return; + + d->types->clear(); + for ( TQStringList::ConstIterator it = types.begin(); it != types.end(); ++it ) + d->types->insertItem( *it ); + d->types->setCurrentItem( 0 ); + setFilter( d->types->text( 0 ) ); +} + +/*! + Adds the filter \a filter to the list of filters and makes it the + current filter. + + \code + TQFileDialog* fd = new TQFileDialog( this ); + fd->addFilter( "Images (*.png *.jpg *.xpm)" ); + fd->show(); + \endcode + + In the above example, a file dialog is created, and the file filter "Images + (*.png *.jpg *.xpm)" is added and is set as the current filter. The original + filter, "All Files (*)", is still available. + + \sa setFilter(), setFilters() +*/ + +void TQFileDialog::addFilter( const TQString &filter ) +{ + if ( filter.isEmpty() ) + return; + TQString f = filter; + TQRegExp r( TQString::fromLatin1(qt_file_dialog_filter_reg_exp) ); + int index = r.search( f ); + if ( index >= 0 ) + f = r.cap( 2 ); + for ( int i = 0; i < d->types->count(); ++i ) { + TQString f2( d->types->text( i ) ); + int index = r.search( f2 ); + if ( index >= 0 ) + f2 = r.cap( 1 ); + if ( f2 == f ) { + d->types->setCurrentItem( i ); + setFilter( f2 ); + return; + } + } + + d->types->insertItem( filter ); + d->types->setCurrentItem( d->types->count() - 1 ); + setFilter( d->types->text( d->types->count() - 1 ) ); +} + +/*! + Since modeButtons is a top-level widget, it may be destroyed by the + kernel at application exit. Notice if this happens to + avoid double deletion. +*/ + +void TQFileDialog::modeButtonsDestroyed() +{ + if ( d ) + d->modeButtons = 0; +} + + +/*! + This is a convenience static function that will return one or more + existing files selected by the user. + + \code + TQStringList files = TQFileDialog::getOpenFileNames( + "Images (*.png *.xpm *.jpg)", + "/home", + this, + "open files dialog", + "Select one or more files to open" ); + \endcode + + This function creates a modal file dialog called \a name, with + parent \a parent. If \a parent is not 0, the dialog will be shown + centered over the parent. + + The file dialog's working directory will be set to \a dir. If \a + dir includes a file name, the file will be selected. The filter + is set to \a filter so that only those files which match the filter + are shown. The filter selected is set to \a selectedFilter. The parameters + \a dir, \a selectedFilter and \a filter may be TQString::null. + + The dialog's caption is set to \a caption. If \a caption is not + specified then a default caption will be used. + + Under Windows and Mac OS X, this static function will use the native + file dialog and not a TQFileDialog, unless the style of the application + is set to something other than the native style. (Note that on Windows the + dialog will spin a blocking modal event loop that will not dispatch any + TQTimers and if parent is not 0 then it will position the dialog just under + the parent's titlebar). + + Under Unix/X11, the normal behavior of the file dialog is to resolve + and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp, + the file dialog will change to /var/tmp after entering /usr/tmp. + If \a resolveSymlinks is FALSE, the file dialog will treat + symlinks as regular directories. + + Note that if you want to iterate over the list of files, you should + iterate over a copy, e.g. + \code + TQStringList list = files; + TQStringList::Iterator it = list.begin(); + while( it != list.end() ) { + myProcessing( *it ); + ++it; + } + \endcode + + \sa getOpenFileName(), getSaveFileName(), getExistingDirectory() +*/ + +TQStringList TQFileDialog::getOpenFileNames( const TQString & filter, + const TQString& dir, + TQWidget *parent, + const char* name, + const TQString& caption, + TQString *selectedFilter, + bool resolveSymlinks ) +{ + bool save_qt_resolve_symlinks = qt_resolve_symlinks; + qt_resolve_symlinks = resolveSymlinks; + + TQStringList filters; + if ( !filter.isEmpty() ) + filters = makeFiltersList( filter ); + + makeVariables(); + + if ( workingDirectory->isNull() ) + *workingDirectory = ::toRootIfNotExists( TQDir::currentDirPath() ); + + if ( !dir.isEmpty() ) { + // #### works only correct for local files + TQUrlOperator u( TQFileDialogPrivate::encodeFileName(dir) ); + if ( u.isLocalFile() && TQFileInfo( u.path() ).isDir() ) { + *workingDirectory = dir; + } else { + *workingDirectory = u.toString(); + } + } + +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::getOpenFileNames( filter, workingDirectory, parent, name, caption, selectedFilter, true ); +#elif defined(Q_WS_WIN) + if ( qt_use_native_dialogs && qApp->style().styleHint( TQStyle::SH_GUIStyle ) == WindowsStyle ) + return winGetOpenFileNames( filter, workingDirectory, parent, name, caption, selectedFilter ); +#elif defined(Q_WS_MAC) + if (qt_use_native_dialogs && (qApp->style().inherits(TQMAC_DEFAULT_STYLE) + || qApp->style().inherits("TQMacStyle"))) { + TQStringList sl = macGetOpenFileNames(filter, dir.isEmpty() ? 0 : workingDirectory, parent, + name, caption, selectedFilter); + TQStringList::iterator it = sl.begin(); + while (it != sl.end()) { + *it = qt_mac_precomposeFileName(*it); + ++it; + } + return sl; + } +#endif + + TQFileDialog *dlg = new TQFileDialog( *workingDirectory, TQString::null, parent, name ? name : "qt_filedlg_gofns", TRUE ); + + Q_CHECK_PTR( dlg ); +#ifndef QT_NO_WIDGET_TOPEXTRA + if ( !caption.isNull() ) + dlg->setCaption( caption ); + else + dlg->setCaption( TQFileDialog::tr("Open") ); +#endif + + dlg->setFilters( filters ); + if ( selectedFilter ) + dlg->setFilter( *selectedFilter ); + dlg->setMode( TQFileDialog::ExistingFiles ); + TQString result; + TQStringList lst; + if ( dlg->exec() == TQDialog::Accepted ) { + lst = dlg->selectedFiles(); + *workingDirectory = dlg->d->url; + if ( selectedFilter ) + *selectedFilter = dlg->selectedFilter(); + } + delete dlg; + + qt_resolve_symlinks = save_qt_resolve_symlinks; + return lst; +} + +/*! Updates the line edit to match the speed-key usage in TQListView. */ + +void TQFileDialog::fixupNameEdit() +{ + if ( files->currentItem() ) { + if ( ( (TQFileDialogPrivate::File*)files->currentItem() )->info.isFile() ) + nameEdit->setText( files->currentItem()->text( 0 ) ); + } +} + +/*! + Returns the URL of the current working directory in the file dialog. + + \sa setUrl() +*/ + +TQUrl TQFileDialog::url() const +{ + return d->url; +} + +static bool isRoot( const TQUrl &u ) +{ +#if defined(Q_OS_MAC9) + TQString p = TQDir::convertSeparators(u.path()); + if(p.contains(':') == 1) + return TRUE; +#elif defined(Q_OS_UNIX) + if ( u.path() == "/" ) + return TRUE; +#elif defined(Q_OS_WIN32) + TQString p = u.path(); + if ( p.length() == 3 && + p.right( 2 ) == ":/" ) + return TRUE; + if ( p[ 0 ] == '/' && p[ 1 ] == '/' ) { + int slashes = p.contains( '/' ); + if ( slashes <= 3 ) + return TRUE; + if ( slashes == 4 && p[ (int)p.length() - 1 ] == '/' ) + return TRUE; + } +#else +#if defined(Q_CC_GNU) +#warning "case not covered.." +#endif +#endif + + if ( !u.isLocalFile() && u.path() == "/" ) + return TRUE; + + return FALSE; +} + +void TQFileDialog::urlStart( TQNetworkOperation *op ) +{ + if ( !op ) + return; + +#if defined(Q_WS_WIN) + qt_ntfs_permission_lookup--; +#endif + if ( op->operation() == TQNetworkProtocol::OpListChildren ) { +#ifndef QT_NO_CURSOR + if ( !d->cursorOverride ) { + TQApplication::setOverrideCursor( TQCursor( TQt::WaitCursor ) ); + d->cursorOverride = TRUE; + } +#endif + if ( isRoot( d->url ) ) + d->cdToParent->setEnabled( FALSE ); + else + d->cdToParent->setEnabled( TRUE ); + d->mimeTypeTimer->stop(); + d->sortedList.clear(); + d->pendingItems.clear(); + d->moreFiles->clearSelection(); + files->clearSelection(); + d->moreFiles->clear(); + files->clear(); + files->setSorting( -1 ); + + TQString s = d->url.toString( FALSE, FALSE ); + bool found = FALSE; + for ( int i = 0; i < d->paths->count(); ++i ) { +#if defined(Q_WS_WIN) + if ( d->paths->text( i ).lower() == s.lower() ) { +#else + if ( d->paths->text( i ) == s ) { +#endif + found = TRUE; + d->paths->setCurrentItem( i ); + break; + } + } + if ( !found ) { + d->paths->insertItem( *openFolderIcon, s, -1 ); + d->paths->setCurrentItem( d->paths->count() - 1 ); + } + d->last = 0; + d->hadDotDot = FALSE; + + if ( d->goBack && d->history.last() != d->url.toString() ) { + d->history.append( d->url.toString() ); + if ( d->history.count() > 1 ) + d->goBack->setEnabled( TRUE ); + } + } +} + +void TQFileDialog::urlFinished( TQNetworkOperation *op ) +{ + if ( !op ) + return; + +#ifndef QT_NO_CURSOR + if ( op->operation() == TQNetworkProtocol::OpListChildren && + d->cursorOverride ) { + TQApplication::restoreOverrideCursor(); + d->cursorOverride = FALSE; + } +#endif + + if ( op->state() == TQNetworkProtocol::StFailed ) { + if ( d->paths->hasFocus() ) + d->ignoreNextKeyPress = TRUE; + + if ( d->progressDia ) { + d->ignoreStop = TRUE; + d->progressDia->close(); + delete d->progressDia; + d->progressDia = 0; + } + + int ecode = op->errorCode(); + TQMessageBox::critical( this, tr( "Error" ), op->protocolDetail() ); + + if ( ecode == TQNetworkProtocol::ErrListChildren || ecode == TQNetworkProtocol::ErrParse || + ecode == TQNetworkProtocol::ErrUnknownProtocol || ecode == TQNetworkProtocol::ErrLoginIncorrect || + ecode == TQNetworkProtocol::ErrValid || ecode == TQNetworkProtocol::ErrHostNotFound || + ecode == TQNetworkProtocol::ErrFileNotExisting ) { + if (d->url != d->oldUrl) { + d->url = d->oldUrl; + rereadDir(); + } + } else { + // another error happened, no need to go back to last dir + } + } else if ( op->operation() == TQNetworkProtocol::OpListChildren && + op == d->currListChildren ) { + if ( !d->hadDotDot && !isRoot( d->url ) ) { + bool ok = TRUE; +#if defined(Q_WS_WIN) + if ( d->url.path().left( 2 ) == "//" ) + ok = FALSE; +#endif + if ( ok ) { + TQUrlInfo ui( d->url, ".." ); + ui.setName( ".." ); + ui.setDir( TRUE ); + ui.setFile( FALSE ); + ui.setSymLink( FALSE ); + ui.setSize( 0 ); + TQValueList<TQUrlInfo> lst; + lst << ui; + insertEntry( lst, 0 ); + } + } + resortDir(); + } else if ( op->operation() == TQNetworkProtocol::OpGet ) { + } else if ( op->operation() == TQNetworkProtocol::OpPut ) { + rereadDir(); + if ( d->progressDia ) { + d->ignoreStop = TRUE; + d->progressDia->close(); + } + delete d->progressDia; + d->progressDia = 0; + } + +#if defined(Q_WS_WIN) + if (d->oldPermissionLookup != qt_ntfs_permission_lookup) + qt_ntfs_permission_lookup++; +#endif +} + +void TQFileDialog::dataTransferProgress( int bytesDone, int bytesTotal, TQNetworkOperation *op ) +{ + if ( !op ) + return; + + TQString label; + TQUrl u( op->arg( 0 ) ); + if ( u.isLocalFile() ) { + label = u.path(); + } else { + label = TQString( "%1 (on %2)" ); + label = label.arg( u.path() ).arg( u.host() ); + } + + if ( !d->progressDia ) { + if ( bytesDone < bytesTotal) { + d->ignoreStop = FALSE; + d->progressDia = new TQFDProgressDialog( this, label, bytesTotal ); + connect( d->progressDia, SIGNAL( cancelled() ), + this, SLOT( stopCopy() ) ); + d->progressDia->show(); + } else + return; + } + + if ( d->progressDia ) { + if ( op->operation() == TQNetworkProtocol::OpGet ) { + if ( d->progressDia ) { + d->progressDia->setReadProgress( bytesDone ); + } + } else if ( op->operation() == TQNetworkProtocol::OpPut ) { + if ( d->progressDia ) { + d->progressDia->setWriteLabel( label ); + d->progressDia->setWriteProgress( bytesDone ); + } + } else { + return; + } + } +} + +void TQFileDialog::insertEntry( const TQValueList<TQUrlInfo> &lst, TQNetworkOperation *op ) +{ + if ( op && op->operation() == TQNetworkProtocol::OpListChildren && + op != d->currListChildren ) + return; + TQValueList<TQUrlInfo>::ConstIterator it = lst.begin(); + for ( ; it != lst.end(); ++it ) { + const TQUrlInfo &inf = *it; + if ( d->mode == DirectoryOnly && !inf.isDir() ) + continue; + if ( inf.name() == ".." ) { + d->hadDotDot = TRUE; + if ( isRoot( d->url ) ) + continue; +#if defined(Q_WS_WIN) + if ( d->url.path().left( 2 ) == "//" ) + continue; +#endif + } else if ( inf.name() == "." ) + continue; + +#if defined(Q_WS_WIN) + // Workaround a Windows bug, '..' is apparantly hidden in directories + // that are one level away from root + if ( !bShowHiddenFiles && inf.name() != ".." ) { + if ( d->url.isLocalFile() ) { + TQString file = d->url.path(); + if ( !file.endsWith( "/" ) ) + file.append( "/" ); + file += inf.name(); + QT_WA( { + if ( GetFileAttributesW( (TCHAR*)file.ucs2() ) & FILE_ATTRIBUTE_HIDDEN ) + continue; + } , { + if ( GetFileAttributesA( file.local8Bit() ) & FILE_ATTRIBUTE_HIDDEN ) + continue; + } ); + } else { + if ( inf.name() != ".." && inf.name()[0] == TQChar('.') ) + continue; + } + } +#else + if ( !bShowHiddenFiles && inf.name() != ".." ) { + if ( inf.name()[ 0 ] == TQChar( '.' ) ) + continue; + } +#endif + if ( !d->url.isLocalFile() ) { + TQFileDialogPrivate::File * i = 0; + TQFileDialogPrivate::MCItem *i2 = 0; + i = new TQFileDialogPrivate::File( d, &inf, files ); + i2 = new TQFileDialogPrivate::MCItem( d->moreFiles, i ); + + if ( d->mode == ExistingFiles && inf.isDir() || + ( isDirectoryMode( d->mode ) && inf.isFile() ) ) { + i->setSelectable( FALSE ); + i2->setSelectable( FALSE ); + } + + i->i = i2; + } + + d->sortedList.append( new TQUrlInfo( inf ) ); + } +} + +void TQFileDialog::removeEntry( TQNetworkOperation *op ) +{ + if ( !op ) + return; + + TQUrlInfo *i = 0; + TQListViewItemIterator it( files ); + bool ok1 = FALSE, ok2 = FALSE; + for ( i = d->sortedList.first(); it.current(); ++it, i = d->sortedList.next() ) { + TQString encName = TQFileDialogPrivate::encodeFileName( + ( (TQFileDialogPrivate::File*)it.current() )->info.name() ); + if ( encName == op->arg( 0 ) ) { + d->pendingItems.removeRef( (TQFileDialogPrivate::File*)it.current() ); + delete ( (TQFileDialogPrivate::File*)it.current() )->i; + delete it.current(); + ok1 = TRUE; + } + if ( i && i->name() == op->arg( 0 ) ) { + d->sortedList.removeRef( i ); + i = d->sortedList.prev(); + ok2 = TRUE; + } + if ( ok1 && ok2 ) + break; + } +} + +void TQFileDialog::itemChanged( TQNetworkOperation *op ) +{ + if ( !op ) + return; + + TQUrlInfo *i = 0; + TQListViewItemIterator it1( files ); + bool ok1 = FALSE, ok2 = FALSE; + // first check whether the new file replaces an existing file. + for ( i = d->sortedList.first(); it1.current(); ++it1, i = d->sortedList.next() ) { + if ( ( (TQFileDialogPrivate::File*)it1.current() )->info.name() == op->arg( 1 ) ) { + delete ( (TQFileDialogPrivate::File*)it1.current() )->i; + delete it1.current(); + ok1 = TRUE; + } + if ( i && i->name() == op->arg( 1 ) ) { + d->sortedList.removeRef( i ); + i = d->sortedList.prev(); + ok2 = TRUE; + } + if ( ok1 && ok2 ) + break; + } + + i = 0; + TQListViewItemIterator it( files ); + ok1 = FALSE; + ok2 = FALSE; + for ( i = d->sortedList.first(); it.current(); ++it, i = d->sortedList.next() ) { + if ( ( (TQFileDialogPrivate::File*)it.current() )->info.name() == op->arg( 0 ) ) { + ( (TQFileDialogPrivate::File*)it.current() )->info.setName( op->arg( 1 ) ); + ok1 = TRUE; + } + if ( i && i->name() == op->arg( 0 ) ) { + i->setName( op->arg( 1 ) ); + ok2 = TRUE; + } + if ( ok1 && ok2 ) + break; + } + + resortDir(); +} + +/*! + \property TQFileDialog::infoPreview + + \brief whether the file dialog can provide preview information about + the currently selected file + + The default is FALSE. +*/ +bool TQFileDialog::isInfoPreviewEnabled() const +{ + return d->infoPreview; +} + +void TQFileDialog::setInfoPreviewEnabled( bool info ) +{ + if ( info == d->infoPreview ) + return; + d->geometryDirty = TRUE; + d->infoPreview = info; + updateGeometries(); +} + + +/*! + \property TQFileDialog::contentsPreview + + \brief whether the file dialog can provide a contents preview of the + currently selected file + + The default is FALSE. + + \sa setContentsPreview() setInfoPreviewEnabled() +*/ +// ### improve the above documentation: how is the preview done, how can I add +// support for customized preview, etc. + +bool TQFileDialog::isContentsPreviewEnabled() const +{ + return d->contentsPreview; +} + +void TQFileDialog::setContentsPreviewEnabled( bool contents ) +{ + if ( contents == d->contentsPreview ) + return; + d->geometryDirty = TRUE; + d->contentsPreview = contents; + updateGeometries(); +} + + +/*! + Sets the widget to be used for displaying information about the file + to the widget \a w and a preview of that information to the + TQFilePreview \a preview. + + Normally you would create a preview widget that derives from both TQWidget and + TQFilePreview, so you should pass the same widget twice. If you + don't, you must remember to delete the preview object in order to + avoid memory leaks. + + \code + class Preview : public TQLabel, public TQFilePreview + { + public: + Preview( TQWidget *parent=0 ) : TQLabel( parent ) {} + + void previewUrl( const TQUrl &u ) + { + TQString path = u.path(); + TQPixmap pix( path ); + if ( pix.isNull() ) + setText( "This is not a pixmap" ); + else + setText( "This is a pixmap" ); + } + }; + + //... + + int main( int argc, char** argv ) + { + Preview* p = new Preview; + + TQFileDialog* fd = new TQFileDialog( this ); + fd->setInfoPreviewEnabled( TRUE ); + fd->setInfoPreview( p, p ); + fd->setPreviewMode( TQFileDialog::Info ); + fd->show(); + } + + \endcode + + \sa setContentsPreview(), setInfoPreviewEnabled(), setPreviewMode() + +*/ + +void TQFileDialog::setInfoPreview( TQWidget *w, TQFilePreview *preview ) +{ + if ( !w || !preview ) + return; + + if ( d->infoPreviewWidget ) { + d->preview->removeWidget( d->infoPreviewWidget ); + delete d->infoPreviewWidget; + } + d->infoPreviewWidget = w; + d->infoPreviewer = preview; + w->reparent( d->preview, 0, TQPoint( 0, 0 ) ); +} + +/*! + Sets the widget to be used for displaying the contents of the file + to the widget \a w and a preview of those contents to the + TQFilePreview \a preview. + + Normally you would create a preview widget that derives from both TQWidget and + TQFilePreview, so you should pass the same widget twice. If you + don't, you must remember to delete the preview object in order to + avoid memory leaks. + + \code + class Preview : public TQLabel, public TQFilePreview + { + public: + Preview( TQWidget *parent=0 ) : TQLabel( parent ) {} + + void previewUrl( const TQUrl &u ) + { + TQString path = u.path(); + TQPixmap pix( path ); + if ( pix.isNull() ) + setText( "This is not a pixmap" ); + else + setPixmap( pix ); + } + }; + + //... + + int main( int argc, char** argv ) + { + Preview* p = new Preview; + + TQFileDialog* fd = new TQFileDialog( this ); + fd->setContentsPreviewEnabled( TRUE ); + fd->setContentsPreview( p, p ); + fd->setPreviewMode( TQFileDialog::Contents ); + fd->show(); + } + \endcode + + \sa setContentsPreviewEnabled(), setInfoPreview(), setPreviewMode() +*/ + +void TQFileDialog::setContentsPreview( TQWidget *w, TQFilePreview *preview ) +{ + if ( !w || !preview ) + return; + + if ( d->contentsPreviewWidget ) { + d->preview->removeWidget( d->contentsPreviewWidget ); + delete d->contentsPreviewWidget; + } + d->contentsPreviewWidget = w; + d->contentsPreviewer = preview; + w->reparent( d->preview, 0, TQPoint( 0, 0 ) ); +} + +/*! + Re-sorts the displayed directory. + + \sa rereadDir() +*/ + +void TQFileDialog::resortDir() +{ + d->mimeTypeTimer->stop(); + d->pendingItems.clear(); + + TQFileDialogPrivate::File *item = 0; + TQFileDialogPrivate::MCItem *item2 = 0; + + d->sortedList.sort(); + + if ( files->childCount() > 0 || d->moreFiles->count() > 0 ) { + d->moreFiles->clear(); + files->clear(); + d->last = 0; + files->setSorting( -1 ); + } + + TQUrlInfo *i = sortAscending ? d->sortedList.first() : d->sortedList.last(); + for ( ; i; i = sortAscending ? d->sortedList.next() : d->sortedList.prev() ) { + item = new TQFileDialogPrivate::File( d, i, files ); + item2 = new TQFileDialogPrivate::MCItem( d->moreFiles, item, item2 ); + item->i = item2; + d->pendingItems.append( item ); + if ( d->mode == ExistingFiles && item->info.isDir() || + ( isDirectoryMode( d->mode ) && item->info.isFile() ) ) { + item->setSelectable( FALSE ); + item2->setSelectable( FALSE ); + } + } + + // ##### As the TQFileIconProvider only support TQFileInfo and no + // TQUrlInfo it can be only used for local files at the moment. In + // 3.0 we have to change the API of TQFileIconProvider to work on + // TQUrlInfo so that also remote filesystems can be show mime-type + // specific icons. + if ( d->url.isLocalFile() ) + d->mimeTypeTimer->start( 0 ); +} + +/*! + Stops the current copy operation. +*/ + +void TQFileDialog::stopCopy() +{ + if ( d->ignoreStop ) + return; + + d->url.blockSignals( TRUE ); + d->url.stop(); + if ( d->progressDia ) { + d->ignoreStop = TRUE; + TQTimer::singleShot( 100, this, SLOT( removeProgressDia() ) ); + } + d->url.blockSignals( FALSE ); +} + +/*! + \internal +*/ + +void TQFileDialog::removeProgressDia() +{ + if ( d->progressDia ) + delete d->progressDia; + d->progressDia = 0; +} + +/*! + \internal +*/ + +void TQFileDialog::doMimeTypeLookup() +{ + if ( !iconProvider() ) { + d->pendingItems.clear(); + d->mimeTypeTimer->stop(); + return; + } + + d->mimeTypeTimer->stop(); + if ( d->pendingItems.count() == 0 ) { + return; + } + + TQRect r; + TQFileDialogPrivate::File *item = d->pendingItems.first(); + if ( item ) { + TQFileInfo fi; + if ( d->url.isLocalFile() ) { + fi.setFile( TQUrl( d->url.path(), TQFileDialogPrivate::encodeFileName( item->info.name() ) ).path( FALSE ) ); + } else + fi.setFile( item->info.name() ); // ##### + const TQPixmap *p = iconProvider()->pixmap( fi ); + if ( p && p != item->pixmap( 0 ) && + ( !item->pixmap( 0 ) || p->serialNumber() != item->pixmap( 0 )->serialNumber() ) && + p != fifteenTransparentPixels ) { + item->hasMimePixmap = TRUE; + + // evil hack to avoid much too much repaints! + TQGuardedPtr<TQFileDialog> that( this ); // this may be deleted by an event handler + qApp->processEvents(); + if ( that.isNull() ) + return; + files->setUpdatesEnabled( FALSE ); + files->viewport()->setUpdatesEnabled( FALSE ); + if ( item != d->pendingItems.first() ) + return; + item->setPixmap( 0, *p ); + qApp->processEvents(); + if ( that.isNull() ) + return; + files->setUpdatesEnabled( TRUE ); + files->viewport()->setUpdatesEnabled( TRUE ); + + if ( files->isVisible() ) { + TQRect ir( files->itemRect( item ) ); + if ( ir != TQRect( 0, 0, -1, -1 ) ) { + r = r.unite( ir ); + } + } else { + TQRect ir( d->moreFiles->itemRect( item->i ) ); + if ( ir != TQRect( 0, 0, -1, -1 ) ) { + r = r.unite( ir ); + } + } + } + if ( d->pendingItems.count() ) + d->pendingItems.removeFirst(); + } + + if ( d->moreFiles->isVisible() ) { + d->moreFiles->viewport()->repaint( r, FALSE ); + } else { + files->viewport()->repaint( r, FALSE ); + } + + if ( d->pendingItems.count() ) + d->mimeTypeTimer->start( 0 ); + else if ( d->moreFiles->isVisible() ) + d->moreFiles->triggerUpdate( TRUE ); +} + +/*! + If \a b is TRUE then all the files in the current directory are selected; + otherwise, they are deselected. +*/ + +void TQFileDialog::selectAll( bool b ) +{ + if ( d->mode != ExistingFiles ) + return; + d->moreFiles->selectAll( b ); + files->selectAll( b ); +} + +void TQFileDialog::goBack() +{ + if ( !d->goBack || !d->goBack->isEnabled() ) + return; + d->history.remove( d->history.last() ); + if ( d->history.count() < 2 ) + d->goBack->setEnabled( FALSE ); + setUrl( d->history.last() ); +} + +// a class with wonderfully inflexible flexibility. why doesn't it +// just subclass TQWidget in the first place? 'you have to derive your +// preview widget from TQWidget and from this class' indeed. + +/*! + \class TQFilePreview qfiledialog.h + \ingroup misc + \brief The TQFilePreview class provides file previewing in TQFileDialog. + + This class is an abstract base class which is used to implement + widgets that can display a preview of a file in a TQFileDialog. + + You must derive the preview widget from both TQWidget and from this + class. Then you must reimplement this class's previewUrl() function, + which is called by the file dialog if the preview of a file + (specified as a URL) should be shown. + + See also TQFileDialog::setPreviewMode(), TQFileDialog::setContentsPreview(), + TQFileDialog::setInfoPreview(), TQFileDialog::setInfoPreviewEnabled(), + TQFileDialog::setContentsPreviewEnabled(). + + For an example of a preview widget see qt/examples/qdir/qdir.cpp. +*/ + +/*! + Constructs the TQFilePreview. +*/ + +TQFilePreview::TQFilePreview() +{ +} + +/*! + \fn void TQFilePreview::previewUrl( const TQUrl &url ) + + This function is called by TQFileDialog if a preview + for the \a url should be shown. Reimplement this + function to provide file previewing. +*/ + + +#include "qfiledialog.moc" + +#endif diff --git a/src/dialogs/qfiledialog.h b/src/dialogs/qfiledialog.h new file mode 100644 index 000000000..0861aa1a7 --- /dev/null +++ b/src/dialogs/qfiledialog.h @@ -0,0 +1,347 @@ +/**************************************************************************** +** +** Definition of TQFileDialog class +** +** Created : 950428 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQFILEDIALOG_H +#define TQFILEDIALOG_H + +class TQPushButton; +class TQButton; +class TQLabel; +class TQWidget; +class TQFileDialog; +class TQTimer; +class TQNetworkOperation; +class TQLineEdit; +class TQListViewItem; +class TQListBoxItem; +class TQFileDialogPrivate; +class TQFileDialogTQFileListView; + +#ifndef QT_H +#include "qdir.h" +#include "qdialog.h" +#include "qurloperator.h" +#include "qurlinfo.h" +#endif // QT_H + +#if __GNUC__ - 0 > 3 +#pragma GCC system_header +#endif + +#ifndef QT_NO_FILEDIALOG + +class Q_EXPORT TQFileIconProvider : public TQObject +{ + Q_OBJECT +public: + TQFileIconProvider( TQObject * parent = 0, const char* name = 0 ); + virtual const TQPixmap * pixmap( const TQFileInfo & ); + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQFileIconProvider( const TQFileIconProvider & ); + TQFileIconProvider& operator=( const TQFileIconProvider & ); +#endif +}; + +class Q_EXPORT TQFilePreview +{ +public: + TQFilePreview(); + virtual void previewUrl( const TQUrl &url ) = 0; + +}; + +class Q_EXPORT TQFileDialog : public TQDialog +{ + Q_OBJECT + Q_ENUMS( Mode ViewMode PreviewMode ) + // ##### Why are this read-only properties ? + Q_PROPERTY( TQString selectedFile READ selectedFile ) + Q_PROPERTY( TQString selectedFilter READ selectedFilter ) + Q_PROPERTY( TQStringList selectedFiles READ selectedFiles ) + // #### Should not we be able to set the path ? + Q_PROPERTY( TQString dirPath READ dirPath ) + Q_PROPERTY( bool showHiddenFiles READ showHiddenFiles WRITE setShowHiddenFiles ) + Q_PROPERTY( Mode mode READ mode WRITE setMode ) + Q_PROPERTY( ViewMode viewMode READ viewMode WRITE setViewMode ) + Q_PROPERTY( PreviewMode previewMode READ previewMode WRITE setPreviewMode ) + Q_PROPERTY( bool infoPreview READ isInfoPreviewEnabled WRITE setInfoPreviewEnabled ) + Q_PROPERTY( bool contentsPreview READ isContentsPreviewEnabled WRITE setContentsPreviewEnabled ) + +public: + TQFileDialog( const TQString& dirName, const TQString& filter = TQString::null, + TQWidget* parent=0, const char* name=0, bool modal = FALSE ); + TQFileDialog( TQWidget* parent=0, const char* name=0, bool modal = FALSE ); + ~TQFileDialog(); + + // recommended static functions + + static TQString getOpenFileName( const TQString &initially = TQString::null, + const TQString &filter = TQString::null, + TQWidget *parent = 0, const char* name = 0, + const TQString &caption = TQString::null, + TQString *selectedFilter = 0, + bool resolveSymlinks = TRUE); + static TQString getSaveFileName( const TQString &initially = TQString::null, + const TQString &filter = TQString::null, + TQWidget *parent = 0, const char* name = 0, + const TQString &caption = TQString::null, + TQString *selectedFilter = 0, + bool resolveSymlinks = TRUE); + static TQString getExistingDirectory( const TQString &dir = TQString::null, + TQWidget *parent = 0, + const char* name = 0, + const TQString &caption = TQString::null, + bool dirOnly = TRUE, + bool resolveSymlinks = TRUE); + static TQStringList getOpenFileNames( const TQString &filter= TQString::null, + const TQString &dir = TQString::null, + TQWidget *parent = 0, + const char* name = 0, + const TQString &caption = TQString::null, + TQString *selectedFilter = 0, + bool resolveSymlinks = TRUE); + + // other static functions + + static void setIconProvider( TQFileIconProvider * ); + static TQFileIconProvider * iconProvider(); + + // non-static function for special needs + + TQString selectedFile() const; + TQString selectedFilter() const; + virtual void setSelectedFilter( const TQString& ); + virtual void setSelectedFilter( int ); + + void setSelection( const TQString &); + + void selectAll( bool b ); + + TQStringList selectedFiles() const; + + TQString dirPath() const; + + void setDir( const TQDir & ); + const TQDir *dir() const; + + void setShowHiddenFiles( bool s ); + bool showHiddenFiles() const; + + void rereadDir(); + void resortDir(); + + enum Mode { AnyFile, ExistingFile, Directory, ExistingFiles, DirectoryOnly }; + void setMode( Mode ); + Mode mode() const; + + enum ViewMode { Detail, List }; + enum PreviewMode { NoPreview, Contents, Info }; + void setViewMode( ViewMode m ); + ViewMode viewMode() const; + void setPreviewMode( PreviewMode m ); + PreviewMode previewMode() const; + + bool eventFilter( TQObject *, TQEvent * ); + + bool isInfoPreviewEnabled() const; + bool isContentsPreviewEnabled() const; + void setInfoPreviewEnabled( bool ); + void setContentsPreviewEnabled( bool ); + + void setInfoPreview( TQWidget *w, TQFilePreview *preview ); + void setContentsPreview( TQWidget *w, TQFilePreview *preview ); + + TQUrl url() const; + + void addFilter( const TQString &filter ); + +public slots: + void done( int ); + void setDir( const TQString& ); + void setUrl( const TQUrlOperator &url ); + void setFilter( const TQString& ); + void setFilters( const TQString& ); + void setFilters( const char ** ); + void setFilters( const TQStringList& ); + +protected: + void resizeEvent( TQResizeEvent * ); + void keyPressEvent( TQKeyEvent * ); + + void addWidgets( TQLabel *, TQWidget *, TQPushButton * ); + void addToolButton( TQButton *b, bool separator = FALSE ); + void addLeftWidget( TQWidget *w ); + void addRightWidget( TQWidget *w ); + +signals: + void fileHighlighted( const TQString& ); + void fileSelected( const TQString& ); + void filesSelected( const TQStringList& ); + void dirEntered( const TQString& ); + void filterSelected( const TQString& ); + +private slots: + void detailViewSelectionChanged(); + void listBoxSelectionChanged(); + void changeMode( int ); + void fileNameEditReturnPressed(); + void stopCopy(); + void removeProgressDia(); + + void fileSelected( int ); + void fileHighlighted( int ); + void dirSelected( int ); + void pathSelected( int ); + + void updateFileNameEdit( TQListViewItem *); + void selectDirectoryOrFile( TQListViewItem * ); + void popupContextMenu( TQListViewItem *, const TQPoint &, int ); + void popupContextMenu( TQListBoxItem *, const TQPoint & ); + void updateFileNameEdit( TQListBoxItem *); + void selectDirectoryOrFile( TQListBoxItem * ); + void fileNameEditDone(); + + void okClicked(); + void filterClicked(); // not used + void cancelClicked(); + + void cdUpClicked(); + void newFolderClicked(); + + void fixupNameEdit(); + + void doMimeTypeLookup(); + + void updateGeometries(); + void modeButtonsDestroyed(); + void urlStart( TQNetworkOperation *op ); + void urlFinished( TQNetworkOperation *op ); + void dataTransferProgress( int bytesDone, int bytesTotal, TQNetworkOperation * ); + void insertEntry( const TQValueList<TQUrlInfo> &fi, TQNetworkOperation *op ); + void removeEntry( TQNetworkOperation * ); + void createdDirectory( const TQUrlInfo &info, TQNetworkOperation * ); + void itemChanged( TQNetworkOperation * ); + void goBack(); + +private: + enum PopupAction { + PA_Open = 0, + PA_Delete, + PA_Rename, + PA_SortName, + PA_SortSize, + PA_SortType, + PA_SortDate, + PA_SortUnsorted, + PA_Cancel, + PA_Reload, + PA_Hidden + }; + + void init(); + bool trySetSelection( bool isDir, const TQUrlOperator &, bool ); + void deleteFile( const TQString &filename ); + void popupContextMenu( const TQString &filename, bool withSort, + PopupAction &action, const TQPoint &p ); + void updatePreviews( const TQUrl &u ); + + TQDir reserved; // was cwd + TQString fileName; + + friend class TQFileDialogTQFileListView; + friend class TQFileListBox; + + TQFileDialogPrivate *d; + TQFileDialogTQFileListView *files; + + TQLineEdit *nameEdit; // also filter + TQPushButton *okB; + TQPushButton *cancelB; + +#if defined(Q_WS_WIN) + static TQString winGetOpenFileName( const TQString &initialSelection, + const TQString &filter, + TQString* workingDirectory, + TQWidget *parent = 0, + const char* name = 0, + const TQString& caption = TQString::null, + TQString* selectedFilter = 0 ); + static TQString winGetSaveFileName( const TQString &initialSelection, + const TQString &filter, + TQString* workingDirectory, + TQWidget *parent = 0, + const char* name = 0, + const TQString& caption = TQString::null, + TQString* selectedFilter = 0 ); + static TQStringList winGetOpenFileNames( const TQString &filter, + TQString* workingDirectory, + TQWidget *parent = 0, + const char* name = 0, + const TQString& caption = TQString::null, + TQString* selectedFilter = 0 ); + static TQString winGetExistingDirectory( const TQString &initialDirectory, + TQWidget* parent = 0, + const char* name = 0, + const TQString& caption = TQString::null); + static TQString resolveLinkFile( const TQString& linkfile ); +#endif +#if defined(Q_WS_MACX) || defined(Q_WS_MAC9) + static TQString macGetSaveFileName( const TQString &, const TQString &, + TQString *, TQWidget *, const char*, + const TQString&, TQString *); + static TQStringList macGetOpenFileNames( const TQString &, TQString*, + TQWidget *, const char *, + const TQString&, TQString *, + bool = TRUE, bool = FALSE ); +#endif + + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQFileDialog( const TQFileDialog & ); + TQFileDialog &operator=( const TQFileDialog & ); +#endif +}; + +#endif + +#endif // TQFILEDIALOG_H diff --git a/src/dialogs/qfontdialog.cpp b/src/dialogs/qfontdialog.cpp new file mode 100644 index 000000000..995d49621 --- /dev/null +++ b/src/dialogs/qfontdialog.cpp @@ -0,0 +1,841 @@ +/**************************************************************************** +** +** Implementation of TQFontDialog +** +** Created : 970605 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qwindowdefs.h" + +#ifndef QT_NO_FONTDIALOG + +#include "qfontdialog.h" + +#include "qlineedit.h" +#include "qlistbox.h" +#include "qpushbutton.h" +#include "qcheckbox.h" +#include "qcombobox.h" +#include "qlayout.h" +#include "qvgroupbox.h" +#include "qhgroupbox.h" +#include "qlabel.h" +#include "qapplication.h" +#include "qfontdatabase.h" +#include "qstyle.h" +#include <private/qfontdata_p.h> +#include <qvalidator.h> + +#ifdef Q_WS_X11 +#include "private/qtkdeintegration_x11_p.h" +#endif + +/*! + \class TQFontDialog qfontdialog.h + \ingroup dialogs + \mainclass + \brief The TQFontDialog class provides a dialog widget for selecting a font. + + The usual way to use this class is to call one of the static convenience + functions, e.g. getFont(). + + Examples: + + \code + bool ok; + TQFont font = TQFontDialog::getFont( + &ok, TQFont( "Helvetica [Cronyx]", 10 ), this ); + if ( ok ) { + // font is set to the font the user selected + } else { + // the user canceled the dialog; font is set to the initial + // value, in this case Helvetica [Cronyx], 10 + } + \endcode + + The dialog can also be used to set a widget's font directly: + \code + myWidget.setFont( TQFontDialog::getFont( 0, myWidget.font() ) ); + \endcode + If the user clicks OK the font they chose will be used for myWidget, + and if they click Cancel the original font is used. + + \sa TQFont TQFontInfo TQFontMetrics + + <img src=qfontdlg-w.png> +*/ + +class TQFontDialogPrivate +{ +public: + TQFontDialogPrivate() : script( TQFontPrivate::defaultScript ) {}; + TQLabel * familyAccel; + TQLineEdit * familyEdit; + TQListBox * familyList; + + TQLabel * styleAccel; + TQLineEdit * styleEdit; + TQListBox * styleList; + + TQLabel * sizeAccel; + TQLineEdit * sizeEdit; + TQListBox * sizeList; + + TQVGroupBox * effects; + TQCheckBox * strikeout; + TQCheckBox * underline; + TQComboBox * color; + + TQHGroupBox * sample; + TQLineEdit * sampleEdit; + + TQLabel * scriptAccel; + TQComboBox * scriptCombo; + + TQPushButton * ok; + TQPushButton * cancel; + + TQBoxLayout * buttonLayout; + TQBoxLayout * effectsLayout; + TQBoxLayout * sampleLayout; + TQBoxLayout * sampleEditLayout; + + TQFontDatabase fdb; + + TQString family; + TQFont::Script script; + TQString style; + int size; + + bool smoothScalable; +}; + + +/*! + \internal + Constructs a standard font dialog. + + Use setFont() to set the initial font attributes. + + The \a parent, \a name, \a modal and \a f parameters are passed to + the TQDialog constructor. + + \sa getFont() +*/ + +TQFontDialog::TQFontDialog( TQWidget *parent, const char *name, + bool modal, WFlags f ) + : TQDialog( parent, name, modal, f ) +{ + setSizeGripEnabled( TRUE ); + d = new TQFontDialogPrivate; + // grid + d->familyEdit = new TQLineEdit( this, "font family I" ); + d->familyEdit->setReadOnly( TRUE ); + d->familyList = new TQListBox( this, "font family II" ); + d->familyEdit->setFocusProxy( d->familyList ); + + d->familyAccel + = new TQLabel( d->familyList, tr("&Font"), this, "family accelerator" ); + d->familyAccel->setIndent( 2 ); + + d->styleEdit = new TQLineEdit( this, "font style I" ); + d->styleEdit->setReadOnly( TRUE ); + d->styleList = new TQListBox( this, "font style II" ); + d->styleEdit->setFocusProxy( d->styleList ); + + d->styleAccel + = new TQLabel( d->styleList, tr("Font st&yle"), this, "style accelerator" ); + d->styleAccel->setIndent( 2 ); + + d->sizeEdit = new TQLineEdit( this, "font size I" ); + d->sizeEdit->setFocusPolicy( ClickFocus ); + TQIntValidator *validator = new TQIntValidator( 1, 512, this ); + d->sizeEdit->setValidator( validator ); + d->sizeList = new TQListBox( this, "font size II" ); + + d->sizeAccel + = new TQLabel ( d->sizeEdit, tr("&Size"), this, "size accelerator" ); + d->sizeAccel->setIndent( 2 ); + + // effects box + d->effects = new TQVGroupBox( tr("Effects"), this, "font effects" ); + d->strikeout = new TQCheckBox( d->effects, "strikeout on/off" ); + d->strikeout->setText( tr("Stri&keout") ); + d->underline = new TQCheckBox( d->effects, "underline on/off" ); + d->underline->setText( tr("&Underline") ); + + d->sample = new TQHGroupBox( tr("Sample"), this, "sample text" ); + d->sampleEdit = new TQLineEdit( d->sample, "r/w sample text" ); + d->sampleEdit->setSizePolicy( TQSizePolicy( TQSizePolicy::Ignored, TQSizePolicy::Ignored) ); + d->sampleEdit->setAlignment( AlignCenter ); + // Note that the sample text is *not* translated with tr(), as the + // characters used depend on the charset encoding. + d->sampleEdit->setText( "AaBbYyZz" ); + + d->scriptCombo = new TQComboBox( FALSE, this, "font encoding" ); + + d->scriptAccel + = new TQLabel( d->scriptCombo, tr("Scr&ipt"), this,"encoding label"); + d->scriptAccel->setIndent( 2 ); + + d->size = 0; + d->smoothScalable = FALSE; + + connect( d->scriptCombo, SIGNAL(activated(int)), + SLOT(scriptHighlighted(int)) ); + connect( d->familyList, SIGNAL(highlighted(int)), + SLOT(familyHighlighted(int)) ); + connect( d->styleList, SIGNAL(highlighted(int)), + SLOT(styleHighlighted(int)) ); + connect( d->sizeList, SIGNAL(highlighted(const TQString&)), + SLOT(sizeHighlighted(const TQString&)) ); + connect( d->sizeEdit, SIGNAL(textChanged(const TQString&)), + SLOT(sizeChanged(const TQString&)) ); + + connect( d->strikeout, SIGNAL(clicked()), + SLOT(updateSample()) ); + connect( d->underline, SIGNAL(clicked()), + SLOT(updateSample()) ); + + (void)d->familyList->sizeHint(); + (void)d->styleList->sizeHint(); + (void)d->sizeList->sizeHint(); + + for (int i = 0; i < TQFont::NScripts; i++) { + TQString scriptname = TQFontDatabase::scriptName((TQFont::Script) i); + if ( !scriptname.isEmpty() ) + d->scriptCombo->insertItem( scriptname ); + } + + updateFamilies(); + if ( d->familyList->count() != 0 ) + d->familyList->setCurrentItem( 0 ); + + // grid layout + TQGridLayout * mainGrid = new TQGridLayout( this, 9, 6, 12, 0 ); + + mainGrid->addWidget( d->familyAccel, 0, 0 ); + mainGrid->addWidget( d->familyEdit, 1, 0 ); + mainGrid->addWidget( d->familyList, 2, 0 ); + + mainGrid->addWidget( d->styleAccel, 0, 2 ); + mainGrid->addWidget( d->styleEdit, 1, 2 ); + mainGrid->addWidget( d->styleList, 2, 2 ); + + mainGrid->addWidget( d->sizeAccel, 0, 4 ); + mainGrid->addWidget( d->sizeEdit, 1, 4 ); + mainGrid->addWidget( d->sizeList, 2, 4 ); + + mainGrid->setColStretch( 0, 38 ); + mainGrid->setColStretch( 2, 24 ); + mainGrid->setColStretch( 4, 10 ); + + mainGrid->addColSpacing( 1, 6 ); + mainGrid->addColSpacing( 3, 6 ); + mainGrid->addColSpacing( 5, 6 ); + + mainGrid->addRowSpacing( 3, 12 ); + + mainGrid->addWidget( d->effects, 4, 0 ); + + mainGrid->addMultiCellWidget( d->sample, 4, 7, 2, 4 ); + + mainGrid->addWidget( d->scriptAccel, 5, 0 ); + mainGrid->addRowSpacing( 6, 2 ); + mainGrid->addWidget( d->scriptCombo, 7, 0 ); + + mainGrid->addRowSpacing( 8, 12 ); + + TQHBoxLayout *buttonBox = new TQHBoxLayout; + mainGrid->addMultiCell( buttonBox, 9, 9, 0, 4 ); + + buttonBox->addStretch( 1 ); + TQString okt = modal ? tr("OK") : tr("Apply"); + d->ok = new TQPushButton( okt, this, "accept font selection" ); + buttonBox->addWidget( d->ok ); + if ( modal ) + connect( d->ok, SIGNAL(clicked()), SLOT(accept()) ); + d->ok->setDefault( TRUE ); + + buttonBox->addSpacing( 12 ); + + TQString cancelt = modal ? tr("Cancel") : tr("Close"); + d->cancel = new TQPushButton( cancelt, this, "cancel/close" ); + buttonBox->addWidget( d->cancel ); + connect( d->cancel, SIGNAL(clicked()), SLOT(reject()) ); + + resize( 500, 360 ); + + d->sizeEdit->installEventFilter( this ); + d->familyList->installEventFilter( this ); + d->styleList->installEventFilter( this ); + d->sizeList->installEventFilter( this ); + + d->familyList->setFocus(); +} + +/*! + \internal + Destroys the font dialog and frees up its storage. +*/ + +TQFontDialog::~TQFontDialog() +{ + delete d; + d = 0; +} + +/*! + Executes a modal font dialog and returns a font. + + If the user clicks OK, the selected font is returned. If the user + clicks Cancel, the \a initial font is returned. + + The dialog is called \a name, with the parent \a parent. + \a initial is the initially selected font. + If the \a ok parameter is not-null, \e *\a ok is set to TRUE if the + user clicked OK, and set to FALSE if the user clicked Cancel. + + This static function is less flexible than the full TQFontDialog + object, but is convenient and easy to use. + + Examples: + \code + bool ok; + TQFont font = TQFontDialog::getFont( &ok, TQFont( "Times", 12 ), this ); + if ( ok ) { + // font is set to the font the user selected + } else { + // the user canceled the dialog; font is set to the initial + // value, in this case Times, 12. + } + \endcode + + The dialog can also be used to set a widget's font directly: + \code + myWidget.setFont( TQFontDialog::getFont( 0, myWidget.font() ) ); + \endcode + In this example, if the user clicks OK the font they chose will be + used, and if they click Cancel the original font is used. +*/ +TQFont TQFontDialog::getFont( bool *ok, const TQFont &initial, + TQWidget *parent, const char* name) +{ + return getFont( ok, &initial, parent, name ); +} + +/*! + \overload + + Executes a modal font dialog and returns a font. + + If the user clicks OK, the selected font is returned. If the user + clicks Cancel, the TQt default font is returned. + + The dialog is called \a name, with parent \a parent. + If the \a ok parameter is not-null, \e *\a ok is set to TRUE if the + user clicked OK, and FALSE if the user clicked Cancel. + + This static function is less functional than the full TQFontDialog + object, but is convenient and easy to use. + + Example: + \code + bool ok; + TQFont font = TQFontDialog::getFont( &ok, this ); + if ( ok ) { + // font is set to the font the user selected + } else { + // the user canceled the dialog; font is set to the default + // application font, TQApplication::font() + } + \endcode + +*/ +TQFont TQFontDialog::getFont( bool *ok, TQWidget *parent,const char* name) +{ + return getFont( ok, 0, parent, name ); +} + +extern bool qt_use_native_dialogs; + +TQFont TQFontDialog::getFont( bool *ok, const TQFont *def, + TQWidget *parent, const char* name) +{ +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::getFont( ok, def, parent, name ); +#endif + TQFont result; + if ( def ) + result = *def; + + TQFontDialog *dlg = new TQFontDialog( parent, name, TRUE ); + + dlg->setFont( ( def ? *def : TQFont() ) ); +#ifndef QT_NO_WIDGET_TOPEXTRA + dlg->setCaption( tr("Select Font") ); +#endif + + bool res = (dlg->exec() == TQDialog::Accepted); + if ( res ) + result = dlg->font(); + if ( ok ) + *ok = res; + delete dlg; + return result; +} + + +/*! + \internal + An event filter to make the Up, Down, PageUp and PageDown keys work + correctly in the line edits. The source of the event is the object + \a o and the event is \a e. +*/ + +bool TQFontDialog::eventFilter( TQObject * o , TQEvent * e ) +{ + if ( e->type() == TQEvent::KeyPress) { + TQKeyEvent * k = (TQKeyEvent *)e; + if ( o == d->sizeEdit && + (k->key() == Key_Up || + k->key() == Key_Down || + k->key() == Key_Prior || + k->key() == Key_Next) ) { + + int ci = d->sizeList->currentItem(); + (void)TQApplication::sendEvent( d->sizeList, k ); + + if ( ci != d->sizeList->currentItem() && + style().styleHint(TQStyle::SH_FontDialog_SelectAssociatedText, this)) + d->sizeEdit->selectAll(); + return TRUE; + } else if ( ( o == d->familyList || o == d->styleList ) && + ( k->key() == Key_Return || k->key() == Key_Enter) ) { + k->accept(); + accept(); + return TRUE; + } + } else if ( e->type() == TQEvent::FocusIn && + style().styleHint(TQStyle::SH_FontDialog_SelectAssociatedText, this) ) { + if ( o == d->familyList ) + d->familyEdit->selectAll(); + else if ( o == d->styleList ) + d->styleEdit->selectAll(); + else if ( o == d->sizeList ) + d->sizeEdit->selectAll(); + } else if ( e->type() == TQEvent::MouseButtonPress && o == d->sizeList ) { + d->sizeEdit->setFocus(); + } + return TQDialog::eventFilter( o, e ); +} + +#ifdef Q_WS_MAC +// #define SHOW_FONTS_IN_FAMILIES +#endif + +#ifdef SHOW_FONTS_IN_FAMILIES +#include "qpainter.h" +#include <sizeedit.h> + +class TQListBoxFontText : public TQListBoxText +{ + TQFont cfont; +public: + TQListBoxFontText( const TQString & text ); + ~TQListBoxFontText() { } + + int height( const TQListBox * ) const; + int width( const TQListBox * ) const; + +protected: + void paint( TQPainter * ); +}; + +TQListBoxFontText::TQListBoxFontText( const TQString & text ) + : TQListBoxText(text), cfont(text) +{ +} + +int TQListBoxFontText::height( const TQListBox * ) const +{ + TQFontMetrics fm(cfont); + return TQMAX( fm.lineSpacing() + 2, TQApplication::globalStrut().height() ); +} + +int TQListBoxFontText::width( const TQListBox * ) const +{ + TQFontMetrics fm(cfont); + return TQMAX( fm.width( text() ) + 6, TQApplication::globalStrut().width() ); +} + +void TQListBoxFontText::paint( TQPainter *painter ) +{ + painter->save(); + painter->setFont(cfont); + TQListBoxText::paint(painter); + painter->restore(); +} + +#endif + +/*! + \internal + Updates the contents of the "font family" list box. This + function can be reimplemented if you have special retquirements. +*/ + +void TQFontDialog::updateFamilies() +{ + d->familyList->blockSignals( TRUE ); + + enum match_t { MATCH_NONE=0, MATCH_LAST_RESORT=1, MATCH_APP=2, MATCH_FALLBACK, MATCH_FAMILY=3 }; + + TQStringList familyNames = d->fdb.families(d->script); + { + // merge the unicode/unknown family list with the above list. + TQStringList l = d->fdb.families(TQFont::Unicode) + + d->fdb.families(TQFont::UnknownScript); + TQStringList::ConstIterator it = l.begin(), end = l.end(); + for (; it != end; ++it) { + if (! familyNames.contains(*it)) + familyNames << *it; + } + } + + familyNames.sort(); + + d->familyList->clear(); +#ifdef SHOW_FONTS_IN_FAMILIES + TQStringList::Iterator it = familyNames.begin(); + int idx = 0; + for( ; it != familyNames.end() ; ++it ) + d->familyList->insertItem(new TQListBoxFontText(*it), idx++); +#else + d->familyList->insertStringList( familyNames ); +#endif + + TQString foundryName1, familyName1, foundryName2, familyName2; + int bestFamilyMatch = -1; + match_t bestFamilyType = MATCH_NONE; + + TQFont f; + + // ##### do the right thing for a list of family names in the font. + TQFontDatabase::parseFontName(d->family, foundryName1, familyName1); + + TQStringList::Iterator it = familyNames.begin(); + int i = 0; + for( ; it != familyNames.end(); ++it, ++i ) { + + TQFontDatabase::parseFontName(*it, foundryName2, familyName2); + + //try to match.. + if ( familyName1 == familyName2 ) { + bestFamilyType = MATCH_FAMILY; + if ( foundryName1 == foundryName2 ) { + bestFamilyMatch = i; + break; + } + if ( bestFamilyMatch < MATCH_FAMILY ) + bestFamilyMatch = i; + } + + //and try some fall backs + match_t type = MATCH_NONE; + if ( bestFamilyType <= MATCH_NONE && familyName2 == f.lastResortFamily() ) + type = MATCH_LAST_RESORT; + if ( bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.family() ) + type = MATCH_APP; + // ### add fallback for script + if ( type != MATCH_NONE ) { + bestFamilyType = type; + bestFamilyMatch = i; + } + } + + if (i != -1 && bestFamilyType != MATCH_NONE) + d->familyList->setCurrentItem(bestFamilyMatch); + else + d->familyList->setCurrentItem( 0 ); + d->familyEdit->setText( d->familyList->currentText() ); + if ( style().styleHint(TQStyle::SH_FontDialog_SelectAssociatedText, this) && + d->familyList->hasFocus() ) + d->familyEdit->selectAll(); + + d->familyList->blockSignals( FALSE ); + updateStyles(); +} + +/*! + \internal + Updates the contents of the "font style" list box. This + function can be reimplemented if you have special retquirements. +*/ + +void TQFontDialog::updateStyles() +{ + d->styleList->blockSignals( TRUE ); + + d->styleList->clear(); + + TQStringList styles = d->fdb.styles( d->familyList->currentText() ); + + if ( styles.isEmpty() ) { + d->styleEdit->clear(); + d->smoothScalable = FALSE; + } else { + d->styleList->insertStringList( styles ); + + if ( !d->style.isEmpty() ) { + bool found = FALSE; + bool first = TRUE; + TQString cstyle = d->style; + redo: + for ( int i = 0 ; i < (int)d->styleList->count() ; i++ ) { + if ( cstyle == d->styleList->text(i) ) { + d->styleList->setCurrentItem( i ); + found = TRUE; + break; + } + } + if (!found && first) { + if (cstyle.contains("Italic")) { + cstyle.replace("Italic", "Oblique"); + first = FALSE; + goto redo; + } else if (cstyle.contains("Oblique")) { + cstyle.replace("Oblique", "Italic"); + first = FALSE; + goto redo; + } + } + if ( !found ) + d->styleList->setCurrentItem( 0 ); + } + + d->styleEdit->setText( d->styleList->currentText() ); + if ( style().styleHint(TQStyle::SH_FontDialog_SelectAssociatedText, this) && + d->styleList->hasFocus() ) + d->styleEdit->selectAll(); + + d->smoothScalable = d->fdb.isSmoothlyScalable( d->familyList->currentText(), d->styleList->currentText() ); + } + + d->styleList->blockSignals( FALSE ); + + updateSizes(); +} + +/*! + \internal + Updates the contents of the "font size" list box. This + function can be reimplemented if you have special retquirements. +*/ + +void TQFontDialog::updateSizes() +{ + d->sizeList->blockSignals( TRUE ); + + d->sizeList->clear(); + + if ( !d->familyList->currentText().isEmpty() ) { + TQValueList<int> sizes = d->fdb.pointSizes( d->familyList->currentText(), d->styleList->currentText() ); + + int i = 0; + bool found = FALSE; + for( TQValueList<int>::iterator it = sizes.begin() ; it != sizes.end(); ++it ) { + d->sizeList->insertItem( TQString::number( *it ) ); + if ( !found && *it >= d->size ) { + d->sizeList->setCurrentItem( i ); + found = TRUE; + } + ++i; + } + if ( !found ) { + // we request a size bigger than the ones in the list, select the biggest one + d->sizeList->setCurrentItem( d->sizeList->count() - 1 ); + } + + d->sizeEdit->blockSignals( TRUE ); + d->sizeEdit->setText( ( d->smoothScalable ? TQString::number( d->size ) : d->sizeList->currentText() ) ); + if ( style().styleHint(TQStyle::SH_FontDialog_SelectAssociatedText, this) && + d->sizeList->hasFocus() ) + d->sizeEdit->selectAll(); + d->sizeEdit->blockSignals( FALSE ); + } else { + d->sizeEdit->clear(); + } + + d->sizeList->blockSignals( FALSE ); + updateSample(); +} + +void TQFontDialog::updateSample() +{ + if ( d->familyList->currentText().isEmpty() ) + d->sampleEdit->clear(); + else + d->sampleEdit->setFont( font() ); +} + +/*! + \internal +*/ +void TQFontDialog::scriptHighlighted( int index ) +{ + d->script = (TQFont::Script)index; + d->sampleEdit->setText( d->fdb.scriptSample( d->script ) ); + updateFamilies(); +} + +/*! + \internal +*/ +void TQFontDialog::familyHighlighted( int i ) +{ + d->family = d->familyList->text( i ); + d->familyEdit->setText( d->family ); + if ( style().styleHint(TQStyle::SH_FontDialog_SelectAssociatedText, this) && + d->familyList->hasFocus() ) + d->familyEdit->selectAll(); + + updateStyles(); +} + + +/*! + \internal +*/ + +void TQFontDialog::styleHighlighted( int index ) +{ + TQString s = d->styleList->text( index ); + d->styleEdit->setText( s ); + if ( style().styleHint(TQStyle::SH_FontDialog_SelectAssociatedText, this) && + d->styleList->hasFocus() ) + d->styleEdit->selectAll(); + + d->style = s; + + updateSizes(); +} + + +/*! + \internal +*/ + +void TQFontDialog::sizeHighlighted( const TQString &s ) +{ + d->sizeEdit->setText( s ); + if ( style().styleHint(TQStyle::SH_FontDialog_SelectAssociatedText, this) && + d->sizeEdit->hasFocus() ) + d->sizeEdit->selectAll(); + + d->size = s.toInt(); + updateSample(); +} + +/*! + \internal + This slot is called if the user changes the font size. + The size is passed in the \a s argument as a \e string. +*/ + +void TQFontDialog::sizeChanged( const TQString &s ) +{ + // no need to check if the conversion is valid, since we have an TQIntValidator in the size edit + int size = s.toInt(); + if ( d->size == size ) + return; + + d->size = size; + if ( d->sizeList->count() != 0 ) { + int i; + for ( i = 0 ; i < (int)d->sizeList->count() - 1 ; i++ ) { + if ( d->sizeList->text(i).toInt() >= d->size ) + break; + } + d->sizeList->blockSignals( TRUE ); + d->sizeList->setCurrentItem( i ); + d->sizeList->blockSignals( FALSE ); + } + updateSample(); +} + +/*! + \internal + Sets the font highlighted in the TQFontDialog to font \a f. + + \sa font() +*/ + +void TQFontDialog::setFont( const TQFont &f ) +{ + d->family = f.family(); + d->style = d->fdb.styleString( f ); + d->size = f.pointSize(); + if ( d->size == -1 ) { + TQFontInfo fi( f ); + d->size = fi.pointSize(); + } + d->strikeout->setChecked( f.strikeOut() ); + d->underline->setChecked( f.underline() ); + + updateFamilies(); +} + +/*! + \internal + Returns the font which the user has chosen. + + \sa setFont() +*/ + +TQFont TQFontDialog::font() const +{ + int pSize = d->sizeEdit->text().toInt(); + + TQFont f = d->fdb.font( d->familyList->currentText(), d->style, pSize ); + f.setStrikeOut( d->strikeout->isChecked() ); + f.setUnderline( d->underline->isChecked() ); + return f; +} + +#endif diff --git a/src/dialogs/qfontdialog.h b/src/dialogs/qfontdialog.h new file mode 100644 index 000000000..c30836acf --- /dev/null +++ b/src/dialogs/qfontdialog.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Definition of TQFontDialog +** +** Created : 970605 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQFONTDIALOG_H +#define TQFONTDIALOG_H + +#include "qwindowdefs.h" + +#ifndef QT_NO_FONTDIALOG + +// +// W A R N I N G +// ------------- +// +// This class is under development and has private constructors. +// +// You may use the public static getFont() functions which are guaranteed +// to be available in the future. +// + +#ifndef QT_H +#include "qdialog.h" +#include "qfont.h" +#endif // QT_H + +class TQFontDialogPrivate; + +class Q_EXPORT TQFontDialog: public TQDialog +{ + Q_OBJECT + +public: + static TQFont getFont( bool *ok, const TQFont &def, + TQWidget* parent=0, const char* name=0); + static TQFont getFont( bool *ok, TQWidget* parent=0, const char* name=0); + +private: + static TQFont getFont( bool *ok, const TQFont *def, + TQWidget* parent=0, const char* name=0); + + TQFontDialog( TQWidget* parent=0, const char* name=0, bool modal=FALSE, + WFlags f=0 ); + ~TQFontDialog(); + + TQFont font() const; + void setFont( const TQFont &font ); + + bool eventFilter( TQObject *, TQEvent * ); + + void updateFamilies(); + void updateStyles(); + void updateSizes(); + +private slots: + void sizeChanged( const TQString &); + void familyHighlighted( int ); + void scriptHighlighted( int ); + void styleHighlighted( int ); + void sizeHighlighted( const TQString & ); + void updateSample(); + +private: + friend class TQFontDialogPrivate; + TQFontDialogPrivate * d; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQFontDialog( const TQFontDialog & ); + TQFontDialog& operator=( const TQFontDialog & ); +#endif +}; + +#endif + +#endif // TQFONTDIALOG_H diff --git a/src/dialogs/qinputdialog.cpp b/src/dialogs/qinputdialog.cpp new file mode 100644 index 000000000..ac58d979e --- /dev/null +++ b/src/dialogs/qinputdialog.cpp @@ -0,0 +1,532 @@ +/**************************************************************************** +** +** Implementation of TQInputDialog class +** +** Created : 991212 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qinputdialog.h" + +#ifndef QT_NO_INPUTDIALOG + +#include "qlayout.h" +#include "qlabel.h" +#include "qlineedit.h" +#include "qpushbutton.h" +#include "qspinbox.h" +#include "qcombobox.h" +#include "qwidgetstack.h" +#include "qvalidator.h" +#include "qapplication.h" + +class TQInputDialogPrivate +{ +public: + friend class TQInputDialog; + TQLabel *label; + TQLineEdit *lineEdit; + TQSpinBox *spinBox; + TQComboBox *comboBox, *editComboBox; + TQPushButton *ok; + TQWidgetStack *stack; + TQInputDialog::Type type; +}; + +/*! + \class TQInputDialog + \brief The TQInputDialog class provides a simple convenience dialog to get a single value from the user. + \ingroup dialogs + \mainclass + + The input value can be a string, a number or an item from a list. A + label must be set to tell the user what they should enter. + + Four static convenience functions are provided: + getText(), getInteger(), getDouble() and getItem(). All the + functions can be used in a similar way, for example: + \code + bool ok; + TQString text = TQInputDialog::getText( + "MyApp 3000", "Enter your name:", TQLineEdit::Normal, + TQString::null, &ok, this ); + if ( ok && !text.isEmpty() ) { + // user entered something and pressed OK + } else { + // user entered nothing or pressed Cancel + } + \endcode + + \img inputdialogs.png Input Dialogs +*/ + +/*! + \enum TQInputDialog::Type + + This enum specifies the type of the dialog, i.e. what kind of data you + want the user to input: + + \value LineEdit A TQLineEdit is used for obtaining string or numeric + input. The TQLineEdit can be accessed using lineEdit(). + + \value SpinBox A TQSpinBox is used for obtaining integer input. + Use spinBox() to access the TQSpinBox. + + \value ComboBox A read-only TQComboBox is used to provide a fixed + list of choices from which the user can choose. + Use comboBox() to access the TQComboBox. + + \value EditableComboBox An editable TQComboBox is used to provide a fixed + list of choices from which the user can choose, but which also + allows the user to enter their own value instead. + Use editableComboBox() to access the TQComboBox. +*/ + +/*! + Constructs the dialog. The \a label is the text which is shown to the user + (it should tell the user what they are expected to enter). The \a parent + is the dialog's parent widget. The widget is called \a name. If \a + modal is TRUE (the default) the dialog will be modal. The \a type + parameter is used to specify which type of dialog to construct. + + \sa getText(), getInteger(), getDouble(), getItem() +*/ + +TQInputDialog::TQInputDialog( const TQString &label, TQWidget* parent, + const char* name, bool modal, Type type ) + : TQDialog( parent, name, modal ) +{ + d = new TQInputDialogPrivate; + d->lineEdit = 0; + d->spinBox = 0; + d->comboBox = 0; + + TQVBoxLayout *vbox = new TQVBoxLayout( this, 6, 6 ); + + d->label = new TQLabel( label, this, "qt_inputdlg_lbl" ); + vbox->addWidget( d->label ); + + d->stack = new TQWidgetStack( this, "qt_inputdlg_ws" ); + vbox->addWidget( d->stack ); + d->lineEdit = new TQLineEdit( d->stack, "qt_inputdlg_le" ); + d->spinBox = new TQSpinBox( d->stack, "qt_inputdlg_sb" ); + d->comboBox = new TQComboBox( FALSE, d->stack, "qt_inputdlg_cb" ); + d->editComboBox = new TQComboBox( TRUE, d->stack, "qt_inputdlg_editcb" ); + + TQHBoxLayout *hbox = new TQHBoxLayout( 6 ); + vbox->addLayout( hbox, AlignRight ); + + d->ok = new TQPushButton( tr( "OK" ), this, "qt_ok_btn" ); + d->ok->setDefault( TRUE ); + TQPushButton *cancel = new TQPushButton( tr( "Cancel" ), this, "qt_cancel_btn" ); + + TQSize bs = d->ok->sizeHint().expandedTo( cancel->sizeHint() ); + d->ok->setFixedSize( bs ); + cancel->setFixedSize( bs ); + + hbox->addStretch(); + hbox->addWidget( d->ok ); + hbox->addWidget( cancel ); + + connect( d->lineEdit, SIGNAL( returnPressed() ), + this, SLOT( tryAccept() ) ); + connect( d->lineEdit, SIGNAL( textChanged(const TQString&) ), + this, SLOT( textChanged(const TQString&) ) ); + + connect( d->ok, SIGNAL( clicked() ), this, SLOT( accept() ) ); + connect( cancel, SIGNAL( clicked() ), this, SLOT( reject() ) ); + + TQSize sh = sizeHint().expandedTo( TQSize(400, 10) ); + setType( type ); + resize( sh.width(), vbox->heightForWidth(sh.width()) ); +} + +/*! + Returns the line edit which is used in LineEdit mode. +*/ + +TQLineEdit *TQInputDialog::lineEdit() const +{ + return d->lineEdit; +} + +/*! + Returns the spinbox which is used in SpinBox mode. +*/ + +TQSpinBox *TQInputDialog::spinBox() const +{ + return d->spinBox; +} + +/*! + Returns the combobox which is used in ComboBox mode. +*/ + +TQComboBox *TQInputDialog::comboBox() const +{ + return d->comboBox; +} + +/*! + Returns the combobox which is used in EditableComboBox mode. +*/ + +TQComboBox *TQInputDialog::editableComboBox() const +{ + return d->editComboBox; +} + +/*! + Sets the input type of the dialog to \a t. +*/ + +void TQInputDialog::setType( Type t ) +{ + TQWidget *input = 0; + switch ( t ) { + case LineEdit: + input = d->lineEdit; + break; + case SpinBox: + input = d->spinBox; + break; + case ComboBox: + input = d->comboBox; + break; + case EditableComboBox: + input = d->editComboBox; + break; + default: +#if defined(QT_CHECK_STATE) + qWarning( "TQInputDialog::setType: Invalid type" ); +#endif + break; + } + if ( input ) { + d->stack->raiseWidget( input ); + d->stack->setFixedHeight( input->sizeHint().height() ); + input->setFocus(); +#ifndef QT_NO_ACCEL + d->label->setBuddy( input ); +#endif + } + + d->type = t; +} + +/*! + Returns the input type of the dialog. + + \sa setType() +*/ + +TQInputDialog::Type TQInputDialog::type() const +{ + return d->type; +} + +/*! + Destructor. +*/ + +TQInputDialog::~TQInputDialog() +{ + delete d; +} + +/*! + Static convenience function to get a string 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 + say what should be entered). \a text is the default text which is + placed in the line edit. The \a mode is the echo mode the line edit + will use. If \a ok is not-null \e *\a ok will be set to TRUE if the + user pressed OK and to FALSE if the user pressed Cancel. The + dialog's parent is \a parent; the dialog is called \a name. The + dialog will be modal. + + This function returns the text which has been entered in the line + edit. It will not return an empty string. + + Use this static function like this: + + \code + bool ok; + TQString text = TQInputDialog::getText( + "MyApp 3000", "Enter your name:", TQLineEdit::Normal, + TQString::null, &ok, this ); + if ( ok && !text.isEmpty() ) { + // user entered something and pressed OK + } else { + // user entered nothing or pressed Cancel + } + \endcode +*/ + +TQString TQInputDialog::getText( const TQString &caption, const TQString &label, + TQLineEdit::EchoMode mode, const TQString &text, + bool *ok, TQWidget *parent, const char *name ) +{ + TQInputDialog *dlg = new TQInputDialog( label, parent, + name ? name : "qt_inputdlg_gettext", + TRUE, LineEdit ); + +#ifndef QT_NO_WIDGET_TOPEXTRA + dlg->setCaption( caption ); +#endif + dlg->lineEdit()->setText( text ); + dlg->lineEdit()->setEchoMode( mode ); + + bool ok_ = FALSE; + TQString result; + ok_ = dlg->exec() == TQDialog::Accepted; + if ( ok ) + *ok = ok_; + if ( ok_ ) + result = dlg->lineEdit()->text(); + + delete dlg; + return result; +} + +/*! + Static convenience function to get an integer 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 say what should be entered). \a value is the default + integer which the spinbox will be set to. \a minValue and \a + maxValue are the minimum and maximum values the user may choose, + and \a step is the amount by which the values change as the user + presses the arrow buttons to increment or decrement the value. + + If \a ok is not-null *\a ok will be set to TRUE if the user + pressed OK and to FALSE if the user pressed Cancel. The dialog's + parent is \a parent; the dialog is called \a name. The dialog will + be modal. + + This function returns the integer which has been entered by the user. + + Use this static function like this: + + \code + bool ok; + int res = TQInputDialog::getInteger( + "MyApp 3000", "Enter a number:", 22, 0, 1000, 2, + &ok, this ); + if ( ok ) { + // user entered something and pressed OK + } else { + // user pressed Cancel + } + \endcode +*/ + +int TQInputDialog::getInteger( const TQString &caption, const TQString &label, + int value, int minValue, int maxValue, int step, bool *ok, + TQWidget *parent, const char *name ) +{ + TQInputDialog *dlg = new TQInputDialog( label, parent, + name ? name : "qt_inputdlg_getint", + TRUE, SpinBox ); +#ifndef QT_NO_WIDGET_TOPEXTRA + dlg->setCaption( caption ); +#endif + dlg->spinBox()->setRange( minValue, maxValue ); + dlg->spinBox()->setSteps( step, 0 ); + dlg->spinBox()->setValue( value ); + + bool ok_ = FALSE; + int result; + ok_ = dlg->exec() == TQDialog::Accepted; + if ( ok ) + *ok = ok_; + result = dlg->spinBox()->value(); + + delete dlg; + return result; +} + +/*! + Static convenience function to get a floating point number 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 say what should be entered). \a value is the default + floating point number that the line edit will be set to. \a + minValue and \a maxValue are the minimum and maximum values the + user may choose, and \a decimals is the maximum number of decimal + places the number may have. + + If \a ok is not-null \e *\a ok will be set to TRUE if the user + pressed OK and to FALSE if the user pressed Cancel. The dialog's + parent is \a parent; the dialog is called \a name. The dialog will + be modal. + + This function returns the floating point number which has been + entered by the user. + + Use this static function like this: + + \code + bool ok; + double res = TQInputDialog::getDouble( + "MyApp 3000", "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 TQInputDialog::getDouble( const TQString &caption, const TQString &label, + double value, double minValue, double maxValue, + int decimals, bool *ok, TQWidget *parent, + const char *name ) +{ + TQInputDialog dlg( label, parent, + name ? name : "qt_inputdlg_getdbl", TRUE, LineEdit ); +#ifndef QT_NO_WIDGET_TOPEXTRA + dlg.setCaption( caption ); +#endif + dlg.lineEdit()->setValidator( new TQDoubleValidator( minValue, maxValue, decimals, dlg.lineEdit() ) ); + dlg.lineEdit()->setText( TQString::number( value, 'f', decimals ) ); + dlg.lineEdit()->selectAll(); + + bool accepted = ( dlg.exec() == TQDialog::Accepted ); + if ( ok ) + *ok = accepted; + return dlg.lineEdit()->text().toDouble(); +} + +/*! + 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 say what should be entered). \a list is the + string list which is inserted into the combobox, and \a current is the number + of the item which should be the current item. If \a editable is TRUE + the user can enter their own text; if \a editable is FALSE the user + may only select one of the existing items. + + If \a ok is not-null \e *\a ok will be set to TRUE if the user + pressed OK and to FALSE if the user pressed Cancel. The dialog's + parent is \a parent; the dialog is called \a name. The dialog will + be modal. + + This function returns the text of the current item, or if \a + editable is TRUE, the current text of the combobox. + + Use this static function like this: + + \code + TQStringList lst; + lst << "First" << "Second" << "Third" << "Fourth" << "Fifth"; + bool ok; + TQString res = TQInputDialog::getItem( + "MyApp 3000", "Select an item:", lst, 1, TRUE, &ok, + this ); + if ( ok ) { + // user selected an item and pressed OK + } else { + // user pressed Cancel + } + \endcode +*/ + +TQString TQInputDialog::getItem( const TQString &caption, const TQString &label, const TQStringList &list, + int current, bool editable, + bool *ok, TQWidget *parent, const char *name ) +{ + TQInputDialog *dlg = new TQInputDialog( label, parent, name ? name : "qt_inputdlg_getitem", TRUE, editable ? EditableComboBox : ComboBox ); +#ifndef QT_NO_WIDGET_TOPEXTRA + dlg->setCaption( caption ); +#endif + if ( editable ) { + dlg->editableComboBox()->insertStringList( list ); + dlg->editableComboBox()->setCurrentItem( current ); + } else { + dlg->comboBox()->insertStringList( list ); + dlg->comboBox()->setCurrentItem( current ); + } + + bool ok_ = FALSE; + TQString result; + ok_ = dlg->exec() == TQDialog::Accepted; + if ( ok ) + *ok = ok_; + if ( editable ) + result = dlg->editableComboBox()->currentText(); + else + result = dlg->comboBox()->currentText(); + + delete dlg; + return result; +} + +/*! + \internal + + This slot is invoked when the text is changed; the new text is passed + in \a s. +*/ + +void TQInputDialog::textChanged( const TQString &s ) +{ + bool on = TRUE; + + if ( d->lineEdit->validator() ) { + TQString str = d->lineEdit->text(); + int index = d->lineEdit->cursorPosition(); + on = ( d->lineEdit->validator()->validate(str, index) == + TQValidator::Acceptable ); + } else if ( type() != LineEdit ) { + on = !s.isEmpty(); + } + d->ok->setEnabled( on ); +} + +/*! + \internal +*/ + +void TQInputDialog::tryAccept() +{ + if ( !d->lineEdit->text().isEmpty() ) + accept(); +} + +#endif diff --git a/src/dialogs/qinputdialog.h b/src/dialogs/qinputdialog.h new file mode 100644 index 000000000..7010bd538 --- /dev/null +++ b/src/dialogs/qinputdialog.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Definition of TQInputDialog class +** +** Created : 991212 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQINPUTDIALOG_H +#define TQINPUTDIALOG_H + +#ifndef QT_H +#include "qdialog.h" +#include "qstring.h" +#include "qlineedit.h" +#endif // QT_H + +#ifndef QT_NO_INPUTDIALOG + +class TQSpinBox; +class TQComboBox; +class TQInputDialogPrivate; + +class Q_EXPORT TQInputDialog : public TQDialog +{ + Q_OBJECT + +private: + enum Type { LineEdit, SpinBox, ComboBox, EditableComboBox }; + + TQInputDialog( const TQString &label, TQWidget* parent=0, const char* name=0, + bool modal = TRUE, Type type = LineEdit ); //### 4.0: widget flag! + ~TQInputDialog(); + + TQLineEdit *lineEdit() const; + TQSpinBox *spinBox() const; + TQComboBox *comboBox() const; + TQComboBox *editableComboBox() const; + + void setType( Type t ); + Type type() const; + +public: + //### 4.0: widget flag! + static TQString getText( const TQString &caption, const TQString &label, TQLineEdit::EchoMode echo = TQLineEdit::Normal, + const TQString &text = TQString::null, bool *ok = 0, TQWidget *parent = 0, const char *name = 0 ); + static int getInteger( const TQString &caption, const TQString &label, int value = 0, int minValue = -2147483647, + int maxValue = 2147483647, + int step = 1, bool *ok = 0, TQWidget *parent = 0, const char *name = 0 ); + static double getDouble( const TQString &caption, const TQString &label, double value = 0, + double minValue = -2147483647, double maxValue = 2147483647, + int decimals = 1, bool *ok = 0, TQWidget *parent = 0, const char *name = 0 ); + static TQString getItem( const TQString &caption, const TQString &label, const TQStringList &list, + int current = 0, bool editable = TRUE, + bool *ok = 0, TQWidget *parent = 0, const char *name = 0 ); + +private slots: + void textChanged( const TQString &s ); + void tryAccept(); + +private: + TQInputDialogPrivate *d; + friend class TQInputDialogPrivate; /* to avoid 'has no friends' warnings... */ + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQInputDialog( const TQInputDialog & ); + TQInputDialog &operator=( const TQInputDialog & ); +#endif +}; + +#endif // QT_NO_INPUTDIALOG + +#endif // TQINPUTDIALOG_H + diff --git a/src/dialogs/qmessagebox.cpp b/src/dialogs/qmessagebox.cpp new file mode 100644 index 000000000..b598917cd --- /dev/null +++ b/src/dialogs/qmessagebox.cpp @@ -0,0 +1,1674 @@ +/**************************************************************************** +** +** Implementation of TQMessageBox class +** +** Created : 950503 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qmessagebox.h" + +#ifndef QT_NO_MESSAGEBOX + +#include "qaccel.h" +#include "qlabel.h" +#include "qpushbutton.h" +#include "qimage.h" +#include "qapplication.h" +#include "qstyle.h" +#include "qobjectlist.h" +#if defined(QT_ACCESSIBILITY_SUPPORT) +#include "qaccessible.h" +#endif +#if defined QT_NON_COMMERCIAL +#include "qnc_win.h" +#endif + + +#ifdef Q_WS_X11 +#include "private/qtkdeintegration_x11_p.h" +#endif + +extern bool qt_use_native_dialogs; + +// Internal class - don't touch + +class TQMessageBoxLabel : public TQLabel +{ + Q_OBJECT +public: + TQMessageBoxLabel( TQWidget* parent ) : TQLabel( parent, "messageBoxText") + { + setAlignment( AlignAuto|ExpandTabs ); + } +}; +#include "qmessagebox.moc" + + + +// the TQt logo, for aboutTQt +/* XPM */ +static const char * const qtlogo_xpm[] = { +/* width height ncolors chars_per_pixel */ +"50 50 17 1", +/* colors */ +" c #000000", +". c #495808", +"X c #2A3304", +"o c #242B04", +"O c #030401", +"+ c #9EC011", +"@ c #93B310", +"# c #748E0C", +"$ c #A2C511", +"% c #8BA90E", +"& c #99BA10", +"* c #060701", +"= c #181D02", +"- c #212804", +"; c #61770A", +": c #0B0D01", +"/ c None", +/* pixels */ +"/$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$/", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$+++$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$@;.o=::=o.;@$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$+#X* **X#+$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$#oO* O **o#+$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$&.* OO O*.&$$$$$$$$$$$$$", +"$$$$$$$$$$$$@XOO * OO X&$$$$$$$$$$$$", +"$$$$$$$$$$$@XO OO O **:::OOO OOO X@$$$$$$$$$$$", +"$$$$$$$$$$&XO O-;#@++@%.oOO X&$$$$$$$$$$", +"$$$$$$$$$$.O : *-#+$$$$$$$$+#- : O O*.$$$$$$$$$$", +"$$$$$$$$$#*OO O*.&$$$$$$$$$$$$+.OOOO **#$$$$$$$$$", +"$$$$$$$$+-OO O *;$$$$$$$$$$$&$$$$;* o+$$$$$$$$", +"$$$$$$$$#O* O .+$$$$$$$$$$@X;$$$+.O *#$$$$$$$$", +"$$$$$$$$X* -&$$$$$$$$$$@- :;$$$&- OX$$$$$$$$", +"$$$$$$$@*O *O#$$$$$$$$$$@oOO**;$$$# O*%$$$$$$$", +"$$$$$$$; -+$$$$$$$$$@o O OO ;+$$-O *;$$$$$$$", +"$$$$$$$. ;$$$$$$$$$@-OO OO X&$$;O .$$$$$$$", +"$$$$$$$o *#$$$$$$$$@o O O O-@$$$#O *o$$$$$$$", +"$$$$$$+= *@$$$$$$$@o* OO -@$$$$&: =$$$$$$$", +"$$$$$$+: :+$$$$$$@- *-@$$$$$$: :+$$$$$$", +"$$$$$$+: :+$$$$$@o* O *-@$$$$$$: :+$$$$$$", +"$$$$$$$= :@$$$$@o*OOO -@$$$$@: =+$$$$$$", +"$$$$$$$- O%$$$@o* O O O O-@$$$#* OX$$$$$$$", +"$$$$$$$. O *O;$$&o O*O* *O -@$$; O.$$$$$$$", +"$$$$$$$;* Oo+$$;O*O:OO-- Oo@+= *;$$$$$$$", +"$$$$$$$@* O O#$$$;*OOOo@@-O Oo;O* **@$$$$$$$", +"$$$$$$$$X* OOO-+$$$;O o@$$@- O O OX$$$$$$$$", +"$$$$$$$$#* * O.$$$$;X@$$$$@-O O O#$$$$$$$$", +"$$$$$$$$+oO O OO.+$$+&$$$$$$@-O o+$$$$$$$$", +"$$$$$$$$$#* **.&$$$$$$$$$$@o OO:#$$$$$$$$$", +"$$$$$$$$$+. O* O-#+$$$$$$$$+;O OOO:@$$$$$$$$$", +"$$$$$$$$$$&X *O -;#@++@#;=O O -@$$$$$$$$", +"$$$$$$$$$$$&X O O*O::::O OO Oo@$$$$$$$", +"$$$$$$$$$$$$@XOO OO O*X+$$$$$$", +"$$$$$$$$$$$$$&.* ** O :: *:#$$$$$$$", +"$$$$$$$$$$$$$$$#o*OO O Oo#@-OOO=#$$$$$$$$", +"$$$$$$$$$$$$$$$$+#X:* * O**X#+$$@-*:#$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$%;.o=::=o.#@$$$$$$@X#$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$+++$$$$$$$$$$$+$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"/$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$/", +}; + + +/*! + \class TQMessageBox + \brief The TQMessageBox class provides a modal dialog with a short message, an icon, and some buttons. + \ingroup dialogs + \mainclass + + Message boxes are used to provide informative messages and to ask + simple questions. + + TQMessageBox provides a range of different messages, arranged + roughly along two axes: severity and complexity. + + Severity is + \table + \row + \i \img qmessagebox-quest.png + \i Question + \i For message boxes that ask a question as part of normal + operation. Some style guides recommend using Information for this + purpose. + \row + \i \img qmessagebox-info.png + \i Information + \i For message boxes that are part of normal operation. + \row + \i \img qmessagebox-warn.png + \i Warning + \i For message boxes that tell the user about unusual errors. + \row + \i \img qmessagebox-crit.png + \i Critical + \i For message boxes that tell the user about critical errors. + \endtable + + The message box has a different icon for each of the severity levels. + + Complexity is one button (OK) for simple messages, or two or even + three buttons for questions. + + There are static functions for the most common cases. + + Examples: + + If a program is unable to find a supporting file, but can do perfectly + well without it: + + \code + TQMessageBox::information( this, "Application name", + "Unable to find the user preferences file.\n" + "The factory default will be used instead." ); + \endcode + + question() is useful for simple yes/no questions: + + \code + if ( TQFile::exists( filename ) && + TQMessageBox::question( + this, + tr("Overwrite File? -- Application Name"), + tr("A file called %1 already exists." + "Do you want to overwrite it?") + .arg( filename ), + tr("&Yes"), tr("&No"), + TQString::null, 0, 1 ) ) + return false; + \endcode + + warning() can be used to tell the user about unusual errors, or + errors which can't be easily fixed: + + \code + switch( TQMessageBox::warning( this, "Application name", + "Could not connect to the <mumble> server.\n" + "This program can't function correctly " + "without the server.\n\n", + "Retry", + "Quit", 0, 0, 1 ) ) { + case 0: // The user clicked the Retry again button or pressed Enter + // try again + break; + case 1: // The user clicked the Quit or pressed Escape + // exit + break; + } + \endcode + + The text part of all message box messages can be either rich text + or plain text. If you specify a rich text formatted string, it + will be rendered using the default stylesheet. See + TQStyleSheet::defaultSheet() for details. With certain strings that + contain XML meta characters, the auto-rich text detection may + fail, interpreting plain text incorrectly as rich text. In these + rare cases, use TQStyleSheet::convertFromPlainText() to convert + your plain text string to a visually equivalent rich text string + or set the text format explicitly with setTextFormat(). + + Note that the Microsoft Windows User Interface Guidelines + recommend using the application name as the window's caption. + + Below are more examples of how to use the static member functions. + After these examples you will find an overview of the non-static + member functions. + + Exiting a program is part of its normal operation. If there is + unsaved data the user probably should be asked if they want to + save the data. For example: + + \code + switch( TQMessageBox::information( this, "Application name here", + "The document contains unsaved changes\n" + "Do you want to save the changes before exiting?", + "&Save", "&Discard", "Cancel", + 0, // Enter == button 0 + 2 ) ) { // Escape == button 2 + case 0: // Save clicked or Alt+S pressed or Enter pressed. + // save + break; + case 1: // Discard clicked or Alt+D pressed + // don't save but exit + break; + case 2: // Cancel clicked or Escape pressed + // don't exit + break; + } + \endcode + + The Escape button cancels the entire exit operation, and pressing + Enter causes the changes to be saved before the exit occurs. + + Disk full errors are unusual and they certainly can be hard to + correct. This example uses predefined buttons instead of + hard-coded button texts: + + \code + switch( TQMessageBox::warning( this, "Application name here", + "Could not save the user preferences,\n" + "because the disk is full. You can delete\n" + "some files and press Retry, or you can\n" + "abort the Save Preferences operation.", + TQMessageBox::Retry | TQMessageBox::Default, + TQMessageBox::Abort | TQMessageBox::Escape )) { + case TQMessageBox::Retry: // Retry clicked or Enter pressed + // try again + break; + case TQMessageBox::Abort: // Abort clicked or Escape pressed + // abort + break; + } + \endcode + + The critical() function should be reserved for critical errors. In + this example errorDetails is a TQString or const char*, and TQString + is used to concatenate several strings: + + \code + TQMessageBox::critical( 0, "Application name here", + TQString("An internal error occurred. Please ") + + "call technical support at 1234-56789 and report\n"+ + "these numbers:\n\n" + errorDetails + + "\n\nApplication will now exit." ); + \endcode + + In this example an OK button is displayed. + + TQMessageBox provides a very simple About box which displays an + appropriate icon and the string you provide: + + \code + TQMessageBox::about( this, "About <Application>", + "<Application> is a <one-paragraph blurb>\n\n" + "Copyright 1991-2003 Such-and-such. " + "<License words here.>\n\n" + "For technical support, call 1234-56789 or see\n" + "http://www.such-and-such.com/Application/\n" ); + \endcode + + See about() for more information. + + If you want your users to know that the application is built using + TQt (so they know that you use high quality tools) you might like + to add an "About TQt" menu option under the Help menu to invoke + aboutTQt(). + + If none of the standard message boxes is suitable, you can create a + TQMessageBox from scratch and use custom button texts: + + \code + TQMessageBox mb( "Application name here", + "Saving the file will overwrite the original file on the disk.\n" + "Do you really want to save?", + TQMessageBox::Information, + TQMessageBox::Yes | TQMessageBox::Default, + TQMessageBox::No, + TQMessageBox::Cancel | TQMessageBox::Escape ); + mb.setButtonText( TQMessageBox::Yes, "Save" ); + mb.setButtonText( TQMessageBox::No, "Discard" ); + switch( mb.exec() ) { + case TQMessageBox::Yes: + // save and exit + break; + case TQMessageBox::No: + // exit without saving + break; + case TQMessageBox::Cancel: + // don't save and don't exit + break; + } + \endcode + + TQMessageBox defines two enum types: Icon and an unnamed button type. + Icon defines the \c Question, \c Information, \c Warning, and \c + Critical icons for each GUI style. It is used by the constructor + and by the static member functions question(), information(), + warning() and critical(). A function called standardIcon() gives + you access to the various icons. + + The button types are: + \list + \i Ok - the default for single-button message boxes + \i Cancel - note that this is \e not automatically Escape + \i Yes + \i No + \i Abort + \i Retry + \i Ignore + \i YesAll + \i NoAll + \endlist + + Button types can be combined with two modifiers by using OR, '|': + \list + \i Default - makes pressing Enter equivalent to + clicking this button. Normally used with Ok, Yes or similar. + \i Escape - makes pressing Escape equivalent to clicking this button. + Normally used with Abort, Cancel or similar. + \endlist + + The text(), icon() and iconPixmap() functions provide access to the + current text and pixmap of the message box. The setText(), setIcon() + and setIconPixmap() let you change it. The difference between + setIcon() and setIconPixmap() is that the former accepts a + TQMessageBox::Icon and can be used to set standard icons, whereas the + latter accepts a TQPixmap and can be used to set custom icons. + + setButtonText() and buttonText() provide access to the buttons. + + TQMessageBox has no signals or slots. + + <img src=qmsgbox-m.png> <img src=qmsgbox-w.png> + + \sa TQDialog, + \link http://www.iarchitect.com/errormsg.htm + Isys on error messages \endlink, + \link guibooks.html#fowler GUI Design Handbook: Message Box \endlink +*/ + + +/*! + \enum TQMessageBox::Icon + + This enum has the following values: + + \value NoIcon the message box does not have any icon. + + \value Question an icon indicating that + the message is asking a question. + + \value Information an icon indicating that + the message is nothing out of the ordinary. + + \value Warning an icon indicating that the + message is a warning, but can be dealt with. + + \value Critical an icon indicating that + the message represents a critical problem. + +*/ + + +struct TQMessageBoxData { + TQMessageBoxData(TQMessageBox* parent) : + iconLabel( parent, "icon" ) + { + } + + int numButtons; // number of buttons + TQMessageBox::Icon icon; // message box icon + TQLabel iconLabel; // label holding any icon + int button[3]; // button types + int defButton; // default button (index) + int escButton; // escape button (index) + TQSize buttonSize; // button size + TQPushButton *pb[3]; // buttons +}; + +static const int LastButton = TQMessageBox::NoAll; + +/* + NOTE: The table of button texts correspond to the button enum. +*/ + +#ifndef Q_OS_TEMP +static const char * const mb_texts[] = { +#else +const char * mb_texts[] = { +#endif + 0, + QT_TRANSLATE_NOOP("TQMessageBox","OK"), + QT_TRANSLATE_NOOP("TQMessageBox","Cancel"), + QT_TRANSLATE_NOOP("TQMessageBox","&Yes"), + QT_TRANSLATE_NOOP("TQMessageBox","&No"), + QT_TRANSLATE_NOOP("TQMessageBox","&Abort"), + QT_TRANSLATE_NOOP("TQMessageBox","&Retry"), + QT_TRANSLATE_NOOP("TQMessageBox","&Ignore"), + QT_TRANSLATE_NOOP("TQMessageBox","Yes to &All"), + QT_TRANSLATE_NOOP("TQMessageBox","N&o to All"), + 0 +}; + +/*! + Constructs a message box with no text and a button with the label + "OK". + + If \a parent is 0, the message box becomes an application-global + modal dialog box. If \a parent is a widget, the message box + becomes modal relative to \a parent. + + The \a parent and \a name arguments are passed to the TQDialog + constructor. +*/ + +TQMessageBox::TQMessageBox( TQWidget *parent, const char *name ) + : TQDialog( parent, name, TRUE, WStyle_Customize | WStyle_DialogBorder | WStyle_Title | WStyle_SysMenu ) +{ + init( Ok, 0, 0 ); +} + + +/*! + Constructs a message box with a \a caption, a \a text, an \a icon, + and up to three buttons. + + The \a icon must be one of the following: + \list + \i TQMessageBox::NoIcon + \i TQMessageBox::Question + \i TQMessageBox::Information + \i TQMessageBox::Warning + \i TQMessageBox::Critical + \endlist + + Each button, \a button0, \a button1 and \a button2, can have one + of the following values: + \list + \i TQMessageBox::NoButton + \i TQMessageBox::Ok + \i TQMessageBox::Cancel + \i TQMessageBox::Yes + \i TQMessageBox::No + \i TQMessageBox::Abort + \i TQMessageBox::Retry + \i TQMessageBox::Ignore + \i TQMessageBox::YesAll + \i TQMessageBox::NoAll + \endlist + + Use TQMessageBox::NoButton for the later parameters to have fewer + than three buttons in your message box. If you don't specify any + buttons at all, TQMessageBox will provide an Ok button. + + One of the buttons can be OR-ed with the \c TQMessageBox::Default + flag to make it the default button (clicked when Enter is + pressed). + + One of the buttons can be OR-ed with the \c TQMessageBox::Escape + flag to make it the cancel or close button (clicked when Escape is + pressed). + + Example: + \code + TQMessageBox mb( "Application Name", + "Hardware failure.\n\nDisk error detected\nDo you want to stop?", + TQMessageBox::Question, + TQMessageBox::Yes | TQMessageBox::Default, + TQMessageBox::No | TQMessageBox::Escape, + TQMessageBox::NoButton ); + if ( mb.exec() == TQMessageBox::No ) + // try again + \endcode + + If \a parent is 0, the message box becomes an application-global + modal dialog box. If \a parent is a widget, the message box + becomes modal relative to \a parent. + + If \a modal is TRUE the message box is modal; otherwise it + is modeless. + + The \a parent, \a name, \a modal, and \a f arguments are passed to + the TQDialog constructor. + + \sa setCaption(), setText(), setIcon() +*/ + +TQMessageBox::TQMessageBox( const TQString& caption, + const TQString &text, Icon icon, + int button0, int button1, int button2, + TQWidget *parent, const char *name, + bool modal, WFlags f ) + : TQDialog( parent, name, modal, f | WStyle_Customize | WStyle_DialogBorder | WStyle_Title | WStyle_SysMenu ) +{ + init( button0, button1, button2 ); +#ifndef QT_NO_WIDGET_TOPEXTRA + setCaption( caption ); +#endif + setText( text ); + setIcon( icon ); +} + + +/*! + Destroys the message box. +*/ + +TQMessageBox::~TQMessageBox() +{ + delete mbd; +} + +static TQString * translatedTextAboutTQt = 0; + +void TQMessageBox::init( int button0, int button1, int button2 ) +{ + if ( !translatedTextAboutTQt ) { + translatedTextAboutTQt = new TQString; + +#if defined(QT_NON_COMMERCIAL) + QT_NC_MSGBOX +#else + *translatedTextAboutTQt = tr( + "<h3>About TQt</h3>" + "<p>This program uses TQt version %1.</p>" + "<p>TQt is a C++ toolkit for multiplatform GUI & " + "application development.</p>" + "<p>TQt provides single-source " + "portability across MS Windows, Mac OS X, " + "Linux, and all major commercial Unix variants." + "<br>TQt is also available for embedded devices.</p>" + "<p>TQt is a Trolltech product. " + "See <tt>http://www.trolltech.com/qt/</tt> " + "for more information.</p>" + ).arg( QT_VERSION_STR ); +#endif + + } + label = new TQMessageBoxLabel( this ); + Q_CHECK_PTR( label ); + + if ( (button2 && !button1) || (button1 && !button0) ) { +#if defined(QT_CHECK_RANGE) + qWarning( "TQMessageBox: Inconsistent button parameters" ); +#endif + button0 = button1 = button2 = 0; + } + mbd = new TQMessageBoxData(this); + Q_CHECK_PTR( mbd ); + mbd->icon = NoIcon; + mbd->iconLabel.setPixmap( TQPixmap() ); + mbd->numButtons = 0; + mbd->button[0] = button0; + mbd->button[1] = button1; + mbd->button[2] = button2; + mbd->defButton = -1; + mbd->escButton = -1; + int i; + for ( i=0; i<3; i++ ) { + int b = mbd->button[i]; + if ( (b & Default) ) { + if ( mbd->defButton >= 0 ) { +#if defined(QT_CHECK_RANGE) + qWarning( "TQMessageBox: There can be at most one " + "default button" ); +#endif + } else { + mbd->defButton = i; + } + } + if ( (b & Escape) ) { + if ( mbd->escButton >= 0 ) { +#if defined(QT_CHECK_RANGE) + qWarning( "TQMessageBox: There can be at most one " + "escape button" ); +#endif + } else { + mbd->escButton = i; + } + } + b &= ButtonMask; + if ( b == 0 ) { + if ( i == 0 ) // no buttons, add an Ok button + b = Ok; + } else if ( b < 0 || b > LastButton ) { +#if defined(QT_CHECK_RANGE) + qWarning( "TQMessageBox: Invalid button specifier" ); +#endif + b = Ok; + } else { + if ( i > 0 && mbd->button[i-1] == 0 ) { +#if defined(QT_CHECK_RANGE) + qWarning( "TQMessageBox: Inconsistent button parameters; " + "button %d defined but not button %d", + i+1, i ); +#endif + b = 0; + } + } + mbd->button[i] = b; + if ( b ) + mbd->numButtons++; + } + for ( i=0; i<3; i++ ) { + if ( i >= mbd->numButtons ) { + mbd->pb[i] = 0; + } else { + TQCString buttonName; + buttonName.sprintf( "button%d", i+1 ); + mbd->pb[i] = new TQPushButton( + tr(mb_texts[mbd->button[i]]), + this, buttonName ); + if ( mbd->defButton == i ) { + mbd->pb[i]->setDefault( TRUE ); + mbd->pb[i]->setFocus(); + } + mbd->pb[i]->setAutoDefault( TRUE ); + mbd->pb[i]->setFocusPolicy( TQWidget::StrongFocus ); + connect( mbd->pb[i], SIGNAL(clicked()), SLOT(buttonClicked()) ); + } + } + resizeButtons(); + reserved1 = reserved2 = 0; +} + + +int TQMessageBox::indexOf( int button ) const +{ + int index = -1; + for ( int i=0; i<mbd->numButtons; i++ ) { + if ( mbd->button[i] == button ) { + index = i; + break; + } + } + return index; +} + + +void TQMessageBox::resizeButtons() +{ + int i; + TQSize maxSize; + for ( i=0; i<mbd->numButtons; i++ ) { + TQSize s = mbd->pb[i]->sizeHint(); + maxSize.setWidth( TQMAX(maxSize.width(), s.width()) ); + maxSize.setHeight( TQMAX(maxSize.height(),s.height()) ); + } + mbd->buttonSize = maxSize; + for ( i=0; i<mbd->numButtons; i++ ) + mbd->pb[i]->resize( maxSize ); +} + + +/*! + \property TQMessageBox::text + \brief the message box text to be displayed. + + The text will be interpreted either as a plain text or as rich + text, depending on the text format setting (\l + TQMessageBox::textFormat). The default setting is \c AutoText, i.e. + the message box will try to auto-detect the format of the text. + + The default value of this property is TQString::null. + + \sa textFormat +*/ +TQString TQMessageBox::text() const +{ + return label->text(); +} + + +void TQMessageBox::setText( const TQString &text ) +{ + label->setText( text ); +} + + +/*! + \property TQMessageBox::icon + \brief the message box's icon + + The icon of the message box can be one of the following predefined + icons: + \list + \i TQMessageBox::NoIcon + \i TQMessageBox::Question + \i TQMessageBox::Information + \i TQMessageBox::Warning + \i TQMessageBox::Critical + \endlist + + The actual pixmap used for displaying the icon depends on the + current \link TQWidget::style() GUI style\endlink. You can also set + a custom pixmap icon using the \l TQMessageBox::iconPixmap + property. The default icon is TQMessageBox::NoIcon. + + \sa iconPixmap +*/ + +TQMessageBox::Icon TQMessageBox::icon() const +{ + return mbd->icon; +} + +void TQMessageBox::setIcon( Icon icon ) +{ + setIconPixmap( standardIcon(icon) ); + mbd->icon = icon; +} + +/*! + \obsolete + + Returns the pixmap used for a standard icon. This + allows the pixmaps to be used in more complex message boxes. + \a icon specifies the retquired icon, e.g. TQMessageBox::Information, + TQMessageBox::Warning or TQMessageBox::Critical. + + \a style is unused. +*/ + +TQPixmap TQMessageBox::standardIcon( Icon icon, GUIStyle style) +{ + Q_UNUSED(style); + return TQMessageBox::standardIcon(icon); +} + + +/*! + Returns the pixmap used for a standard icon. This allows the + pixmaps to be used in more complex message boxes. \a icon + specifies the retquired icon, e.g. TQMessageBox::Question, + TQMessageBox::Information, TQMessageBox::Warning or + TQMessageBox::Critical. +*/ + +TQPixmap TQMessageBox::standardIcon( Icon icon ) +{ + TQPixmap pm; + switch ( icon ) { + case Information: + pm = TQApplication::style().stylePixmap( TQStyle::SP_MessageBoxInformation ); + break; + case Warning: + pm = TQApplication::style().stylePixmap( TQStyle::SP_MessageBoxWarning ); + break; + case Critical: + pm = TQApplication::style().stylePixmap( TQStyle::SP_MessageBoxCritical ); + break; + case Question: + pm = TQApplication::style().stylePixmap( TQStyle::SP_MessageBoxQuestion ); + default: + break; + } + return pm; +} + + +/*! + \property TQMessageBox::iconPixmap + \brief the current icon + + The icon currently used by the message box. Note that it's often + hard to draw one pixmap that looks appropriate in both Motif and + Windows GUI styles; you may want to draw two pixmaps. + + \sa icon +*/ + +const TQPixmap *TQMessageBox::iconPixmap() const +{ + return mbd->iconLabel.pixmap(); +} + + +void TQMessageBox::setIconPixmap( const TQPixmap &pixmap ) +{ + mbd->iconLabel.setPixmap(pixmap); + mbd->icon = NoIcon; +} + + +/*! + Returns the text of the message box button \a button, or + TQString::null if the message box does not contain the button. + + \sa setButtonText() +*/ + +TQString TQMessageBox::buttonText( int button ) const +{ + int index = indexOf(button); + return index >= 0 && mbd->pb[index] + ? mbd->pb[index]->text() + : TQString::null; +} + + +/*! + Sets the text of the message box button \a button to \a text. + Setting the text of a button that is not in the message box is + silently ignored. + + \sa buttonText() +*/ + +void TQMessageBox::setButtonText( int button, const TQString &text ) +{ + int index = indexOf(button); + if ( index >= 0 && mbd->pb[index] ) { + mbd->pb[index]->setText( text ); + resizeButtons(); + } +} + + +/*! + \internal + Internal slot to handle button clicks. +*/ + +void TQMessageBox::buttonClicked() +{ + int reply = 0; + const TQObject *s = sender(); + for ( int i=0; i<mbd->numButtons; i++ ) { + if ( mbd->pb[i] == s ) + reply = mbd->button[i]; + } + done( reply ); +} + + +/*! + Adjusts the size of the message box to fit the contents just before + TQDialog::exec() or TQDialog::show() is called. + + This function will not be called if the message box has been explicitly + resized before showing it. +*/ +void TQMessageBox::adjustSize() +{ + if ( !testWState(WState_Polished) ) + polish(); + resizeButtons(); + label->adjustSize(); + TQSize labelSize( label->size() ); + int n = mbd->numButtons; + int bw = mbd->buttonSize.width(); + int bh = mbd->buttonSize.height(); + int border = bh / 2 - style().pixelMetric(TQStyle::PM_ButtonDefaultIndicator); + if ( border <= 0 ) + border = 10; + int btn_spacing = 7; + if ( style().styleHint(TQStyle::SH_GUIStyle) == MotifStyle ) + btn_spacing = border; +#ifndef Q_OS_TEMP + int buttons = mbd->numButtons * bw + (n-1) * btn_spacing; + int h = bh; +#else + int visibleButtons = 0; + for ( int i = 0; i < mbd->numButtons; ++i ) + visibleButtons += mbd->pb[i]->isVisible() ? 1 : 0; + int buttons = visibleButtons == 0 ? 0 : visibleButtons * bw + (visibleButtons-1) * btn_spacing; + int h = visibleButtons == 0 ? 0 : bh; + n = visibleButtons; +#endif + if ( labelSize.height() ) + h += labelSize.height() + 3*border; + else + h += 2*border; + int lmargin = 0; + if ( mbd->iconLabel.pixmap() && mbd->iconLabel.pixmap()->width() ) { + mbd->iconLabel.adjustSize(); + lmargin += mbd->iconLabel.width() + border; + if ( h < mbd->iconLabel.height() + 3*border + bh && n ) + h = mbd->iconLabel.height() + 3*border + bh; + } + int w = TQMAX( buttons, labelSize.width() + lmargin ) + 2*border; + TQRect screen = TQApplication::desktop()->screenGeometry( pos() ); + if ( w > screen.width() ) + w = screen.width(); + resize( w, h ); + setMinimumSize( size() ); +#ifdef Q_WS_MAC + setMaximumSize(size()); +#endif +} + + +/*!\reimp +*/ +void TQMessageBox::resizeEvent( TQResizeEvent * ) +{ + int i; + int n = mbd->numButtons; + int bw = mbd->buttonSize.width(); + int bh = mbd->buttonSize.height(); +#ifdef Q_OS_TEMP + int visibleButtons = 0; + for ( i = 0; i < n; ++i ) + visibleButtons += mbd->pb[i]->isVisible() ? 1 : 0; + n = visibleButtons; + bw = visibleButtons == 0 ? 0 : bw; + bh = visibleButtons == 0 ? 0 : bh; +#endif + int border = bh / 2 - style().pixelMetric(TQStyle::PM_ButtonDefaultIndicator); + if ( border <= 0 ) + border = 10; + int btn_spacing = 7; + if ( style().styleHint(TQStyle::SH_GUIStyle) == MotifStyle ) + btn_spacing = border; + int lmargin = 0; + mbd->iconLabel.adjustSize(); + bool rtl = TQApplication::reverseLayout(); + if (rtl) + mbd->iconLabel.move(width() - border - mbd->iconLabel.width(), border); + else + mbd->iconLabel.move(border, border); + if ( mbd->iconLabel.pixmap() && mbd->iconLabel.pixmap()->width() ) + lmargin += mbd->iconLabel.width() + border; + label->setGeometry((rtl ? 0 : lmargin) + border, + border, + width() - lmargin -2*border, + height() - 3*border - bh); + int extra_space = (width() - bw*n - 2*border - (n-1)*btn_spacing); + if ( style().styleHint(TQStyle::SH_GUIStyle) == MotifStyle ) + for ( i=0; i<n; i++ ) + mbd->pb[rtl ? n - i - 1 : i]->move(border + i*bw + i*btn_spacing + extra_space*(i+1)/(n+1), + height() - border - bh ); + else + for ( i=0; i<n; i++ ) + mbd->pb[rtl ? n - i - 1 : i]->move(border + i*bw + extra_space/2 + i*btn_spacing, + height() - border - bh ); +} + + +/*!\reimp +*/ +void TQMessageBox::keyPressEvent( TQKeyEvent *e ) +{ + if ( e->key() == Key_Escape ) { + if ( mbd->escButton >= 0 ) { + TQPushButton *pb = mbd->pb[mbd->escButton]; + pb->animateClick(); + e->accept(); + return; + } + } +#ifndef QT_NO_ACCEL + if ( !( e->state() & AltButton ) ) { + TQObjectList *list = queryList( "TQPushButton" ); + TQObjectListIt it( *list ); + TQPushButton *pb; + while ( (pb = (TQPushButton*)it.current()) ) { + int key = e->key() & ~(MODIFIER_MASK|UNICODE_ACCEL); + int acc = pb->accel() & ~(MODIFIER_MASK|UNICODE_ACCEL); + if ( key && acc && acc == key ) { + delete list; + emit pb->animateClick(); + return; + } + ++it; + } + delete list; + } +#endif + TQDialog::keyPressEvent( e ); +} + +/*!\reimp +*/ +void TQMessageBox::showEvent( TQShowEvent *e ) +{ +#if defined(QT_ACCESSIBILITY_SUPPORT) + TQAccessible::updateAccessibility( this, 0, TQAccessible::Alert ); +#endif + TQDialog::showEvent( e ); +} + +/*!\reimp +*/ +void TQMessageBox::closeEvent( TQCloseEvent *e ) +{ + TQDialog::closeEvent( e ); + if ( mbd->escButton != -1 ) + setResult( mbd->button[mbd->escButton] ); +} + +/***************************************************************************** + Static TQMessageBox functions + *****************************************************************************/ + +/*!\fn int TQMessageBox::message( const TQString &,const TQString&,const TQString&,TQWidget*,const char * ) + \obsolete + Opens a modal message box directly using the specified parameters. + + Please use information(), warning(), question(), or critical() instead. +*/ + +/*! \fn bool TQMessageBox::query( const TQString &,const TQString&,const TQString&,const TQString&,TQWidget *, const char * ) + \obsolete + Queries the user using a modal message box with two buttons. + Note that \a caption is not always shown, it depends on the window manager. + + Please use information(), question(), warning(), or critical() instead. +*/ + +/*! + Opens an information message box with the caption \a caption and + the text \a text. The dialog may have up to three buttons. Each of + the buttons, \a button0, \a button1 and \a button2 may be set to + one of the following values: + + \list + \i TQMessageBox::NoButton + \i TQMessageBox::Ok + \i TQMessageBox::Cancel + \i TQMessageBox::Yes + \i TQMessageBox::No + \i TQMessageBox::Abort + \i TQMessageBox::Retry + \i TQMessageBox::Ignore + \i TQMessageBox::YesAll + \i TQMessageBox::NoAll + \endlist + + If you don't want all three buttons, set the last button, or last + two buttons to TQMessageBox::NoButton. + + One button can be OR-ed with \c TQMessageBox::Default, and one + button can be OR-ed with \c TQMessageBox::Escape. + + Returns the identity (TQMessageBox::Ok, or TQMessageBox::No, etc.) + of the button that was clicked. + + If \a parent is 0, the message box becomes an application-global + modal dialog box. If \a parent is a widget, the message box + becomes modal relative to \a parent. + + \sa question(), warning(), critical() +*/ + +int TQMessageBox::information( TQWidget *parent, + const TQString& caption, const TQString& text, + int button0, int button1, int button2 ) +{ +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::information( parent, caption, text, button0, button1, button2 ); +#endif + TQMessageBox *mb = new TQMessageBox( caption, text, Information, + button0, button1, button2, + parent, "qt_msgbox_information", TRUE, + WDestructiveClose); + Q_CHECK_PTR( mb ); + return mb->exec(); +} + +/*! + Opens a question message box with the caption \a caption and the + text \a text. The dialog may have up to three buttons. Each of the + buttons, \a button0, \a button1 and \a button2 may be set to one + of the following values: + + \list + \i TQMessageBox::NoButton + \i TQMessageBox::Ok + \i TQMessageBox::Cancel + \i TQMessageBox::Yes + \i TQMessageBox::No + \i TQMessageBox::Abort + \i TQMessageBox::Retry + \i TQMessageBox::Ignore + \i TQMessageBox::YesAll + \i TQMessageBox::NoAll + \endlist + + If you don't want all three buttons, set the last button, or last + two buttons to TQMessageBox::NoButton. + + One button can be OR-ed with \c TQMessageBox::Default, and one + button can be OR-ed with \c TQMessageBox::Escape. + + Returns the identity (TQMessageBox::Yes, or TQMessageBox::No, etc.) + of the button that was clicked. + + If \a parent is 0, the message box becomes an application-global + modal dialog box. If \a parent is a widget, the message box + becomes modal relative to \a parent. + + \sa information(), warning(), critical() +*/ + +int TQMessageBox::question( TQWidget *parent, + const TQString& caption, const TQString& text, + int button0, int button1, int button2 ) +{ +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::question( parent, caption, text, button0, button1, button2 ); +#endif + TQMessageBox *mb = new TQMessageBox( caption, text, Question, + button0, button1, button2, + parent, "qt_msgbox_information", TRUE, + WDestructiveClose); + Q_CHECK_PTR( mb ); + return mb->exec(); +} + + +/*! + Opens a warning message box with the caption \a caption and the + text \a text. The dialog may have up to three buttons. Each of the + button parameters, \a button0, \a button1 and \a button2 may be + set to one of the following values: + + \list + \i TQMessageBox::NoButton + \i TQMessageBox::Ok + \i TQMessageBox::Cancel + \i TQMessageBox::Yes + \i TQMessageBox::No + \i TQMessageBox::Abort + \i TQMessageBox::Retry + \i TQMessageBox::Ignore + \i TQMessageBox::YesAll + \i TQMessageBox::NoAll + \endlist + + If you don't want all three buttons, set the last button, or last + two buttons to TQMessageBox::NoButton. + + One button can be OR-ed with \c TQMessageBox::Default, and one + button can be OR-ed with \c TQMessageBox::Escape. + + Returns the identity (TQMessageBox::Ok, or TQMessageBox::No, etc.) + of the button that was clicked. + + If \a parent is 0, the message box becomes an application-global + modal dialog box. If \a parent is a widget, the message box + becomes modal relative to \a parent. + + \sa information(), question(), critical() +*/ + +int TQMessageBox::warning( TQWidget *parent, + const TQString& caption, const TQString& text, + int button0, int button1, int button2 ) +{ +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::warning( parent, caption, text, button0, button1, button2 ); +#endif + TQMessageBox *mb = new TQMessageBox( caption, text, Warning, + button0, button1, button2, + parent, "qt_msgbox_warning", TRUE, + WDestructiveClose); + Q_CHECK_PTR( mb ); + return mb->exec(); +} + + +/*! + Opens a critical message box with the caption \a caption and the + text \a text. The dialog may have up to three buttons. Each of the + button parameters, \a button0, \a button1 and \a button2 may be + set to one of the following values: + + \list + \i TQMessageBox::NoButton + \i TQMessageBox::Ok + \i TQMessageBox::Cancel + \i TQMessageBox::Yes + \i TQMessageBox::No + \i TQMessageBox::Abort + \i TQMessageBox::Retry + \i TQMessageBox::Ignore + \i TQMessageBox::YesAll + \i TQMessageBox::NoAll + \endlist + + If you don't want all three buttons, set the last button, or last + two buttons to TQMessageBox::NoButton. + + One button can be OR-ed with \c TQMessageBox::Default, and one + button can be OR-ed with \c TQMessageBox::Escape. + + Returns the identity (TQMessageBox::Ok, or TQMessageBox::No, etc.) + of the button that was clicked. + + If \a parent is 0, the message box becomes an application-global + modal dialog box. If \a parent is a widget, the message box + becomes modal relative to \a parent. + + \sa information(), question(), warning() +*/ + +int TQMessageBox::critical( TQWidget *parent, + const TQString& caption, const TQString& text, + int button0, int button1, int button2 ) +{ +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::critical( parent, caption, text, button0, button1, button2 ); +#endif + TQMessageBox *mb = new TQMessageBox( caption, text, Critical, + button0, button1, button2, + parent, "qt_msgbox_critical", TRUE, + WDestructiveClose); + Q_CHECK_PTR( mb ); + return mb->exec(); +} + + +/*! + Displays a simple about box with caption \a caption and text \a + text. The about box's parent is \a parent. + + about() looks for a suitable icon in four locations: + \list 1 + \i It prefers \link TQWidget::icon() parent->icon() \endlink if that exists. + \i If not, it tries the top-level widget containing \a parent. + \i If that fails, it tries the \link + TQApplication::mainWidget() main widget. \endlink + \i As a last resort it uses the Information icon. + \endlist + + The about box has a single button labelled "OK". + + \sa TQWidget::icon() TQApplication::mainWidget() +*/ + +void TQMessageBox::about( TQWidget *parent, const TQString &caption, + const TQString& text ) +{ + TQMessageBox *mb = new TQMessageBox( caption, text, + Information, + Ok + Default, 0, 0, + parent, "qt_msgbox_simple_about_box", TRUE, + WDestructiveClose); + Q_CHECK_PTR( mb ); +#ifndef QT_NO_WIDGET_TOPEXTRA + const TQPixmap *pm = parent ? parent->icon() : 0; + if ( pm && !pm->isNull() ) + mb->setIconPixmap( *pm ); + else { + pm = parent ? parent->topLevelWidget()->icon() : 0; + if ( pm && !pm->isNull() ) + mb->setIconPixmap( *pm ); + else { + pm = qApp && qApp->mainWidget() ? qApp->mainWidget()->icon() : 0; + if ( pm && !pm->isNull() ) + mb->setIconPixmap( *pm ); + } + } +#endif + mb->exec(); +} + + +/*! \reimp +*/ + +void TQMessageBox::styleChanged( TQStyle& ) +{ + if ( mbd->icon != NoIcon ) { + // Reload icon for new style + setIcon( mbd->icon ); + } +} + + +static int textBox( TQWidget *parent, TQMessageBox::Icon severity, + const TQString& caption, const TQString& text, + const TQString& button0Text, + const TQString& button1Text, + const TQString& button2Text, + int defaultButtonNumber, + int escapeButtonNumber ) +{ + int b[3]; + b[0] = 1; + b[1] = button1Text.isEmpty() ? 0 : 2; + b[2] = button2Text.isEmpty() ? 0 : 3; + + int i; + for( i=0; i<3; i++ ) { + if ( b[i] && defaultButtonNumber == i ) + b[i] += TQMessageBox::Default; + if ( b[i] && escapeButtonNumber == i ) + b[i] += TQMessageBox::Escape; + } + + TQMessageBox *mb = new TQMessageBox( caption, text, severity, + b[0], b[1], b[2], + parent, "qt_msgbox_information", TRUE, + TQt::WDestructiveClose); + Q_CHECK_PTR( mb ); + if ( button0Text.isEmpty() ) + mb->setButtonText( 1, TQMessageBox::tr(mb_texts[TQMessageBox::Ok]) ); + else + mb->setButtonText( 1, button0Text ); + if ( b[1] ) + mb->setButtonText( 2, button1Text ); + if ( b[2] ) + mb->setButtonText( 3, button2Text ); + +#ifndef QT_NO_CURSOR + mb->setCursor( TQt::arrowCursor ); +#endif + return mb->exec() - 1; +} + + +/*! + \overload + + Displays an information message box with caption \a caption, text + \a text and one, two or three buttons. Returns the index of the + button that was clicked (0, 1 or 2). + + \a button0Text is the text of the first button, and is optional. + If \a button0Text is not supplied, "OK" (translated) will be used. + \a button1Text is the text of the second button, and is optional. + \a button2Text is the text of the third button, and is optional. + \a defaultButtonNumber (0, 1 or 2) is the index of the default + button; pressing Return or Enter is the same as clicking the + default button. It defaults to 0 (the first button). \a + escapeButtonNumber is the index of the Escape button; pressing + Escape is the same as clicking this button. It defaults to -1; + supply 0, 1 or 2 to make pressing Escape equivalent to clicking + the relevant button. + + If \a parent is 0, the message box becomes an application-global + modal dialog box. If \a parent is a widget, the message box + becomes modal relative to \a parent. + + Note: If you do not specify an Escape button then if the Escape + button is pressed then -1 will be returned. It is suggested that + you specify an Escape button to prevent this from happening. + + \sa question(), warning(), critical() +*/ + +int TQMessageBox::information( TQWidget *parent, const TQString &caption, + const TQString& text, + const TQString& button0Text, + const TQString& button1Text, + const TQString& button2Text, + int defaultButtonNumber, + int escapeButtonNumber ) +{ +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::information( parent, caption, text, + button0Text, button1Text, button2Text, defaultButtonNumber, escapeButtonNumber ); +#endif + return textBox( parent, Information, caption, text, + button0Text, button1Text, button2Text, + defaultButtonNumber, escapeButtonNumber ); +} + +/*! + \overload + + Displays a question message box with caption \a caption, text \a + text and one, two or three buttons. Returns the index of the + button that was clicked (0, 1 or 2). + + \a button0Text is the text of the first button, and is optional. + If \a button0Text is not supplied, "OK" (translated) will be used. + \a button1Text is the text of the second button, and is optional. + \a button2Text is the text of the third button, and is optional. + \a defaultButtonNumber (0, 1 or 2) is the index of the default + button; pressing Return or Enter is the same as clicking the + default button. It defaults to 0 (the first button). \a + escapeButtonNumber is the index of the Escape button; pressing + Escape is the same as clicking this button. It defaults to -1; + supply 0, 1 or 2 to make pressing Escape equivalent to clicking + the relevant button. + + If \a parent is 0, the message box becomes an application-global + modal dialog box. If \a parent is a widget, the message box + becomes modal relative to \a parent. + + Note: If you do not specify an Escape button then if the Escape + button is pressed then -1 will be returned. It is suggested that + you specify an Escape button to prevent this from happening. + + \sa information(), warning(), critical() +*/ +int TQMessageBox::question( TQWidget *parent, const TQString &caption, + const TQString& text, + const TQString& button0Text, + const TQString& button1Text, + const TQString& button2Text, + int defaultButtonNumber, + int escapeButtonNumber ) +{ +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::question( parent, caption, text, + button0Text, button1Text, button2Text, defaultButtonNumber, escapeButtonNumber ); +#endif + return textBox( parent, Question, caption, text, + button0Text, button1Text, button2Text, + defaultButtonNumber, escapeButtonNumber ); +} + + +/*! + \overload + + Displays a warning message box with a caption, a text, and 1, 2 or + 3 buttons. Returns the number of the button that was clicked (0, + 1, or 2). + + \a button0Text is the text of the first button, and is optional. + If \a button0Text is not supplied, "OK" (translated) will be used. + \a button1Text is the text of the second button, and is optional, + and \a button2Text is the text of the third button, and is + optional. \a defaultButtonNumber (0, 1 or 2) is the index of the + default button; pressing Return or Enter is the same as clicking + the default button. It defaults to 0 (the first button). \a + escapeButtonNumber is the index of the Escape button; pressing + Escape is the same as clicking this button. It defaults to -1; + supply 0, 1, or 2 to make pressing Escape equivalent to clicking + the relevant button. + + If \a parent is 0, the message box becomes an application-global + modal dialog box. If \a parent is a widget, the message box + becomes modal relative to \a parent. + + Note: If you do not specify an Escape button then if the Escape + button is pressed then -1 will be returned. It is suggested that + you specify an Escape button to prevent this from happening. + + \sa information(), question(), critical() +*/ + +int TQMessageBox::warning( TQWidget *parent, const TQString &caption, + const TQString& text, + const TQString& button0Text, + const TQString& button1Text, + const TQString& button2Text, + int defaultButtonNumber, + int escapeButtonNumber ) +{ +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::warning( parent, caption, text, + button0Text, button1Text, button2Text, defaultButtonNumber, escapeButtonNumber ); +#endif + return textBox( parent, Warning, caption, text, + button0Text, button1Text, button2Text, + defaultButtonNumber, escapeButtonNumber ); +} + + +/*! + \overload + + Displays a critical error message box with a caption, a text, and + 1, 2 or 3 buttons. Returns the number of the button that was + clicked (0, 1 or 2). + + \a button0Text is the text of the first button, and is optional. + If \a button0Text is not supplied, "OK" (translated) will be used. + \a button1Text is the text of the second button, and is optional, + and \a button2Text is the text of the third button, and is + optional. \a defaultButtonNumber (0, 1 or 2) is the index of the + default button; pressing Return or Enter is the same as clicking + the default button. It defaults to 0 (the first button). \a + escapeButtonNumber is the index of the Escape button; pressing + Escape is the same as clicking this button. It defaults to -1; + supply 0, 1, or 2 to make pressing Escape equivalent to clicking + the relevant button. + + If \a parent is 0, the message box becomes an application-global + modal dialog box. If \a parent is a widget, the message box + becomes modal relative to \a parent. + + \sa information(), question(), warning() +*/ + +int TQMessageBox::critical( TQWidget *parent, const TQString &caption, + const TQString& text, + const TQString& button0Text, + const TQString& button1Text, + const TQString& button2Text, + int defaultButtonNumber, + int escapeButtonNumber ) +{ +#if defined(Q_WS_X11) + if ( qt_use_native_dialogs && TQKDEIntegration::enabled()) + return TQKDEIntegration::critical( parent, caption, text, + button0Text, button1Text, button2Text, defaultButtonNumber, escapeButtonNumber ); +#endif + return textBox( parent, Critical, caption, text, + button0Text, button1Text, button2Text, + defaultButtonNumber, escapeButtonNumber ); +} + + +/*! + Displays a simple message box about TQt, with caption \a caption + and centered over \a parent (if \a parent is not 0). The message + includes the version number of TQt being used by the application. + + This is useful for inclusion in the Help menu of an application. + See the examples/menu/menu.cpp example. + + TQApplication provides this functionality as a slot. + + \sa TQApplication::aboutTQt() +*/ + +void TQMessageBox::aboutTQt( TQWidget *parent, const TQString &caption ) +{ + TQMessageBox *mb = new TQMessageBox( parent, "qt_msgbox_about_qt" ); + Q_CHECK_PTR( mb ); + mb->setWFlags( WDestructiveClose ); + +#ifndef QT_NO_WIDGET_TOPEXTRA + TQString c = caption; + if ( c.isNull() ) + c = tr( "About TQt" ); + mb->setCaption( c ); +#endif + mb->setText( *translatedTextAboutTQt ); +#ifndef QT_NO_IMAGEIO + TQPixmap pm; + TQImage logo( (const char **)qtlogo_xpm); + if ( qGray(mb->palette().active().text().rgb()) > + qGray(mb->palette().active().base().rgb()) ) + { + // light on dark, adjust some colors (where's 10?) + logo.setColor( 0, 0xffffffff ); + logo.setColor( 1, 0xff666666 ); + logo.setColor( 2, 0xffcccc66 ); + logo.setColor( 4, 0xffcccccc ); + logo.setColor( 6, 0xffffff66 ); + logo.setColor( 7, 0xff999999 ); + logo.setColor( 8, 0xff3333ff ); + logo.setColor( 9, 0xffffff33 ); + logo.setColor( 11, 0xffcccc99 ); + } + if ( pm.convertFromImage( logo ) ) + mb->setIconPixmap( pm ); +#endif + mb->setButtonText( 0, tr("OK") ); + if ( mb->mbd && mb->mbd->pb[0] ) { + mb->mbd->pb[0]->setAutoDefault( TRUE ); + mb->mbd->pb[0]->setFocusPolicy( TQWidget::StrongFocus ); + mb->mbd->pb[0]->setDefault( TRUE ); + mb->mbd->pb[0]->setFocus(); + } + mb->exec(); +} + +/*! + \reimp +*/ + +void TQMessageBox::setIcon( const TQPixmap &pix ) +{ + //reimplemented to avoid compiler warning. +#ifndef QT_NO_WIDGET_TOPEXTRA + TQDialog::setIcon( pix ); +#endif +} + + +/*! + \property TQMessageBox::textFormat + \brief the format of the text displayed by the message box + + The current text format used by the message box. See the \l + TQt::TextFormat enum for an explanation of the possible options. + + The default format is \c AutoText. + + \sa setText() +*/ + +TQt::TextFormat TQMessageBox::textFormat() const +{ + return label->textFormat(); +} + + +void TQMessageBox::setTextFormat( TQt::TextFormat format ) +{ + label->setTextFormat( format ); +} + + +#endif diff --git a/src/dialogs/qmessagebox.h b/src/dialogs/qmessagebox.h new file mode 100644 index 000000000..27468ef0c --- /dev/null +++ b/src/dialogs/qmessagebox.h @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Definition of TQMessageBox class +** +** Created : 950503 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQMESSAGEBOX_H +#define TQMESSAGEBOX_H + +#ifndef QT_H +#include "qdialog.h" +#endif // QT_H + +#ifndef QT_NO_MESSAGEBOX + +class TQLabel; +class TQPushButton; +struct TQMessageBoxData; + +class Q_EXPORT TQMessageBox : public TQDialog +{ + Q_OBJECT + Q_ENUMS( Icon ) + Q_PROPERTY( TQString text READ text WRITE setText ) + Q_PROPERTY( Icon icon READ icon WRITE setIcon ) + Q_PROPERTY( TQPixmap iconPixmap READ iconPixmap WRITE setIconPixmap ) + Q_PROPERTY( TextFormat textFormat READ textFormat WRITE setTextFormat ) + +public: + enum Icon { NoIcon = 0, Information = 1, Warning = 2, Critical = 3, + Question = 4 }; + + TQMessageBox( TQWidget* parent=0, const char* name=0 ); + TQMessageBox( const TQString& caption, const TQString &text, Icon icon, + int button0, int button1, int button2, + TQWidget* parent=0, const char* name=0, bool modal=TRUE, + WFlags f=WStyle_DialogBorder ); + ~TQMessageBox(); + + enum { NoButton = 0, Ok = 1, Cancel = 2, Yes = 3, No = 4, Abort = 5, + Retry = 6, Ignore = 7, YesAll = 8, NoAll = 9, ButtonMask = 0xff, + Default = 0x100, Escape = 0x200, FlagMask = 0x300 }; + + static int information( TQWidget *parent, const TQString &caption, + const TQString& text, + int button0, int button1=0, int button2=0 ); + static int information( TQWidget *parent, const TQString &caption, + const TQString& text, + const TQString& button0Text = TQString::null, + const TQString& button1Text = TQString::null, + const TQString& button2Text = TQString::null, + int defaultButtonNumber = 0, + int escapeButtonNumber = -1 ); + + static int question( TQWidget *parent, const TQString &caption, + const TQString& text, + int button0, int button1=0, int button2=0 ); + static int question( TQWidget *parent, const TQString &caption, + const TQString& text, + const TQString& button0Text = TQString::null, + const TQString& button1Text = TQString::null, + const TQString& button2Text = TQString::null, + int defaultButtonNumber = 0, + int escapeButtonNumber = -1 ); + + static int warning( TQWidget *parent, const TQString &caption, + const TQString& text, + int button0, int button1, int button2=0 ); + static int warning( TQWidget *parent, const TQString &caption, + const TQString& text, + const TQString& button0Text = TQString::null, + const TQString& button1Text = TQString::null, + const TQString& button2Text = TQString::null, + int defaultButtonNumber = 0, + int escapeButtonNumber = -1 ); + + static int critical( TQWidget *parent, const TQString &caption, + const TQString& text, + int button0, int button1, int button2=0 ); + static int critical( TQWidget *parent, const TQString &caption, + const TQString& text, + const TQString& button0Text = TQString::null, + const TQString& button1Text = TQString::null, + const TQString& button2Text = TQString::null, + int defaultButtonNumber = 0, + int escapeButtonNumber = -1 ); + + static void about( TQWidget *parent, const TQString &caption, + const TQString& text ); + + static void aboutTQt( TQWidget *parent, + const TQString& caption=TQString::null ); + +/* OBSOLETE */ + static int message( const TQString &caption, + const TQString& text, + const TQString& buttonText=TQString::null, + TQWidget *parent=0, const char * =0 ) { + return TQMessageBox::information( parent, caption, text, + buttonText.isEmpty() + ? tr("OK") : buttonText ) == 0; + } + +/* OBSOLETE */ + static bool query( const TQString &caption, + const TQString& text, + const TQString& yesButtonText=TQString::null, + const TQString& noButtonText=TQString::null, + TQWidget *parent=0, const char * = 0 ) { + return TQMessageBox::information( parent, caption, text, + yesButtonText.isEmpty() + ? tr("OK") : yesButtonText, + noButtonText ) == 0; + } + + TQString text() const; + void setText( const TQString &); + + Icon icon() const; + + void setIcon( Icon ); + void setIcon( const TQPixmap & ); + + const TQPixmap *iconPixmap() const; + void setIconPixmap( const TQPixmap & ); + + TQString buttonText( int button ) const; + void setButtonText( int button, const TQString &); + + void adjustSize(); + +/* OBSOLETE */ + static TQPixmap standardIcon( Icon icon, GUIStyle ); + + static TQPixmap standardIcon( Icon icon ); + + TextFormat textFormat() const; + void setTextFormat( TextFormat ); + +protected: + void resizeEvent( TQResizeEvent * ); + void showEvent( TQShowEvent * ); + void closeEvent( TQCloseEvent * ); + void keyPressEvent( TQKeyEvent * ); + void styleChanged( TQStyle& ); + +private slots: + void buttonClicked(); + +private: + void init( int, int, int ); + int indexOf( int ) const; + void resizeButtons(); + TQLabel *label; + TQMessageBoxData *mbd; + void *reserved1; + void *reserved2; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQMessageBox( const TQMessageBox & ); + TQMessageBox &operator=( const TQMessageBox & ); +#endif +}; + +/* +* Macro to be used at the beginning of main(), e.g. +* +* #include <qapplication.h> +* #include <qmessagebox.h> +* int main( int argc, char**argv ) +* { +* QT_RETQUIRE_VERSION( argc, argv, "3.0.5" ) +* ... +* } +*/ +#define QT_RETQUIRE_VERSION( argc, argv, str ) { TQString s=TQString::fromLatin1(str);\ +TQString sq=TQString::fromLatin1(qVersion()); if ( (sq.section('.',0,0).toInt()<<16)+\ +(sq.section('.',1,1).toInt()<<8)+sq.section('.',2,2).toInt()<(s.section('.',0,0).toInt()<<16)+\ +(s.section('.',1,1).toInt()<<8)+s.section('.',2,2).toInt() ){if ( !qApp){ int c=0; new \ +TQApplication(argc,argv);} TQString s = TQApplication::tr("Executable '%1' retquires TQt "\ + "%2, found TQt %3.").arg(TQString::fromLatin1(qAppName())).arg(TQString::fromLatin1(\ +str)).arg(TQString::fromLatin1(qVersion()) ); TQMessageBox::critical( 0, TQApplication::tr(\ +"Incompatible TQt Library Error" ), s, TQMessageBox::Abort,0 ); qFatal(s.ascii()); }} + + +#endif // QT_NO_MESSAGEBOX + +#endif // TQMESSAGEBOX_H diff --git a/src/dialogs/qprintdialog.cpp b/src/dialogs/qprintdialog.cpp new file mode 100644 index 000000000..9d6e82b81 --- /dev/null +++ b/src/dialogs/qprintdialog.cpp @@ -0,0 +1,1672 @@ +/**************************************************************************** +** +** Implementation of internal print dialog (X11) used by TQPrinter::select(). +** +** Created : 950829 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qprintdialog.h" + +#ifndef QT_NO_PRINTDIALOG + +#include "qfiledialog.h" +#include "qfile.h" +#include "qtextstream.h" +#include "qcombobox.h" +#include "qframe.h" +#include "qlabel.h" +#include "qlineedit.h" +#include "qpushbutton.h" +#include "qprinter.h" +#include "qlistview.h" +#include "qlayout.h" +#include "qbuttongroup.h" +#include "qradiobutton.h" +#include "qspinbox.h" +#include "qapplication.h" +#include "qheader.h" +#include "qstyle.h" +#include "qstring.h" +#include "qregexp.h" +#if !defined(QT_NO_CUPS) || !defined(QT_NO_NIS) +#include "qlibrary.h" +#endif + +#ifndef QT_NO_NIS + +#ifndef BOOL_DEFINED +#define BOOL_DEFINED +#endif + +#include <rpcsvc/ypclnt.h> +#include <rpcsvc/yp_prot.h> + +// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED. +#if defined(connect) +# undef connect +#endif + +#endif // QT_NO_NIS + +// UNIX Large File Support redefines open -> open64 +#if defined(open) +# undef open +#endif + +#include <ctype.h> +#include <stdlib.h> + + +class TQPrintDialogSpinBox : public TQSpinBox +{ +public: + TQPrintDialogSpinBox(int min, int max, int steps, TQWidget *parent, const char *name) + : TQSpinBox(min, max, steps, parent, name) + {} + + void interpretText() + { + TQSpinBox::interpretText(); + } +}; + + + + +enum { Success = 's', Unavail = 'u', NotFound = 'n', TryAgain = 't' }; +enum { Continue = 'c', Return = 'r' }; + +class TQPrintDialogPrivate +{ +public: + TQPrinter * printer; + + TQButtonGroup * printerOrFile; + + bool outputToFile; + TQListView * printers; + TQLineEdit * fileName; + TQPushButton * browse, *ok; + + TQButtonGroup * printRange; + TQLabel * firstPageLabel; + TQPrintDialogSpinBox * firstPage; + TQLabel * lastPageLabel; + TQPrintDialogSpinBox * lastPage; + TQRadioButton * printAllButton; + TQRadioButton * printRangeButton; + TQRadioButton * printSelectionButton; + TQRadioButton * printToFileButton; + TQComboBox *orientationCombo, *sizeCombo; + + TQPrinter::PageSize pageSize; + TQPrinter::Orientation orientation; + + TQButtonGroup * pageOrder; + TQPrinter::PageOrder pageOrder2; + + TQButtonGroup * colorMode; + TQPrinter::ColorMode colorMode2; + + TQPrintDialogSpinBox * copies; + int numCopies; + + TQBoxLayout *customLayout; + + TQPrinter::PageSize indexToPageSize[TQPrinter::NPageSize]; +}; + + +typedef void (*Q_PrintDialogHook)(TQListView *); +static Q_PrintDialogHook addPrinterHook = 0; + +void qt_set_printdialog_hook( Q_PrintDialogHook hook ) +{ + addPrinterHook = hook; +} + +static void isc( TQPrintDialogPrivate * d, const TQString & text, + TQPrinter::PageSize ps ); + +class TQPrinterListViewItem : public TQListViewItem +{ +public: + TQPrinterListViewItem( TQListView * printers, const TQString& name, + const TQString& host, const TQString& comment, + const TQStringList& aliases ) + : TQListViewItem( printers, name, host, comment ), ali( aliases ) { } + + bool samePrinter( const TQString& name ) { + return text( 0 ) == name || ali.find( name ) != ali.end(); + } + + TQStringList ali; +}; + +static void perhapsAddPrinter( TQListView * printers, const TQString &name, + TQString host, TQString comment, + TQStringList aliases = TQStringList() ) +{ + const TQListViewItem * i = printers->firstChild(); + while ( i && !((TQPrinterListViewItem *) i)->samePrinter(name) ) + i = i->nextSibling(); + if ( i ) + return; + if ( host.isEmpty() ) + host = TQPrintDialog::tr( "locally connected" ); + (void)new TQPrinterListViewItem( printers, + name.simplifyWhiteSpace(), + host.simplifyWhiteSpace(), + comment.simplifyWhiteSpace(), aliases ); +} + +static void parsePrinterDesc( TQString printerDesc, TQListView * printers ) +{ + if ( printerDesc.length() < 1 ) + return; + + printerDesc = printerDesc.simplifyWhiteSpace(); + int i = printerDesc.find( ':' ); + TQString printerName, printerComment, printerHost; + TQStringList aliases; + + if ( i >= 0 ) { + // have ':' want '|' + int j = printerDesc.find( '|' ); + if ( j > 0 && j < i ) { + printerName = printerDesc.left( j ); + aliases = TQStringList::split( '|', + printerDesc.mid(j + 1, i - j - 1) ); + // try extracting a comment from the aliases + printerComment = TQPrintDialog::tr( "Aliases: %1" ) + .arg( aliases.join(", ") ); + } else { + printerName = printerDesc.left( i ); + } + // look for lprng pseudo all printers entry + i = printerDesc.find( TQRegExp(TQString::fromLatin1(": *all *=")) ); + if ( i >= 0 ) + printerName = ""; + // look for signs of this being a remote printer + i = printerDesc.find( TQRegExp(TQString::fromLatin1(": *rm *=")) ); + if ( i >= 0 ) { + // point k at the end of remote host name + while ( printerDesc[i] != '=' ) + i++; + while ( printerDesc[i] == '=' || printerDesc[i].isSpace() ) + i++; + j = i; + while ( j < (int)printerDesc.length() && printerDesc[j] != ':' ) + j++; + + // and stuff that into the string + printerHost = printerDesc.mid( i, j - i ); + } + } + if ( printerName.length() ) + perhapsAddPrinter( printers, printerName, printerHost, printerComment, + aliases ); +} + +static int parsePrintcap( TQListView * printers, const TQString& fileName ) +{ + TQFile printcap( fileName ); + if ( !printcap.open( IO_ReadOnly ) ) + return NotFound; + + char * line_ascii = new char[1025]; + line_ascii[1024] = '\0'; + + TQString printerDesc; + bool atEnd = FALSE; + + while ( !atEnd ) { + if ( printcap.atEnd() || printcap.readLine( line_ascii, 1024 ) <= 0 ) + atEnd = TRUE; + TQString line = line_ascii; + line = line.stripWhiteSpace(); + if ( line.length() >= 1 && line[int(line.length()) - 1] == '\\' ) + line.truncate( line.length() - 1 ); + if ( line[0] == '#' ) { + if ( !atEnd ) + continue; + } else if ( line[0] == '|' || line[0] == ':' ) { + printerDesc += line; + if ( !atEnd ) + continue; + } + + parsePrinterDesc( printerDesc, printers ); + + // add the first line of the new printer definition + printerDesc = line; + } + delete[] line_ascii; + return Success; +} + + +// solaris, not 2.6 +static void parseEtcLpPrinters( TQListView * printers ) +{ + TQDir lp( TQString::fromLatin1("/etc/lp/printers") ); + const TQFileInfoList * dirs = lp.entryInfoList(); + if ( !dirs ) + return; + + TQFileInfoListIterator it( *dirs ); + TQFileInfo *printer; + TQString tmp; + while ( (printer = it.current()) != 0 ) { + ++it; + if ( printer->isDir() ) { + tmp.sprintf( "/etc/lp/printers/%s/configuration", + printer->fileName().ascii() ); + TQFile configuration( tmp ); + char * line = new char[1025]; + TQString remote( TQString::fromLatin1("Remote:") ); + TQString contentType( TQString::fromLatin1("Content types:") ); + TQString printerHost; + bool canPrintPostscript = FALSE; + if ( configuration.open( IO_ReadOnly ) ) { + while ( !configuration.atEnd() && + configuration.readLine( line, 1024 ) > 0 ) { + if ( TQString::fromLatin1(line).startsWith( remote ) ) { + const char * p = line; + while ( *p != ':' ) + p++; + p++; + while ( isspace((uchar) *p) ) + p++; + printerHost = TQString::fromLocal8Bit(p); + printerHost = printerHost.simplifyWhiteSpace(); + } else if ( TQString::fromLatin1(line).startsWith( contentType ) ) { + char * p = line; + while ( *p != ':' ) + p++; + p++; + char * e; + while ( *p ) { + while ( isspace((uchar) *p) ) + p++; + if ( *p ) { + char s; + e = p; + while ( isalnum((uchar) *e) ) + e++; + s = *e; + *e = '\0'; + if ( !qstrcmp( p, "postscript" ) || + !qstrcmp( p, "any" ) ) + canPrintPostscript = TRUE; + *e = s; + if ( s == ',' ) + e++; + p = e; + } + } + } + } + if ( canPrintPostscript ) + perhapsAddPrinter( printers, printer->fileName(), + printerHost, TQString::fromLatin1("") ); + } + delete[] line; + } + } +} + + +// solaris 2.6 +static char * parsePrintersConf( TQListView * printers, bool *found = 0 ) +{ + TQFile pc( TQString::fromLatin1("/etc/printers.conf") ); + if ( !pc.open( IO_ReadOnly ) ) { + if ( found ) + *found = FALSE; + return 0; + } + if ( found ) + *found = TRUE; + + char * line = new char[1025]; + line[1024] = '\0'; + + TQString printerDesc; + int lineLength = 0; + + char * defaultPrinter = 0; + + while ( !pc.atEnd() && + (lineLength=pc.readLine( line, 1024 )) > 0 ) { + if ( *line == '#' ) { + *line = '\0'; + lineLength = 0; + } + if ( lineLength >= 2 && line[lineLength-2] == '\\' ) { + line[lineLength-2] = '\0'; + printerDesc += TQString::fromLocal8Bit(line); + } else { + printerDesc += TQString::fromLocal8Bit(line); + printerDesc = printerDesc.simplifyWhiteSpace(); + int i = printerDesc.find( ':' ); + TQString printerName, printerHost, printerComment; + TQStringList aliases; + if ( i >= 0 ) { + // have : want | + int j = printerDesc.find( '|', 0 ); + if ( j >= i ) + j = -1; + printerName = printerDesc.mid( 0, j < 0 ? i : j ); + if ( printerName == TQString::fromLatin1("_default") ) { + i = printerDesc.find( + TQRegExp( TQString::fromLatin1(": *use *=") ) ); + while ( printerDesc[i] != '=' ) + i++; + while ( printerDesc[i] == '=' || printerDesc[i].isSpace() ) + i++; + j = i; + while ( j < (int)printerDesc.length() && + printerDesc[j] != ':' && printerDesc[j] != ',' ) + j++; + // that's our default printer + defaultPrinter = + qstrdup( printerDesc.mid( i, j-i ).ascii() ); + printerName = ""; + printerDesc = ""; + } else if ( printerName == TQString::fromLatin1("_all") ) { + // skip it.. any other cases we want to skip? + printerName = ""; + printerDesc = ""; + } + + if ( j > 0 ) { + // try extracting a comment from the aliases + aliases = TQStringList::split( '|', + printerDesc.mid(j + 1, i - j - 1) ); + printerComment = TQPrintDialog::tr( "Aliases: %1" ) + .arg( aliases.join(", ") ); + } + // look for signs of this being a remote printer + i = printerDesc.find( + TQRegExp( TQString::fromLatin1(": *bsdaddr *=") ) ); + if ( i >= 0 ) { + // point k at the end of remote host name + while ( printerDesc[i] != '=' ) + i++; + while ( printerDesc[i] == '=' || printerDesc[i].isSpace() ) + i++; + j = i; + while ( j < (int)printerDesc.length() && + printerDesc[j] != ':' && printerDesc[j] != ',' ) + j++; + // and stuff that into the string + printerHost = printerDesc.mid( i, j-i ); + // maybe stick the remote printer name into the comment + if ( printerDesc[j] == ',' ) { + i = ++j; + while ( printerDesc[i].isSpace() ) + i++; + j = i; + while ( j < (int)printerDesc.length() && + printerDesc[j] != ':' && printerDesc[j] != ',' ) + j++; + if ( printerName != printerDesc.mid( i, j-i ) ) { + printerComment = + TQString::fromLatin1("Remote name: "); + printerComment += printerDesc.mid( i, j-i ); + } + } + } + } + if ( printerComment == ":" ) + printerComment = ""; // for cups + if ( printerName.length() ) + perhapsAddPrinter( printers, printerName, printerHost, + printerComment, aliases ); + // chop away the line, for processing the next one + printerDesc = ""; + } + } + delete[] line; + return defaultPrinter; +} + +#ifndef QT_NO_NIS + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif + +static int foreach( int /* status */, char * /* key */, int /* keyLen */, + char * val, int valLen, char * data ) +{ + parsePrinterDesc( TQString::fromLatin1(val, valLen), (TQListView *) data ); + return 0; +} + +#if defined(Q_C_CALLBACKS) +} +#endif + +static int retrieveNisPrinters( TQListView * printers ) +{ + typedef int (*WildCast)( int, char *, int, char *, int, char * ); + char printersConfByname[] = "printers.conf.byname"; + char *domain; + int err; + + TQLibrary lib( "nsl" ); + typedef int (*ypGetDefaultDomain)(char **); + ypGetDefaultDomain _ypGetDefaultDomain = (ypGetDefaultDomain)lib.resolve( "yp_get_default_domain" ); + typedef int (*ypAll)(const char *, const char *, const struct ypall_callback *); + ypAll _ypAll = (ypAll)lib.resolve( "yp_all" ); + + if ( _ypGetDefaultDomain && _ypAll ) { + err = _ypGetDefaultDomain( &domain ); + if ( err == 0 ) { + ypall_callback cb; + // wild cast to support K&R-style system headers + (WildCast &) cb.foreach = (WildCast) foreach; + cb.data = (char *) printers; + err = _ypAll( domain, printersConfByname, &cb ); + } + if ( !err ) + return Success; + } + return Unavail; +} + +#endif // QT_NO_NIS + +static char *parseNsswitchPrintersEntry( TQListView * printers, char *line ) +{ +#define skipSpaces() \ + while ( isspace((uchar) line[k]) ) \ + k++ + + char *defaultPrinter = 0; + bool stop = FALSE; + int lastStatus = NotFound; + + int k = 8; + skipSpaces(); + if ( line[k] != ':' ) + return 0; + k++; + + char *cp = strchr( line, '#' ); + if ( cp != 0 ) + *cp = '\0'; + + while ( line[k] != '\0' ) { + if ( isspace((uchar) line[k]) ) { + k++; + } else if ( line[k] == '[' ) { + k++; + skipSpaces(); + while ( line[k] != '\0' ) { + char status = tolower( line[k] ); + char action = '?'; + + while ( line[k] != '=' && line[k] != ']' && + line[k] != '\0' ) + k++; + if ( line[k] == '=' ) { + k++; + skipSpaces(); + action = tolower( line[k] ); + while ( line[k] != '\0' && !isspace((uchar) line[k]) && line[k] != ']' ) + k++; + } else if ( line[k] == ']' ) { + k++; + break; + } + skipSpaces(); + + if ( lastStatus == status ) + stop = ( action == (char) Return ); + } + } else { + if ( stop ) + break; + + TQCString source; + while ( line[k] != '\0' && !isspace((uchar) line[k]) && line[k] != '[' ) { + source += line[k]; + k++; + } + + if ( source == "user" ) { + lastStatus = parsePrintcap( printers, + TQDir::homeDirPath() + "/.printers" ); + } else if ( source == "files" ) { + bool found; + defaultPrinter = parsePrintersConf( printers, &found ); + if ( found ) + lastStatus = Success; +#ifndef QT_NO_NIS + } else if ( source == "nis" ) { + lastStatus = retrieveNisPrinters( printers ); +#endif + } else { + // nisplus, dns, etc., are not implemented yet + lastStatus = NotFound; + } + stop = ( lastStatus == Success ); + } + } + return defaultPrinter; +} + +static char *parseNsswitchConf( TQListView * printers ) +{ + TQFile nc( TQString::fromLatin1("/etc/nsswitch.conf") ); + if ( !nc.open(IO_ReadOnly) ) + return 0; + + char *defaultPrinter = 0; + + char *line = new char[1025]; + line[1024] = '\0'; + + while ( !nc.atEnd() && + nc.readLine(line, 1024) > 0 ) { + if ( strncmp(line, "printers", 8) == 0 ) { + defaultPrinter = parseNsswitchPrintersEntry( printers, line ); + delete[] line; + return defaultPrinter; + } + } + + strcpy( line, "printers: user files nis nisplus xfn" ); + defaultPrinter = parseNsswitchPrintersEntry( printers, line ); + delete[] line; + return defaultPrinter; +} + +// HP-UX +static void parseEtcLpMember( TQListView * printers ) +{ + TQDir lp( TQString::fromLatin1("/etc/lp/member") ); + if ( !lp.exists() ) + return; + const TQFileInfoList * dirs = lp.entryInfoList(); + if ( !dirs ) + return; + + TQFileInfoListIterator it( *dirs ); + TQFileInfo *printer; + TQString tmp; + while ( (printer = it.current()) != 0 ) { + ++it; + // I haven't found any real documentation, so I'm guessing that + // since lpstat uses /etc/lp/member rather than one of the + // other directories, it's the one to use. I did not find a + // decent way to locate aliases and remote printers. + if ( printer->isFile() ) + perhapsAddPrinter( printers, printer->fileName(), + TQPrintDialog::tr("unknown"), + TQString::fromLatin1("") ); + } +} + +// IRIX 6.x +static void parseSpoolInterface( TQListView * printers ) +{ + TQDir lp( TQString::fromLatin1("/usr/spool/lp/interface") ); + if ( !lp.exists() ) + return; + const TQFileInfoList * files = lp.entryInfoList(); + if( !files ) + return; + + TQFileInfoListIterator it( *files ); + TQFileInfo *printer; + while ( (printer = it.current()) != 0) { + ++it; + + if ( !printer->isFile() ) + continue; + + // parse out some information + TQFile configFile( printer->filePath() ); + if ( !configFile.open( IO_ReadOnly ) ) + continue; + + TQCString line( 1025 ); + TQString namePrinter; + TQString hostName; + TQString hostPrinter; + TQString printerType; + + TQString nameKey( TQString::fromLatin1("NAME=") ); + TQString typeKey( TQString::fromLatin1("TYPE=") ); + TQString hostKey( TQString::fromLatin1("HOSTNAME=") ); + TQString hostPrinterKey( TQString::fromLatin1("HOSTPRINTER=") ); + + while ( !configFile.atEnd() && + (configFile.readLine(line.data(), 1024)) > 0 ) { + TQString uline = line; + if ( uline.startsWith( typeKey ) ) { + printerType = line.mid( nameKey.length() ); + printerType = printerType.simplifyWhiteSpace(); + } else if ( uline.startsWith( hostKey ) ) { + hostName = line.mid( hostKey.length() ); + hostName = hostName.simplifyWhiteSpace(); + } else if ( uline.startsWith( hostPrinterKey ) ) { + hostPrinter = line.mid( hostPrinterKey.length() ); + hostPrinter = hostPrinter.simplifyWhiteSpace(); + } else if ( uline.startsWith( nameKey ) ) { + namePrinter = line.mid( nameKey.length() ); + namePrinter = namePrinter.simplifyWhiteSpace(); + } + } + configFile.close(); + + printerType = printerType.stripWhiteSpace(); + if ( printerType.find("postscript", 0, FALSE) < 0 ) + continue; + + int ii = 0; + while ( (ii = namePrinter.find('"', ii)) >= 0 ) + namePrinter.remove( ii, 1 ); + + if ( hostName.isEmpty() || hostPrinter.isEmpty() ) { + perhapsAddPrinter( printers, printer->fileName(), + TQString::fromLatin1(""), namePrinter ); + } else { + TQString comment; + comment = namePrinter; + comment += " ("; + comment += hostPrinter; + comment += ")"; + perhapsAddPrinter( printers, printer->fileName(), + hostName, comment ); + } + } +} + + +// Every unix must have its own. It's a standard. Here is AIX. +static void parseQconfig( TQListView * printers ) +{ + TQFile qconfig( TQString::fromLatin1("/etc/qconfig") ); + if ( !qconfig.open( IO_ReadOnly ) ) + return; + + TQTextStream ts( &qconfig ); + TQString line; + + TQString stanzaName; // either a queue or a device name + bool up = TRUE; // queue up? default TRUE, can be FALSE + TQString remoteHost; // null if local + TQString deviceName; // null if remote + + TQRegExp newStanza( TQString::fromLatin1("^[0-z\\-]+:$") ); + + // our basic strategy here is to process each line, detecting new + // stanzas. each time we see a new stanza, we check if the + // previous stanza was a valid queue for a) a remote printer or b) + // a local printer. if it wasn't, we assume that what we see is + // the start of the first stanza, or that the previous stanza was + // a device stanza, or that there is some syntax error (we don't + // report those). + + do { + line = ts.readLine(); + bool indented = line[0].isSpace(); + line = line.simplifyWhiteSpace(); + + int i = line.find('='); + if ( indented && i != -1 ) { // line in stanza + TQString variable = line.left( i ).simplifyWhiteSpace(); + TQString value=line.mid( i+1, line.length() ).simplifyWhiteSpace(); + if ( variable == TQString::fromLatin1("device") ) + deviceName = value; + else if ( variable == TQString::fromLatin1("host") ) + remoteHost = value; + else if ( variable == TQString::fromLatin1("up") ) + up = !(value.lower() == TQString::fromLatin1("false")); + } else if ( line[0] == '*' ) { // comment + // nothing to do + } else if ( ts.atEnd() || // end of file, or beginning of new stanza + ( !indented && line.find( newStanza ) != -1 ) ) { + if ( up && stanzaName.length() > 0 && stanzaName.length() < 21 ) { + if ( remoteHost.length() ) // remote printer + perhapsAddPrinter( printers, stanzaName, remoteHost, + TQString::null ); + else if ( deviceName.length() ) // local printer + perhapsAddPrinter( printers, stanzaName, TQString::null, + TQString::null ); + } + line.truncate( line.length()-1 ); + if ( line.length() >= 1 && line.length() <= 20 ) + stanzaName = line; + up = TRUE; + remoteHost = TQString::null; + deviceName = TQString::null; + } else { + // syntax error? ignore. + } + } while ( !ts.atEnd() ); +} + + +#ifndef QT_NO_CUPS +#include <cups/cups.h> + +static char * parseCupsOutput( TQListView * printers ) +{ + char * defaultPrinter = 0; + int nd; + cups_dest_t * d; + TQLibrary lib( "cups" ); + typedef int (*CupsGetDests)(cups_dest_t **dests); + CupsGetDests _cupsGetDests = (CupsGetDests)lib.resolve( "cupsGetDests" ); + if ( _cupsGetDests ) { + nd = _cupsGetDests( &d ); + if ( nd < 1 ) + return 0; + + int n = 0; + while ( n < nd ) { + perhapsAddPrinter( printers, d[n].name, + TQPrintDialog::tr("Unknown Location"), 0 ); + if ( d[n].is_default && !defaultPrinter ) + defaultPrinter = qstrdup( d[n].instance ); + n++; + } + } + return defaultPrinter; +} +#endif + +static TQPrintDialog * globalPrintDialog = 0; + +static void qpd_cleanup_globaldialog() +{ + if ( globalPrintDialog != 0 ) + delete globalPrintDialog; + globalPrintDialog = 0; +} + +/*! + \class TQPrintDialog qprintdialog.h + + \brief The TQPrintDialog class provides a dialog for specifying + the printer's configuration. + + \internal + + \warning The use of this class is not recommended since it is not + present on all platforms; use TQPrinter::setup() instead. + + \omit + + (ingroup dialogs) + + THIS DOCUMENTATION IS Not Revised. It must be revised before + becoming public API. + + It encompasses both the sort of details needed for doing a simple + print-out and some print configuration setup. + + The easiest way to use the class is through the static + function getPrinterSetup(). You can also subclass the TQPrintDialog + and add some custom buttons with addButton() to extend the + functionality of the print dialog. + + <img src="qprintdlg-m.png"><br clear=all> + The printer dialog, on a large screen, in Motif style. +*/ + + +/*! Constructs a new modal printer dialog that configures \a prn and is a + child of \a parent named \a name. +*/ + +TQPrintDialog::TQPrintDialog( TQPrinter *prn, TQWidget *parent, const char *name ) + : TQDialog( parent, name, TRUE ) +{ + d = new TQPrintDialogPrivate; + d->numCopies = 1; + + TQBoxLayout * tll = new TQBoxLayout( this, TQBoxLayout::Down, 12, 0 ); + + // destination + TQGroupBox * g; + g = setupDestination(); + tll->addWidget( g, 1 ); + + tll->addSpacing( 12 ); + + // printer and paper settings + TQBoxLayout * lay = new TQBoxLayout( TQBoxLayout::LeftToRight ); + tll->addLayout( lay ); + + g = setupPrinterSettings(); + lay->addWidget( g, 1 ); + + lay->addSpacing( 12 ); + + g = setupPaper(); + lay->addWidget( g ); + + tll->addSpacing( 12 ); + + // options + g = setupOptions(); + tll->addWidget( g ); + tll->addSpacing( 12 ); + + TQBoxLayout *l = new TQBoxLayout( TQBoxLayout::LeftToRight ); + d->customLayout = new TQBoxLayout( TQBoxLayout::LeftToRight ); + tll->addLayout( l ); + l->addLayout( d->customLayout ); + l->addStretch(); + tll->addSpacing( 12 ); + + // buttons + TQBoxLayout *horiz = new TQBoxLayout( TQBoxLayout::LeftToRight ); + tll->addLayout( horiz ); + + bool rightalign = + bool(style().styleHint(TQStyle::SH_PrintDialog_RightAlignButtons, this)); + + if (rightalign) + horiz->addStretch( 1 ); + + d->ok = new TQPushButton( this, "ok" ); + d->ok->setText( tr("OK") ); + d->ok->setDefault( TRUE ); + horiz->addWidget( d->ok ); + if (! rightalign) + horiz->addStretch( 1 ); + horiz->addSpacing( 6 ); + + TQPushButton * cancel = new TQPushButton( this, "cancel" ); + cancel->setText( tr("Cancel") ); + horiz->addWidget( cancel ); + + TQSize s1 = d->ok->sizeHint(); + TQSize s2 = cancel->sizeHint(); + s1 = TQSize( TQMAX(s1.width(), s2.width()), + TQMAX(s1.height(), s2.height()) ); + + d->ok->setFixedSize( s1 ); + cancel->setFixedSize( s1 ); + + tll->activate(); + + connect( d->ok, SIGNAL(clicked()), SLOT(okClicked()) ); + connect( cancel, SIGNAL(clicked()), SLOT(reject()) ); + + TQSize ms( minimumSize() ); + TQSize ss( TQApplication::desktop()->screenGeometry( pos() ).size() ); + if ( ms.height() < 512 && ss.height() >= 600 ) + ms.setHeight( 512 ); + else if ( ms.height() < 460 && ss.height() >= 480 ) + ms.setHeight( 460 ); + resize( ms ); + + setPrinter( prn, TRUE ); + d->printers->setFocus(); +} + + +/*! Destroys the object and frees any allocated resources. Does not + delete the associated TQPrinter object. +*/ + +TQPrintDialog::~TQPrintDialog() +{ + if ( this == globalPrintDialog ) + globalPrintDialog = 0; + delete d; +} + +/*! + This method allows you to specify a global print dialog, given in \a + pd, that will be used instead of the default dialog provided by TQt. + + This is useful, since there are many different printing systems on + Unix, and we cannot support all of them. Calling this method before + using a printer for the first time allows you to set up your own + print dialog. + + \sa setupPrinters() +*/ +void TQPrintDialog::setGlobalPrintDialog( TQPrintDialog *pd ) +{ + TQPrintDialog *oldPd = globalPrintDialog; + globalPrintDialog = pd; + if ( oldPd ) + delete oldPd; + else + qAddPostRoutine( qpd_cleanup_globaldialog ); + globalPrintDialog->adjustSize(); +} + +TQGroupBox * TQPrintDialog::setupPrinterSettings() +{ + TQGroupBox * g = new TQGroupBox( 1, Horizontal, tr( "Printer settings"), + this, "settings group box" ); + + d->colorMode = new TQButtonGroup( this ); + d->colorMode->hide(); + connect( d->colorMode, SIGNAL(clicked(int)), + this, SLOT(colorModeSelected(int)) ); + + TQRadioButton *rb; + rb = new TQRadioButton( tr( "Print in color if available" ), + g, "color" ); + d->colorMode->insert( rb, TQPrinter::Color ); + rb->setChecked( TRUE ); + + rb = new TQRadioButton( tr("Print in grayscale"), + g, "graysacle" ); + d->colorMode->insert( rb, TQPrinter::GrayScale ); + + return g; +} + +TQGroupBox * TQPrintDialog::setupDestination() +{ + TQGroupBox * g = new TQGroupBox( 0, Horizontal, tr( "Print destination"), + this, "destination group box" ); + + TQBoxLayout * tll = new TQBoxLayout( g->layout(), TQBoxLayout::Down ); + + d->printerOrFile = new TQButtonGroup( this ); + d->printerOrFile->hide(); + connect( d->printerOrFile, SIGNAL(clicked(int)), + this, SLOT(printerOrFileSelected(int)) ); + + // printer radio button, list + TQRadioButton * rb = new TQRadioButton( tr( "Print to printer:" ), g, + "printer" ); + tll->addWidget( rb ); + d->printerOrFile->insert( rb, 0 ); + rb->setChecked( TRUE ); + d->outputToFile = FALSE; + + TQBoxLayout * horiz = new TQBoxLayout( TQBoxLayout::LeftToRight ); + tll->addLayout( horiz, 3 ); + horiz->addSpacing( 19 ); + + d->printers = new TQListView( g, "list of printers" ); + d->printers->setAllColumnsShowFocus( TRUE ); + d->printers->addColumn( tr("Printer"), 125 ); + d->printers->addColumn( tr("Host"), 125 ); + d->printers->addColumn( tr("Comment"), 150 ); + +#if defined(Q_OS_UNIX) + char * etcLpDefault = 0; + +#ifndef QT_NO_CUPS + etcLpDefault = parseCupsOutput( d->printers ); +#endif + if ( d->printers->childCount() == 0 ) { + // we only use other schemes when cups fails. + + parsePrintcap( d->printers, TQString::fromLatin1("/etc/printcap") ); + parseEtcLpMember( d->printers ); + parseSpoolInterface( d->printers ); + parseQconfig( d->printers ); + if ( addPrinterHook ) + (*addPrinterHook)( d->printers ); + + TQFileInfo f; + f.setFile( TQString::fromLatin1("/etc/lp/printers") ); + if ( f.isDir() ) { + parseEtcLpPrinters( d->printers ); + TQFile def( TQString::fromLatin1("/etc/lp/default") ); + if ( def.open( IO_ReadOnly ) ) { + if ( etcLpDefault ) + delete[] etcLpDefault; + etcLpDefault = new char[1025]; + def.readLine( etcLpDefault, 1024 ); + char * p = etcLpDefault; + while ( p && *p ) { + if ( !isprint((uchar) *p) || isspace((uchar) *p) ) + *p = 0; + else + p++; + } + } + } + + char * def = 0; + f.setFile( TQString::fromLatin1("/etc/nsswitch.conf") ); + if ( f.isFile() ) { + def = parseNsswitchConf( d->printers ); + } else { + f.setFile( TQString::fromLatin1("/etc/printers.conf") ); + if ( f.isFile() ) + def = parsePrintersConf( d->printers ); + } + + if ( def ) { + if ( etcLpDefault ) + delete[] etcLpDefault; + etcLpDefault = def; + } + } + + // all printers hopefully known. try to find a good default + TQString dollarPrinter; + { + const char * t = getenv( "PRINTER" ); + if ( !t || !*t ) + t = getenv( "LPDEST" ); + dollarPrinter = TQString::fromLatin1( t ); + if ( !dollarPrinter.isEmpty() ) + perhapsAddPrinter( d->printers, dollarPrinter, + TQPrintDialog::tr("unknown"), + TQString::fromLatin1("") ); + } + int quality = 0; + + // bang the best default into the listview + const TQListViewItem * lvi = d->printers->firstChild(); + d->printers->setCurrentItem( (TQListViewItem *)lvi ); + while ( lvi ) { + TQRegExp ps( TQString::fromLatin1("[^a-z]ps(?:[^a-z]|$)") ); + TQRegExp lp( TQString::fromLatin1("[^a-z]lp(?:[^a-z]|$)") ); + + if ( quality < 4 && lvi->text(0) == dollarPrinter ) { + d->printers->setCurrentItem( (TQListViewItem *)lvi ); + quality = 4; + } else if ( quality < 3 && etcLpDefault && + lvi->text(0) == TQString::fromLatin1(etcLpDefault) ) { + d->printers->setCurrentItem( (TQListViewItem *)lvi ); + quality = 3; + } else if ( quality < 2 && + ( lvi->text(0) == TQString::fromLatin1("ps") || + ps.search(lvi->text(2)) != -1 ) ) { + d->printers->setCurrentItem( (TQListViewItem *)lvi ); + quality = 2; + } else if ( quality < 1 && + ( lvi->text(0) == TQString::fromLatin1("lp") || + lp.search(lvi->text(2)) > -1 ) ) { + d->printers->setCurrentItem( (TQListViewItem *)lvi ); + quality = 1; + } + lvi = lvi->nextSibling(); + } + + if ( d->printers->currentItem() ) + d->printers->setSelected( d->printers->currentItem(), TRUE ); + + if ( etcLpDefault ) // Avoid purify complaint + delete[] etcLpDefault; +#endif + + int h = fontMetrics().height(); + if ( d->printers->firstChild() ) + h = d->printers->firstChild()->height(); + d->printers->setMinimumSize( d->printers->sizeHint().width(), + d->printers->header()->height() + + 3 * h ); + horiz->addWidget( d->printers, 3 ); + + tll->addSpacing( 6 ); + + // file radio button, edit/browse + d->printToFileButton = new TQRadioButton( tr( "Print to file:" ), g, "file" ); + tll->addWidget( d->printToFileButton ); + d->printerOrFile->insert( d->printToFileButton, 1 ); + + horiz = new TQBoxLayout( TQBoxLayout::LeftToRight ); + tll->addLayout( horiz ); + horiz->addSpacing( 19 ); + + d->fileName = new TQLineEdit( g, "file name" ); + connect( d->fileName, SIGNAL( textChanged(const TQString&) ), + this, SLOT( fileNameEditChanged(const TQString&) ) ); + horiz->addWidget( d->fileName, 1 ); + horiz->addSpacing( 6 ); + d->browse = new TQPushButton( tr("Browse..."), g, "browse files" ); + d->browse->setAutoDefault( FALSE ); +#ifdef QT_NO_FILEDIALOG + d->browse->setEnabled( FALSE ); +#endif + connect( d->browse, SIGNAL(clicked()), + this, SLOT(browseClicked()) ); + horiz->addWidget( d->browse ); + + d->fileName->setEnabled( FALSE ); + d->browse->setEnabled( FALSE ); + + tll->activate(); + + return g; +} + + +TQGroupBox * TQPrintDialog::setupOptions() +{ + TQGroupBox * g = new TQGroupBox( 0, Horizontal, tr( "Options"), + this, "options group box" ); + + TQBoxLayout * tll = new TQBoxLayout( g->layout(), TQBoxLayout::Down ); + + TQBoxLayout *lay = new TQBoxLayout( TQBoxLayout::LeftToRight ); + tll->addLayout( lay ); + + tll = new TQBoxLayout( lay, TQBoxLayout::Down ); + + d->printRange = new TQButtonGroup( this ); + d->printRange->hide(); + connect( d->printRange, SIGNAL(clicked(int)), + this, SLOT(printRangeSelected(int)) ); + + d->pageOrder = new TQButtonGroup( this ); + d->pageOrder->hide(); + connect( d->pageOrder, SIGNAL(clicked(int)), + this, SLOT(pageOrderSelected(int)) ); + + d->printAllButton = new TQRadioButton( tr("Print all"), g, "print all" ); + d->printRange->insert( d->printAllButton, 0 ); + tll->addWidget( d->printAllButton ); + + d->printSelectionButton = new TQRadioButton( tr("Print selection"), + g, "print selection" ); + d->printRange->insert( d->printSelectionButton, 1 ); + tll->addWidget( d->printSelectionButton ); + + d->printRangeButton = new TQRadioButton( tr("Print range"), + g, "print range" ); + d->printRange->insert( d->printRangeButton, 2 ); + tll->addWidget( d->printRangeButton ); + + TQBoxLayout * horiz = new TQBoxLayout( TQBoxLayout::LeftToRight ); + tll->addLayout( horiz ); + + d->firstPageLabel = new TQLabel( tr("From page:"), g, "first page" ); + horiz->addSpacing( 19 ); + horiz->addWidget( d->firstPageLabel ); + + d->firstPage = new TQPrintDialogSpinBox( 1, 9999, 1, g, "first page" ); + d->firstPage->setValue( 1 ); + horiz->addWidget( d->firstPage, 1 ); + connect( d->firstPage, SIGNAL(valueChanged(int)), + this, SLOT(setFirstPage(int)) ); + + horiz = new TQBoxLayout( TQBoxLayout::LeftToRight ); + tll->addLayout( horiz ); + + d->lastPageLabel = new TQLabel( tr("To page:"), g, "last page" ); + horiz->addSpacing( 19 ); + horiz->addWidget( d->lastPageLabel ); + + d->lastPage = new TQPrintDialogSpinBox( 1, 9999, 1, g, "last page" ); + d->lastPage->setValue( 9999 ); + horiz->addWidget( d->lastPage, 1 ); + connect( d->lastPage, SIGNAL(valueChanged(int)), + this, SLOT(setLastPage(int)) ); + + lay->addSpacing( 25 ); + tll = new TQBoxLayout( lay, TQBoxLayout::Down ); + + // print order + TQRadioButton * rb = new TQRadioButton( tr("Print first page first"), + g, "first page first" ); + tll->addWidget( rb ); + d->pageOrder->insert( rb, TQPrinter::FirstPageFirst ); + rb->setChecked( TRUE ); + + rb = new TQRadioButton( tr("Print last page first"), + g, "last page first" ); + tll->addWidget( rb ); + d->pageOrder->insert( rb, TQPrinter::LastPageFirst ); + + tll->addStretch(); + + // copies + + horiz = new TQBoxLayout( TQBoxLayout::LeftToRight ); + tll->addLayout( horiz ); + + TQLabel * l = new TQLabel( tr("Number of copies:"), g, "Number of copies" ); + horiz->addWidget( l ); + + d->copies = new TQPrintDialogSpinBox( 1, 99, 1, g, "copies" ); + d->copies->setValue( 1 ); + horiz->addWidget( d->copies, 1 ); + connect( d->copies, SIGNAL(valueChanged(int)), + this, SLOT(setNumCopies(int)) ); + + TQSize s = d->firstPageLabel->sizeHint() + .expandedTo( d->lastPageLabel->sizeHint() ) + .expandedTo( l->sizeHint() ); + d->firstPageLabel->setMinimumSize( s ); + d->lastPageLabel->setMinimumSize( s ); + l->setMinimumSize( s.width() + 19, s.height() ); + + tll->activate(); + + return g; +} + + +void isc( TQPrintDialogPrivate * d, + const TQString & text, + TQPrinter::PageSize ps ) +{ + if ( d && text && ps < TQPrinter::NPageSize ) { + d->sizeCombo->insertItem( text, -1 ); + int index = d->sizeCombo->count()-1; + if ( index >= 0 && index < TQPrinter::NPageSize ) + d->indexToPageSize[index] = ps; + } +} + +TQGroupBox * TQPrintDialog::setupPaper() +{ + TQGroupBox * g = new TQGroupBox( 1, Horizontal, tr( "Paper format"), + this, "Paper format" ); + d->pageSize = TQPrinter::A4; + + // page orientation + d->orientationCombo = new TQComboBox( FALSE, g ); + d->orientationCombo->insertItem( tr( "Portrait" ), -1 ); + d->orientationCombo->insertItem( tr( "Landscape" ), -1 ); + + d->orientation = TQPrinter::Portrait; + + g->addSpace( 8 ); + + connect( d->orientationCombo, SIGNAL( activated(int) ), + this, SLOT( orientSelected(int) ) ); + + // paper size + d->sizeCombo = new TQComboBox( FALSE, g ); + + int n; + for( n=0; n<TQPrinter::NPageSize; n++ ) + d->indexToPageSize[n] = TQPrinter::A4; + + isc( d, tr( "A0 (841 x 1189 mm)" ), TQPrinter::A0 ); + isc( d, tr( "A1 (594 x 841 mm)" ), TQPrinter::A1 ); + isc( d, tr( "A2 (420 x 594 mm)" ), TQPrinter::A2 ); + isc( d, tr( "A3 (297 x 420 mm)" ), TQPrinter::A3 ); + isc( d, tr( "A4 (210x297 mm, 8.26x11.7 inches)" ), TQPrinter::A4 ); + isc( d, tr( "A5 (148 x 210 mm)" ), TQPrinter::A5 ); + isc( d, tr( "A6 (105 x 148 mm)" ), TQPrinter::A6 ); + isc( d, tr( "A7 (74 x 105 mm)" ), TQPrinter::A7 ); + isc( d, tr( "A8 (52 x 74 mm)" ), TQPrinter::A8 ); + isc( d, tr( "A9 (37 x 52 mm)" ), TQPrinter::A9 ); + isc( d, tr( "B0 (1000 x 1414 mm)" ), TQPrinter::B0 ); + isc( d, tr( "B1 (707 x 1000 mm)" ), TQPrinter::B1 ); + isc( d, tr( "B2 (500 x 707 mm)" ), TQPrinter::B2 ); + isc( d, tr( "B3 (353 x 500 mm)" ), TQPrinter::B3 ); + isc( d, tr( "B4 (250 x 353 mm)" ), TQPrinter::B4 ); + isc( d, tr( "B5 (176 x 250 mm, 6.93x9.84 inches)" ), TQPrinter::B5 ); + isc( d, tr( "B6 (125 x 176 mm)" ), TQPrinter::B6 ); + isc( d, tr( "B7 (88 x 125 mm)" ), TQPrinter::B7 ); + isc( d, tr( "B8 (62 x 88 mm)" ), TQPrinter::B8 ); + isc( d, tr( "B9 (44 x 62 mm)" ), TQPrinter::B9 ); + isc( d, tr( "B10 (31 x 44 mm)" ), TQPrinter::B10 ); + isc( d, tr( "C5E (163 x 229 mm)" ), TQPrinter::C5E ); + isc( d, tr( "DLE (110 x 220 mm)" ), TQPrinter::DLE ); + isc( d, tr( "Executive (7.5x10 inches, 191x254 mm)" ), TQPrinter::Executive ); + isc( d, tr( "Folio (210 x 330 mm)" ), TQPrinter::Folio ); + isc( d, tr( "Ledger (432 x 279 mm)" ), TQPrinter::Ledger ); + isc( d, tr( "Legal (8.5x14 inches, 216x356 mm)" ), TQPrinter::Legal ); + isc( d, tr( "Letter (8.5x11 inches, 216x279 mm)" ), TQPrinter::Letter ); + isc( d, tr( "Tabloid (279 x 432 mm)" ), TQPrinter::Tabloid ); + isc( d, tr( "US Common #10 Envelope (105 x 241 mm)" ), TQPrinter::Comm10E ); + + connect( d->sizeCombo, SIGNAL( activated(int) ), + this, SLOT( paperSizeSelected(int) ) ); + + return g; +} + + +/*! + Display a dialog and allow the user to configure the TQPrinter \a + p for an optional widget \a w. Returns TRUE if the user clicks OK or + presses Enter, FALSE if the user clicks Cancel or presses Esc. + + getPrinterSetup() remembers the settings and provides the same + settings the next time the dialog is shown. +*/ + +bool TQPrintDialog::getPrinterSetup( TQPrinter * p, TQWidget* w ) +{ + if ( !globalPrintDialog ) { + globalPrintDialog = new TQPrintDialog( 0, 0, "global print dialog" ); +#ifndef QT_NO_WIDGET_TOPEXTRA + globalPrintDialog->setCaption( TQPrintDialog::tr( "Setup Printer" ) ); +#endif + qAddPostRoutine( qpd_cleanup_globaldialog ); + globalPrintDialog->setPrinter( p, TRUE ); + globalPrintDialog->adjustSize(); + } else { + globalPrintDialog->setPrinter( p, TRUE ); + } + globalPrintDialog->adjustPosition( w ); + #ifndef QT_NO_WIDGET_TOPEXTRA + if ( w ) { + const TQPixmap *pm = w->icon(); + if ( pm && !pm->isNull() ) + globalPrintDialog->setIcon( *pm ); + else { + w = w ? w->topLevelWidget() : 0; + pm = w ? w->icon() : 0; + if ( pm && !pm->isNull() ) + globalPrintDialog->setIcon( *pm ); + } + } +#endif + bool r = globalPrintDialog->exec() == TQDialog::Accepted; + globalPrintDialog->setPrinter( 0 ); + return r; +} + + +void TQPrintDialog::printerOrFileSelected( int id ) +{ + d->outputToFile = id ? TRUE : FALSE; + if ( d->outputToFile ) { + d->ok->setEnabled( TRUE ); + fileNameEditChanged( d->fileName->text() ); + if ( !d->fileName->edited() && d->fileName->text().isEmpty() ) { + TQString home = TQString::fromLatin1( ::getenv( "HOME" ) ); + TQString cur = TQDir::currentDirPath(); + if ( home.at(home.length()-1) != '/' ) + home += '/'; + if ( cur.at(cur.length()-1) != '/' ) + cur += '/'; + if ( cur.left( home.length() ) != home ) + cur = home; +#ifdef Q_WS_X11 + cur += "print.ps"; +#endif + d->fileName->setText( cur ); + d->fileName->setCursorPosition( cur.length() ); + d->fileName->selectAll(); + } + d->browse->setEnabled( TRUE ); + d->fileName->setEnabled( TRUE ); + d->fileName->setFocus(); + d->printers->setEnabled( FALSE ); + } else { + d->ok->setEnabled( d->printers->childCount() != 0 ); + d->printers->setEnabled( TRUE ); + if ( d->fileName->hasFocus() || d->browse->hasFocus() ) + d->printers->setFocus(); + d->browse->setEnabled( FALSE ); + d->fileName->setEnabled( FALSE ); + } +} + + +void TQPrintDialog::landscapeSelected( int id ) +{ + d->orientation = (TQPrinter::Orientation)id; +} + + +void TQPrintDialog::paperSizeSelected( int id ) +{ + if ( id < TQPrinter::NPageSize ) + d->pageSize = TQPrinter::PageSize( d->indexToPageSize[id] ); +} + + +void TQPrintDialog::orientSelected( int id ) +{ + d->orientation = (TQPrinter::Orientation)id; +} + + +void TQPrintDialog::pageOrderSelected( int id ) +{ + d->pageOrder2 = (TQPrinter::PageOrder)id; +} + + +void TQPrintDialog::setNumCopies( int copies ) +{ + d->numCopies = copies; +} + + +void TQPrintDialog::browseClicked() +{ +#ifndef QT_NO_FILEDIALOG + TQString fn = TQFileDialog::getSaveFileName( d->fileName->text(), tr( "PostScript Files (*.ps);;All Files (*)" ), this ); + if ( !fn.isNull() ) + d->fileName->setText( fn ); +#endif +} + + +void TQPrintDialog::okClicked() +{ + d->lastPage->interpretText(); + d->firstPage->interpretText(); + d->copies->interpretText(); + if ( d->outputToFile ) { + d->printer->setOutputToFile( TRUE ); + d->printer->setOutputFileName( d->fileName->text() ); + } else { + d->printer->setOutputToFile( FALSE ); + TQListViewItem * l = d->printers->currentItem(); + if ( l ) + d->printer->setPrinterName( l->text( 0 ) ); + } + + d->printer->setOrientation( d->orientation ); + d->printer->setPageSize( d->pageSize ); + d->printer->setPageOrder( d->pageOrder2 ); + d->printer->setColorMode( d->colorMode2 ); + d->printer->setNumCopies( d->numCopies ); + if ( d->printAllButton->isChecked() ) { + d->printer->setPrintRange(TQPrinter::AllPages); + d->printer->setFromTo( d->printer->minPage(), d->printer->maxPage() ); + } else { + if (d->printSelectionButton->isChecked()) + d->printer->setPrintRange(TQPrinter::Selection); + else + d->printer->setPrintRange(TQPrinter::PageRange); + d->printer->setFromTo( d->firstPage->value(), d->lastPage->value() ); + } + + accept(); +} + + +void TQPrintDialog::printRangeSelected( int id ) +{ + bool enable = id == 2 ? TRUE : FALSE; + d->firstPage->setEnabled( enable ); + d->lastPage->setEnabled( enable ); + d->firstPageLabel->setEnabled( enable ); + d->lastPageLabel->setEnabled( enable ); +} + + +void TQPrintDialog::setFirstPage( int fp ) +{ + if ( d->printer ) + d->lastPage->setRange( fp, TQMAX(fp, TQPrintDialog::d->printer->maxPage()) ); +} + + +void TQPrintDialog::setLastPage( int lp ) +{ + if ( d->printer ) + d->firstPage->setRange( TQMIN(lp, TQPrintDialog::d->printer->minPage()), lp ); +} + + +/*! + Sets this dialog to configure printer \a p, or no printer if \a p + is null. If \a pickUpSettings is TRUE, the dialog reads most of + its settings from \a p. If \a pickUpSettings is FALSE (the + default) the dialog keeps its old settings. +*/ + +void TQPrintDialog::setPrinter( TQPrinter * p, bool pickUpSettings ) +{ + d->printer = p; + + if ( p && pickUpSettings ) { + // top to botton in the old dialog. + // printer or file + d->printerOrFile->setButton( p->outputToFile() ); + printerOrFileSelected( p->outputToFile() ); + + // printer name + if ( !!p->printerName() ) { + TQListViewItem * i = d->printers->firstChild(); + while ( i && i->text( 0 ) != p->printerName() ) + i = i->nextSibling(); + if ( i ) { + d->printers->setSelected( i, TRUE ); + d->ok->setEnabled( TRUE ); + } else if ( d->fileName->text().isEmpty() ) { + d->ok->setEnabled( d->printers->childCount() != 0 ); + } + } + + // print command does not exist any more + + // file name + d->printToFileButton->setEnabled( d->printer->isOptionEnabled( TQPrinter::PrintToFile ) ); + d->fileName->setText( p->outputFileName() ); + + // orientation + d->orientationCombo->setCurrentItem( (int)p->orientation() ); + orientSelected( p->orientation() ); + + // page size + int n = 0; + while ( n < TQPrinter::NPageSize && + d->indexToPageSize[n] != p->pageSize() ) + n++; + d->sizeCombo->setCurrentItem( n ); + paperSizeSelected( n ); + + // New stuff (Options) + + // page order + d->pageOrder->setButton( (int)p->pageOrder() ); + pageOrderSelected( p->pageOrder() ); + + // color mode + d->colorMode->setButton( (int)p->colorMode() ); + colorModeSelected( p->colorMode() ); + + // number of copies + d->copies->setValue( p->numCopies() ); + setNumCopies( p->numCopies() ); + } + + if( p ) { + d->printAllButton->setEnabled( TRUE ); + d->printSelectionButton + ->setEnabled( d->printer->isOptionEnabled( TQPrinter::PrintSelection ) ); + d->printRangeButton + ->setEnabled( d->printer->isOptionEnabled( TQPrinter::PrintPageRange ) ); + + TQPrinter::PrintRange range = p->printRange(); + switch ( range ) { + case TQPrinter::AllPages: + d->printAllButton->setChecked(TRUE); + printRangeSelected( d->printRange->id( d->printAllButton ) ); + break; + case TQPrinter::Selection: + d->printSelectionButton->setChecked(TRUE); + printRangeSelected( d->printRange->id( d->printSelectionButton ) ); + break; + case TQPrinter::PageRange: + d->printRangeButton->setChecked(TRUE); + printRangeSelected( d->printRange->id( d->printRangeButton ) ); + break; + } + } + + if ( p && p->maxPage() ) { + d->firstPage->setRange( p->minPage(), p->maxPage() ); + d->lastPage->setRange( p->minPage(), p->maxPage() ); + if ( p->fromPage() || p->toPage() ) { + setFirstPage( p->fromPage() ); + setLastPage( p->toPage() ); + d->firstPage->setValue(p->fromPage()); + d->lastPage->setValue(p->toPage()); + } + } +} + + +/*! Returns a pointer to the printer this dialog configures, or 0 if + this dialog does not operate on any printer. */ + +TQPrinter * TQPrintDialog::printer() const +{ + return d->printer; +} + + +void TQPrintDialog::colorModeSelected( int id ) +{ + d->colorMode2 = (TQPrinter::ColorMode)id; +} + +/*! + Adds the button \a but to the layout of the print dialog. The added + buttons are arranged from the left to the right below the + last groupbox of the printdialog. +*/ + +void TQPrintDialog::addButton( TQPushButton *but ) +{ + d->customLayout->addWidget( but ); +} + +void TQPrintDialog::fileNameEditChanged( const TQString &text ) +{ + if ( d->fileName->isEnabled() ) + d->ok->setEnabled( !text.isEmpty() ); +} + +#endif diff --git a/src/dialogs/qprintdialog.h b/src/dialogs/qprintdialog.h new file mode 100644 index 000000000..c0cc7dc40 --- /dev/null +++ b/src/dialogs/qprintdialog.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Definition of print dialog. +** +** Created : 950829 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQPRINTDIALOG_H +#define TQPRINTDIALOG_H + +#ifndef QT_H +#include "qdialog.h" +#endif // QT_H + +#ifndef QT_NO_PRINTDIALOG + +class TQGroupBox; +class TQPrintDialogPrivate; +class TQListView; + +class Q_EXPORT TQPrintDialog : public TQDialog +{ + Q_OBJECT +public: + TQPrintDialog( TQPrinter *, TQWidget* parent=0, const char* name=0 ); + ~TQPrintDialog(); + + static bool getPrinterSetup( TQPrinter *, TQWidget* = 0 ); + static void setGlobalPrintDialog( TQPrintDialog * ); + + void setPrinter( TQPrinter *, bool = FALSE ); + TQPrinter * printer() const; + + void addButton( TQPushButton *but ); + +private slots: + void browseClicked(); + void okClicked(); + + void printerOrFileSelected( int ); + void landscapeSelected( int ); + void paperSizeSelected( int ); + void orientSelected( int ); + void pageOrderSelected( int ); + void colorModeSelected( int ); + void setNumCopies( int ); + void printRangeSelected( int ); + void setFirstPage( int ); + void setLastPage( int ); + + void fileNameEditChanged( const TQString &text ); + +private: + TQPrintDialogPrivate *d; + + TQGroupBox * setupDestination(); + TQGroupBox * setupOptions(); + TQGroupBox * setupPaper(); + TQGroupBox * setupPrinterSettings(); + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQPrintDialog( const TQPrintDialog & ); + TQPrintDialog &operator=( const TQPrintDialog & ); +#endif +}; + +#endif + +#endif // TQPRINTDIALOG_H diff --git a/src/dialogs/qprogressdialog.cpp b/src/dialogs/qprogressdialog.cpp new file mode 100644 index 000000000..7fa745578 --- /dev/null +++ b/src/dialogs/qprogressdialog.cpp @@ -0,0 +1,826 @@ +/**************************************************************************** +** +** Implementation of TQProgressDialog class +** +** Created : 970521 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qprogressdialog.h" + +#ifndef QT_NO_PROGRESSDIALOG + +#include "qaccel.h" +#include "qpainter.h" +#include "qdrawutil.h" +#include "qdatetime.h" +#include "qapplication.h" +#include "qstyle.h" +#include "qpushbutton.h" +#include "qcursor.h" +#include "qtimer.h" +#include <limits.h> + +// If the operation is expected to take this long (as predicted by +// progress time), show the progress dialog. +static const int defaultShowTime = 4000; +// Wait at least this long before attempting to make a prediction. +static const int minWaitTime = 50; + +// Various layout values +static const int margin_lr = 10; +static const int margin_tb = 10; +static const int spacing = 4; + + +class TQProgressDialogData +{ +public: + TQProgressDialogData( TQProgressDialog* that, TQWidget* parent, + const TQString& labelText, + int totalSteps ) : + creator( parent ), + label( new TQLabel(labelText,that,"label") ), + cancel( 0 ), + bar( new TQProgressBar(totalSteps,that,"bar") ), + shown_once( FALSE ), + cancellation_flag( FALSE ), + showTime( defaultShowTime ) + { + label->setAlignment(that->style().styleHint(TQStyle::SH_ProgressDialog_TextLabelAlignment, that)); + } + + TQWidget *creator; + TQLabel *label; + TQPushButton *cancel; + TQProgressBar *bar; + bool shown_once; + bool cancellation_flag; + TQTime starttime; +#ifndef QT_NO_CURSOR + TQCursor parentCursor; +#endif + int showTime; + bool autoClose; + bool autoReset; + bool forceHide; +}; + + +/*! + \class TQProgressDialog qprogressdialog.h + \brief The TQProgressDialog class provides feedback on the progress of a slow operation. + \ingroup dialogs + \mainclass + + A progress dialog is used to give the user an indication of how long + an operation is going to take, and to demonstrate that the + application has not frozen. It can also give the user an opportunity + to abort the operation. + + A common problem with progress dialogs is that it is difficult to know + when to use them; operations take different amounts of time on different + hardware. TQProgressDialog offers a solution to this problem: + it estimates the time the operation will take (based on time for + steps), and only shows itself if that estimate is beyond minimumDuration() + (4 seconds by default). + + Use setTotalSteps() (or the constructor) to set the number of + "steps" in the operation and call setProgress() as the operation + progresses. The step value can be chosen arbitrarily. It can be the + number of files copied, the number of bytes received, the number of + iterations through the main loop of your algorithm, or some other + suitable unit. Progress starts at 0, and the progress dialog shows + that the operation has finished when you call setProgress() with + totalSteps() as its argument. + + The dialog automatically resets and hides itself at the end of the + operation. Use setAutoReset() and setAutoClose() to change this + behavior. + + There are two ways of using TQProgressDialog: modal and modeless. + + Using a modal TQProgressDialog is simpler for the programmer, but you + must call TQApplication::processEvents() or + TQEventLoop::processEvents(ExcludeUserInput) to keep the event loop + running to ensure that the application doesn't freeze. Do the + operation in a loop, call \l setProgress() at intervals, and check + for cancellation with wasCanceled(). For example: +\code +TQProgressDialog progress( "Copying files...", "Abort Copy", numFiles, + this, "progress", TRUE ); +for ( int i = 0; i < numFiles; i++ ) { + progress.setProgress( i ); + qApp->processEvents(); + + if ( progress.wasCanceled() ) + break; + //... copy one file +} +progress.setProgress( numFiles ); +\endcode + + A modeless progress dialog is suitable for operations that take + place in the background, where the user is able to interact with the + application. Such operations are typically based on TQTimer (or + TQObject::timerEvent()), TQSocketNotifier, or TQUrlOperator; or performed + in a separate thread. A TQProgressBar in the status bar of your main window + is often an alternative to a modeless progress dialog. + + You need to have an event loop to be running, connect the + canceled() signal to a slot that stops the operation, and call \l + setProgress() at intervals. For example: +\code +Operation::Operation( TQObject *parent = 0 ) + : TQObject( parent ), steps( 0 ) +{ + pd = new TQProgressDialog( "Operation in progress.", "Cancel", 100 ); + connect( pd, SIGNAL(canceled()), this, SLOT(cancel()) ); + t = new TQTimer( this ); + connect( t, SIGNAL(timeout()), this, SLOT(perform()) ); + t->start( 0 ); +} + +void Operation::perform() +{ + pd->setProgress( steps ); + //... perform one percent of the operation + steps++; + if ( steps > pd->totalSteps() ) + t->stop(); +} + +void Operation::cancel() +{ + t->stop(); + //... cleanup +} +\endcode + + + In both modes the progress dialog may be customized by + replacing the child widgets with custom widgets by using setLabel(), + setBar(), and setCancelButton(). + The functions setLabelText() and setCancelButtonText() + set the texts shown. + + <img src=qprogdlg-m.png> <img src=qprogdlg-w.png> + + \sa TQDialog TQProgressBar + \link guibooks.html#fowler GUI Design Handbook: Progress Indicator\endlink +*/ + + +/*! + Returns the TQLabel currently being displayed above the progress bar. + This TQLabel is owned by the TQProgressDialog. + + \sa setLabel() +*/ +TQLabel *TQProgressDialog::label() const +{ + return d->label; +} + +/*! + Returns the TQProgressBar currently being used to display progress. + This TQProgressBar is owned by the TQProgressDialog. + + \sa setBar() +*/ +TQProgressBar *TQProgressDialog::bar() const +{ + return d->bar; +} + + +/*! + Constructs a progress dialog. + + Default settings: + \list + \i The label text is empty. + \i The cancel button text is (translated) "Cancel". + \i The total number of steps is 100. + \endlist + + The \a creator argument is the widget to use as the dialog's parent. + The \a name, \a modal, and the widget flags, \a f, are + passed to the TQDialog::TQDialog() constructor. If \a modal is FALSE (the + default), you must have an event loop proceeding for any redrawing + of the dialog to occur. If \a modal is TRUE, the dialog ensures that + events are processed when needed. + + \sa setLabelText(), setLabel(), setCancelButtonText(), setCancelButton(), + setTotalSteps() +*/ + +TQProgressDialog::TQProgressDialog( TQWidget *creator, const char *name, + bool modal, WFlags f ) + : TQDialog( creator, name, modal, f) +{ + init( creator, TQString::fromLatin1(""), tr("Cancel"), 100 ); +} + +/*! + Constructs a progress dialog. + + The \a labelText is text used to remind the user what is progressing. + + The \a cancelButtonText is the text to display on the cancel button, + or 0 if no cancel button is to be shown. + + The \a totalSteps is the total number of steps in the operation for + which this progress dialog shows progress. For example, if the + operation is to examine 50 files, this value would be 50. Before + examining the first file, call setProgress(0). As each file is + processed call setProgress(1), setProgress(2), etc., finally + calling setProgress(50) after examining the last file. + + The \a creator argument is the widget to use as the dialog's parent. + The \a name, \a modal, and widget flags, \a f, are passed to the + TQDialog::TQDialog() constructor. If \a modal is FALSE (the default), + you will must have an event loop proceeding for any redrawing of + the dialog to occur. If \a modal is TRUE, the dialog ensures that + events are processed when needed. + + + \sa setLabelText(), setLabel(), setCancelButtonText(), setCancelButton(), + setTotalSteps() +*/ + +TQProgressDialog::TQProgressDialog( const TQString &labelText, + const TQString &cancelButtonText, + int totalSteps, + TQWidget *creator, const char *name, + bool modal, WFlags f ) + : TQDialog( creator, name, modal, f) +{ + init( creator, labelText, cancelButtonText, totalSteps ); +} + + +/*! + Destroys the progress dialog. +*/ + +TQProgressDialog::~TQProgressDialog() +{ +#ifndef QT_NO_CURSOR + if ( d->creator ) + d->creator->setCursor( d->parentCursor ); +#endif + delete d; +} + +void TQProgressDialog::init( TQWidget *creator, + const TQString& lbl, const TQString& canc, + int totstps) +{ + d = new TQProgressDialogData(this, creator, lbl, totstps); + d->autoClose = TRUE; + d->autoReset = TRUE; + d->forceHide = FALSE; + setCancelButtonText( canc ); + connect( this, SIGNAL(canceled()), this, SIGNAL(cancelled()) ); + connect( this, SIGNAL(canceled()), this, SLOT(cancel()) ); + forceTimer = new TQTimer( this ); + connect( forceTimer, SIGNAL(timeout()), this, SLOT(forceShow()) ); + layout(); +} + +/*! + \fn void TQProgressDialog::canceled() + + This signal is emitted when the cancel button is clicked. + It is connected to the cancel() slot by default. + + \sa wasCanceled() +*/ + +/*! + \fn void TQProgressDialog::cancelled() + + \obsolete + + Use canceled() instead. +*/ + + +/*! + Sets the label to \a label. The progress dialog resizes to fit. The + label becomes owned by the progress dialog and will be deleted when + necessary, so do not pass the address of an object on the stack. + + \sa setLabelText() +*/ + +void TQProgressDialog::setLabel( TQLabel *label ) +{ + delete d->label; + d->label = label; + if (label) { + if ( label->parentWidget() == this ) { + label->hide(); // until we resize + } else { + label->reparent( this, 0, TQPoint(0,0), FALSE ); + } + } + int w = TQMAX( isVisible() ? width() : 0, sizeHint().width() ); + int h = TQMAX( isVisible() ? height() : 0, sizeHint().height() ); + resize( w, h ); + if (label) + label->show(); +} + + +/*! + \property TQProgressDialog::labelText + \brief the label's text + + The default text is TQString::null. +*/ + +TQString TQProgressDialog::labelText() const +{ + if ( label() ) + return label()->text(); + return TQString::null; +} + +void TQProgressDialog::setLabelText( const TQString &text ) +{ + if ( label() ) { + label()->setText( text ); + int w = TQMAX( isVisible() ? width() : 0, sizeHint().width() ); + int h = TQMAX( isVisible() ? height() : 0, sizeHint().height() ); + resize( w, h ); + } +} + + +/*! + Sets the cancel button to the push button, \a cancelButton. The + progress dialog takes ownership of this button which will be deleted + when necessary, so do not pass the address of an object that is on + the stack, i.e. use new() to create the button. + + \sa setCancelButtonText() +*/ + +void TQProgressDialog::setCancelButton( TQPushButton *cancelButton ) +{ + delete d->cancel; + d->cancel = cancelButton; + if (cancelButton) { + if ( cancelButton->parentWidget() == this ) { + cancelButton->hide(); // until we resize + } else { + cancelButton->reparent( this, 0, TQPoint(0,0), FALSE ); + } + connect( d->cancel, SIGNAL(clicked()), this, SIGNAL(canceled()) ); +#ifndef QT_NO_ACCEL + TQAccel *accel = new TQAccel( this ); + accel->connectItem( accel->insertItem(Key_Escape), + d->cancel, SIGNAL(clicked()) ); +#endif + } + int w = TQMAX( isVisible() ? width() : 0, sizeHint().width() ); + int h = TQMAX( isVisible() ? height() : 0, sizeHint().height() ); + resize( w, h ); + if (cancelButton) + cancelButton->show(); +} + +/*! + Sets the cancel button's text to \a cancelButtonText. + \sa setCancelButton() +*/ + +void TQProgressDialog::setCancelButtonText( const TQString &cancelButtonText ) +{ + if ( !cancelButtonText.isNull() ) { + if ( d->cancel ) + d->cancel->setText(cancelButtonText); + else + setCancelButton(new TQPushButton(cancelButtonText, this, "cancel")); + } else { + setCancelButton(0); + } + int w = TQMAX( isVisible() ? width() : 0, sizeHint().width() ); + int h = TQMAX( isVisible() ? height() : 0, sizeHint().height() ); + resize( w, h ); +} + + +/*! + Sets the progress bar widget to \a bar. The progress dialog resizes to + fit. The progress dialog takes ownership of the progress \a bar which + will be deleted when necessary, so do not use a progress bar + allocated on the stack. +*/ + +void TQProgressDialog::setBar( TQProgressBar *bar ) +{ + if ( progress() > 0 ) { +#if defined(QT_CHECK_STATE) + qWarning( "TQProgrssDialog::setBar: Cannot set a new progress bar " + "while the old one is active" ); +#endif + } + delete d->bar; + d->bar = bar; + int w = TQMAX( isVisible() ? width() : 0, sizeHint().width() ); + int h = TQMAX( isVisible() ? height() : 0, sizeHint().height() ); + resize( w, h ); +} + + +/*! + \property TQProgressDialog::wasCancelled + \brief whether the dialog was canceled + + \obsolete + + Use \l wasCanceled instead. +*/ + +/*! + \property TQProgressDialog::wasCanceled + \brief whether the dialog was canceled + + \sa setProgress() +*/ + +bool TQProgressDialog::wasCancelled() const +{ + return d->cancellation_flag; +} + + +/*! + \property TQProgressDialog::totalSteps + \brief the total number of steps + + The default is 0. +*/ + +int TQProgressDialog::totalSteps() const +{ + if ( d && d->bar ) + return bar()->totalSteps(); + return 0; +} + +void TQProgressDialog::setTotalSteps( int totalSteps ) +{ + bar()->setTotalSteps( totalSteps ); +} + + +/*! + Resets the progress dialog. + The progress dialog becomes hidden if autoClose() is TRUE. + + \sa setAutoClose(), setAutoReset() +*/ + +void TQProgressDialog::reset() +{ +#ifndef QT_NO_CURSOR + if ( progress() >= 0 ) { + if ( d->creator ) + d->creator->setCursor( d->parentCursor ); + } +#endif + if ( d->autoClose || d->forceHide ) + hide(); + bar()->reset(); + d->cancellation_flag = FALSE; + d->shown_once = FALSE; + forceTimer->stop(); +} + +/*! + Resets the progress dialog. wasCanceled() becomes TRUE until + the progress dialog is reset. + The progress dialog becomes hidden. +*/ + +void TQProgressDialog::cancel() +{ + d->forceHide = TRUE; + reset(); + d->forceHide = FALSE; + d->cancellation_flag = TRUE; +} + +/*! + \property TQProgressDialog::progress + \brief the current amount of progress made. + + For the progress dialog to work as expected, you should initially set + this property to 0 and finally set it to + TQProgressDialog::totalSteps(); you can call setProgress() any number of times + in-between. + + \warning If the progress dialog is modal + (see TQProgressDialog::TQProgressDialog()), + this function calls TQApplication::processEvents(), so take care that + this does not cause undesirable re-entrancy in your code. For example, + don't use a TQProgressDialog inside a paintEvent()! + + \sa totalSteps +*/ + +int TQProgressDialog::progress() const +{ + return bar()->progress(); +} + +void TQProgressDialog::setProgress( int progress ) +{ + if ( progress == bar()->progress() || + bar()->progress() == -1 && progress == bar()->totalSteps() ) + return; + + bar()->setProgress(progress); + + if ( d->shown_once ) { + if (testWFlags(WShowModal)) + qApp->processEvents(); + } else { + if ( progress == 0 ) { +#ifndef QT_NO_CURSOR + if ( d->creator ) { + d->parentCursor = d->creator->cursor(); + d->creator->setCursor( waitCursor ); + } +#endif + d->starttime.start(); + forceTimer->start( d->showTime ); + return; + } else { + bool need_show; + int elapsed = d->starttime.elapsed(); + if ( elapsed >= d->showTime ) { + need_show = TRUE; + } else { + if ( elapsed > minWaitTime ) { + int estimate; + if ( (totalSteps() - progress) >= INT_MAX / elapsed ) + estimate = (totalSteps() - progress) / progress * elapsed; + else + estimate = elapsed * (totalSteps() - progress) / progress; + need_show = estimate >= d->showTime; + } else { + need_show = FALSE; + } + } + if ( need_show ) { + int w = TQMAX( isVisible() ? width() : 0, sizeHint().width() ); + int h = TQMAX( isVisible() ? height() : 0, sizeHint().height() ); + resize( w, h ); + show(); + d->shown_once = TRUE; + } + } +#ifdef Q_WS_MACX + TQApplication::flush(); +#endif + } + + if ( progress == bar()->totalSteps() && d->autoReset ) + reset(); +} + +/*! + \overload + + Sets the current amount of progress to \a progress and the total number of + steps to \a totalSteps. + + \sa setTotalSteps() +*/ + +void TQProgressDialog::setProgress( int progress, int totalSteps ) +{ + setTotalSteps( totalSteps ); + setProgress( progress ); +} + +/*! + Returns a size that fits the contents of the progress dialog. + The progress dialog resizes itself as retquired, so you should not + need to call this yourself. +*/ + +TQSize TQProgressDialog::sizeHint() const +{ + TQSize sh = label()->sizeHint(); + TQSize bh = bar()->sizeHint(); + int h = margin_tb*2 + bh.height() + sh.height() + spacing; + if ( d->cancel ) + h += d->cancel->sizeHint().height() + spacing; + return TQSize( TQMAX(200, sh.width() + 2*margin_lr), h ); +} + +/*!\reimp +*/ +void TQProgressDialog::resizeEvent( TQResizeEvent * ) +{ + layout(); +} + +/*! + \reimp +*/ +void TQProgressDialog::styleChange(TQStyle& s) +{ + TQDialog::styleChange(s); + layout(); +} + +void TQProgressDialog::layout() +{ + int sp = spacing; + int mtb = margin_tb; + int mlr = TQMIN(width()/10, margin_lr); + const bool centered = + bool(style().styleHint(TQStyle::SH_ProgressDialog_CenterCancelButton, this)); + + TQSize cs = d->cancel ? d->cancel->sizeHint() : TQSize(0,0); + TQSize bh = bar()->sizeHint(); + int cspc; + int lh = 0; + + // Find spacing and sizes that fit. It is important that a progress + // dialog can be made very small if the user demands it so. + for (int attempt=5; attempt--; ) { + cspc = d->cancel ? cs.height() + sp : 0; + lh = TQMAX(0, height() - mtb - bh.height() - sp - cspc); + + if ( lh < height()/4 ) { + // Getting cramped + sp /= 2; + mtb /= 2; + if ( d->cancel ) { + cs.setHeight(TQMAX(4,cs.height()-sp-2)); + } + bh.setHeight(TQMAX(4,bh.height()-sp-1)); + } else { + break; + } + } + + if ( d->cancel ) { + d->cancel->setGeometry( + centered ? width()/2 - cs.width()/2 : width() - mlr - cs.width(), + height() - mtb - cs.height() + sp, + cs.width(), cs.height() ); + } + + label()->setGeometry( mlr, 0, width()-mlr*2, lh ); + bar()->setGeometry( mlr, lh+sp, width()-mlr*2, bh.height() ); +} + +/*! + \property TQProgressDialog::minimumDuration + \brief the time that must pass before the dialog appears + + If the expected duration of the task is less than the + minimumDuration, the dialog will not appear at all. This prevents + the dialog popping up for tasks that are tquickly over. For tasks + that are expected to exceed the minimumDuration, the dialog will + pop up after the minimumDuration time or as soon as any progress + is set. + + If set to 0, the dialog is always shown as soon as any progress is + set. The default is 4000 milliseconds. +*/ +void TQProgressDialog::setMinimumDuration( int ms ) +{ + d->showTime = ms; + if ( bar()->progress() == 0 ) { + forceTimer->stop(); + forceTimer->start( ms ); + } +} + +int TQProgressDialog::minimumDuration() const +{ + return d->showTime; +} + + +/*! + \reimp +*/ + +void TQProgressDialog::closeEvent( TQCloseEvent *e ) +{ + emit canceled(); + TQDialog::closeEvent( e ); +} + +/*! + \property TQProgressDialog::autoReset + \brief whether the progress dialog calls reset() as soon as progress() equals totalSteps() + + The default is TRUE. + + \sa setAutoClose() +*/ + +void TQProgressDialog::setAutoReset( bool b ) +{ + d->autoReset = b; +} + +bool TQProgressDialog::autoReset() const +{ + return d->autoReset; +} + +/*! + \property TQProgressDialog::autoClose + \brief whether the dialog gets hidden by reset() + + The default is TRUE. + + \sa setAutoReset() +*/ + +void TQProgressDialog::setAutoClose( bool b ) +{ + d->autoClose = b; +} + +bool TQProgressDialog::autoClose() const +{ + return d->autoClose; +} + +/*! + \reimp +*/ + +void TQProgressDialog::showEvent( TQShowEvent *e ) +{ + TQDialog::showEvent( e ); + int w = TQMAX( isVisible() ? width() : 0, sizeHint().width() ); + int h = TQMAX( isVisible() ? height() : 0, sizeHint().height() ); + resize( w, h ); + forceTimer->stop(); +} + +/*! + Shows the dialog if it is still hidden after the algorithm has been started + and minimumDuration milliseconds have passed. + + \sa setMinimumDuration() +*/ + +void TQProgressDialog::forceShow() +{ + if ( d->shown_once || d->cancellation_flag ) + return; + + show(); + d->shown_once = TRUE; +} + + +#endif diff --git a/src/dialogs/qprogressdialog.h b/src/dialogs/qprogressdialog.h new file mode 100644 index 000000000..b96da1188 --- /dev/null +++ b/src/dialogs/qprogressdialog.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Definition of TQProgressDialog class +** +** Created : 970520 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQPROGRESSDIALOG_H +#define TQPROGRESSDIALOG_H + +#ifndef QT_H +#include "qsemimodal.h" +#include "qlabel.h" // ### remove or keep for users' convenience? +#include "qprogressbar.h" // ### remove or keep for users' convenience? +#endif // QT_H + +#ifndef QT_NO_PROGRESSDIALOG + +class TQPushButton; +class TQTimer; +class TQProgressDialogData; + +class Q_EXPORT TQProgressDialog : public TQDialog +{ + Q_OBJECT + Q_PROPERTY( bool wasCancelled READ wasCancelled DESIGNABLE false STORED false ) // ### remove in 4.0 + Q_PROPERTY( bool wasCanceled READ wasCanceled ) + Q_PROPERTY( int totalSteps READ totalSteps WRITE setTotalSteps ) + Q_PROPERTY( int progress READ progress WRITE setProgress ) + Q_PROPERTY( bool autoReset READ autoReset WRITE setAutoReset ) + Q_PROPERTY( bool autoClose READ autoClose WRITE setAutoClose ) + Q_PROPERTY( int minimumDuration READ minimumDuration WRITE setMinimumDuration ) + Q_PROPERTY( TQString labelText READ labelText WRITE setLabelText ) + +public: + TQProgressDialog( TQWidget* parent=0, const char* name=0, bool modal=FALSE, + WFlags f=0 ); + TQProgressDialog( const TQString& labelText, const TQString &cancelButtonText, + int totalSteps, TQWidget* parent=0, const char* name=0, + bool modal=FALSE, WFlags f=0 ); + ~TQProgressDialog(); + + void setLabel( TQLabel * ); + void setCancelButton( TQPushButton * ); + void setBar( TQProgressBar * ); + + // ### TQt 4.0: remove wasCancelled() in 4.0 + bool wasCancelled() const; + inline bool wasCanceled() const { return wasCancelled(); } + + int totalSteps() const; + int progress() const; + + TQSize sizeHint() const; + + TQString labelText() const; + + void setAutoReset( bool b ); + bool autoReset() const; + void setAutoClose( bool b ); + bool autoClose() const; + +public slots: + void cancel(); + void reset(); + void setTotalSteps( int totalSteps ); + void setProgress( int progress ); + void setProgress( int progress, int totalSteps ); + void setLabelText( const TQString &); + void setCancelButtonText( const TQString &); + + void setMinimumDuration( int ms ); +public: + int minimumDuration() const; + +signals: + // ### remove cancelled() in 4.0 + void cancelled(); + void canceled(); + +protected: + void resizeEvent( TQResizeEvent * ); + void closeEvent( TQCloseEvent * ); + void styleChange( TQStyle& ); + void showEvent( TQShowEvent *e ); + +protected slots: + void forceShow(); + +private: + void init( TQWidget *creator, const TQString& lbl, const TQString &canc, + int totstps); + void layout(); + TQLabel *label() const; + TQProgressBar *bar() const; + TQProgressDialogData *d; + TQTimer *forceTimer; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQProgressDialog( const TQProgressDialog & ); + TQProgressDialog &operator=( const TQProgressDialog & ); +#endif +}; + +#endif // QT_NO_PROGRESSDIALOG + +#endif // TQPROGRESSDIALOG_H diff --git a/src/dialogs/qsemimodal.h b/src/dialogs/qsemimodal.h new file mode 100644 index 000000000..200c07dbc --- /dev/null +++ b/src/dialogs/qsemimodal.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Definition of TQSemiModal class for source compatibility +** +** Created : 001010 +** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQSEMIMODAL_H +#define TQSEMIMODAL_H + +#ifndef QT_H +#include "qdialog.h" +#endif // QT_H + +#ifndef QT_NO_COMPAT +#ifndef QT_NO_SEMIMODAL +class Q_EXPORT TQSemiModal : public TQDialog +{ + Q_OBJECT +public: + TQSemiModal( TQWidget* parent=0, const char* name=0, bool modal=FALSE, WFlags f=0 ) + : TQDialog( parent, name, modal, f ) { } + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQSemiModal( const TQSemiModal & ); + TQSemiModal &operator=( const TQSemiModal & ); +#endif +}; +#endif +#endif + +#endif // TQSEMIMODAL_H diff --git a/src/dialogs/qt_dialogs.pri b/src/dialogs/qt_dialogs.pri new file mode 100644 index 000000000..9bd899205 --- /dev/null +++ b/src/dialogs/qt_dialogs.pri @@ -0,0 +1,33 @@ +# Qt dialogs module + +dialogs { + DIALOGS_P = dialogs + + HEADERS += $$DIALOGS_H/qcolordialog.h \ + $$DIALOGS_H/qdialog.h \ + $$DIALOGS_H/qerrormessage.h \ + $$DIALOGS_H/qfiledialog.h \ + $$DIALOGS_H/qfontdialog.h \ + $$DIALOGS_H/qmessagebox.h \ + $$DIALOGS_H/qprogressdialog.h \ + $$DIALOGS_H/qsemimodal.h \ + $$DIALOGS_H/qtabdialog.h \ + $$DIALOGS_H/qwizard.h \ + $$DIALOGS_H/qinputdialog.h + + !embedded:mac:SOURCES += $$DIALOGS_CPP/qfiledialog_mac.cpp $$DIALOGS_CPP/qcolordialog_mac.cpp + win32:SOURCES += $$DIALOGS_CPP/qfiledialog_win.cpp + unix:SOURCES += $$DIALOGS_CPP/qprintdialog.cpp + unix:HEADERS += $$DIALOGS_H/qprintdialog.h + + SOURCES += $$DIALOGS_CPP/qcolordialog.cpp \ + $$DIALOGS_CPP/qdialog.cpp \ + $$DIALOGS_CPP/qerrormessage.cpp \ + $$DIALOGS_CPP/qfiledialog.cpp \ + $$DIALOGS_CPP/qfontdialog.cpp \ + $$DIALOGS_CPP/qmessagebox.cpp \ + $$DIALOGS_CPP/qprogressdialog.cpp \ + $$DIALOGS_CPP/qtabdialog.cpp \ + $$DIALOGS_CPP/qwizard.cpp \ + $$DIALOGS_CPP/qinputdialog.cpp +} diff --git a/src/dialogs/qtabdialog.cpp b/src/dialogs/qtabdialog.cpp new file mode 100644 index 000000000..72cf487c7 --- /dev/null +++ b/src/dialogs/qtabdialog.cpp @@ -0,0 +1,1145 @@ +/**************************************************************************** +** +** Implementation of TQTabDialog class +** +** Created : 960825 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qtabdialog.h" + +#ifndef QT_NO_TABDIALOG + +#include "qobjectlist.h" +#include "qtabbar.h" +#include "qtabwidget.h" +#include "qpushbutton.h" +#include "qpainter.h" +#include "qpixmap.h" +#include "qapplication.h" +#include "qtabwidget.h" +#include "qwidgetstack.h" +#include "qlayout.h" + +/*! + \class TQTabDialog qtabdialog.h + + \brief The TQTabDialog class provides a stack of tabbed widgets. + + \ingroup dialogs + \mainclass + + A tabbed dialog is one in which several "tab pages" are available. + By clicking on a tab page's tab or by pressing the indicated + Alt+\e{letter} key combination, the user can select which tab page + they want to use. + + TQTabDialog provides a tab bar consisting of single row of tabs at + the top; each tab has an associated widget which is that tab's + tab page. In addition, TQTabDialog provides an OK button and the + following optional buttons: Apply, Cancel, Defaults and Help. + + The normal way to use TQTabDialog is to do the following in the + constructor: + \list 1 + \i Create a TQTabDialog. + \i Create a TQWidget for each of the pages in the tab dialog, insert + children into it, set up geometry management for it, and use + addTab() (or insertTab()) to set up a tab and keyboard accelerator + for it. + \i Set up the buttons for the tab dialog using setOkButton(), + setApplyButton(), setDefaultsButton(), setCancelButton() and + setHelpButton(). + \i Connect to the signals and slots. + \endlist + + If you don't call addTab() the page you have created will not be + visible. Don't confuse the object name you supply to the + TQWidget constructor and the tab label you supply to addTab(); + addTab() takes user-visible name that appears on the widget's tab + and may identify an accelerator, whereas the widget name is used + primarily for debugging. + + Almost all applications have to connect the applyButtonPressed() + signal to something. applyButtonPressed() is emitted when either OK + or Apply is clicked, and your slot must copy the dialog's state into + the application. + + There are also several other signals which may be useful: + \list + \i cancelButtonPressed() is emitted when the user clicks Cancel. + \i defaultButtonPressed() is emitted when the user clicks Defaults; + the slot it is connected to should reset the state of the dialog to + the application defaults. + \i helpButtonPressed() is emitted when the user clicks Help. + \i aboutToShow() is emitted at the start of show(); if there is any + chance that the state of the application may change between the + creation of the tab dialog and the time show() is called, you must + connect this signal to a slot that resets the state of the dialog. + \i currentChanged() is emitted when the user selects a page. + \endlist + + Each tab is either enabled or disabled at any given time (see + setTabEnabled()). If a tab is enabled the tab text is drawn in + black and the user can select that tab. If it is disabled the tab + is drawn in a different way and the user cannot select that tab. + Note that even if a tab is disabled, the page can still be visible; + for example, if all of the tabs happen to be disabled. + + You can change a tab's label and iconset using changeTab(). A tab + page can be removed with removePage() and shown with showPage(). The + current page is given by currentPage(). + + TQTabDialog does not support tabs on the sides or bottom, nor can + you set or retrieve the visible page. If you need more functionality + than TQTabDialog provides, consider creating a TQDialog and using a + TQTabBar with TQTabWidgets. + + Most of the functionality in TQTabDialog is provided by a TQTabWidget. + + <img src=qtabdlg-m.png> <img src=qtabdlg-w.png> + + \sa TQDialog +*/ + +/*! + \fn void TQTabDialog::selected( const TQString & ); + \obsolete + + This signal is emitted whenever a tab is selected (raised), + including during the first show(). + + \sa raise() +*/ + +/*! \fn void TQTabDialog::currentChanged( TQWidget* ); + + This signal is emitted whenever the current page changes. + + \sa currentPage(), showPage(), tabLabel() +*/ + + +// add comments about delete, ok and apply + +class TQTabDialogPrivate +{ +public: + TQTabDialogPrivate(); + + TQTabWidget* tw; + + TQPushButton * ok; + TQPushButton * cb; + TQPushButton * db; + TQPushButton * hb; + TQPushButton * ab; + + TQBoxLayout * tll; +}; + +TQTabDialogPrivate::TQTabDialogPrivate() + : tw(0), + ok(0), cb(0), db(0), hb(0), ab(0), + tll(0) +{ } + +/*! + Constructs a TQTabDialog with only an OK button. + The \a parent, \a name, \a modal and widget flag, \a f, arguments + are passed on to the TQDialog constructor. +*/ + +TQTabDialog::TQTabDialog( TQWidget *parent, const char *name, bool modal, + WFlags f ) + : TQDialog( parent, name, modal, f ) +{ + d = new TQTabDialogPrivate; + Q_CHECK_PTR( d ); + + d->tw = new TQTabWidget( this, "tab widget" ); + connect ( d->tw, SIGNAL ( selected(const TQString&) ), this, SIGNAL( selected(const TQString&) ) ); + connect ( d->tw, SIGNAL ( currentChanged(TQWidget*) ), this, SIGNAL( currentChanged(TQWidget*) ) ); + + d->ok = new TQPushButton( this, "ok" ); + Q_CHECK_PTR( d->ok ); + d->ok->setText( tr("OK") ); + d->ok->setDefault( TRUE ); + connect( d->ok, SIGNAL(clicked()), + this, SIGNAL(applyButtonPressed()) ); + connect( d->ok, SIGNAL(clicked()), + this, SLOT(accept()) ); +} + + +/*! + Destroys the tab dialog. +*/ + +TQTabDialog::~TQTabDialog() +{ + delete d; +} + + +/*! + Sets the font for the tabs to \a font. + + If the widget is visible, the display is updated with the new font + immediately. There may be some geometry changes, depending on the + size of the old and new fonts. +*/ + +void TQTabDialog::setFont( const TQFont & font ) +{ + TQDialog::setFont( font ); + setSizes(); +} + + +/*! + \fn void TQTabDialog::applyButtonPressed(); + + This signal is emitted when either the Apply or OK button is clicked. + + It should be connected to a slot (or several slots) that change the + application's state according to the state of the dialog. + + \sa cancelButtonPressed() defaultButtonPressed() setApplyButton() +*/ + + +/*! + Returns TRUE if the tab dialog has a Defaults button; otherwise + returns FALSE. + + \sa setDefaultButton() defaultButtonPressed() hasApplyButton() + hasCancelButton() +*/ + +bool TQTabDialog::hasDefaultButton() const +{ + return d->db != 0; +} + + +/*! + Returns TRUE if the tab dialog has a Help button; otherwise returns + FALSE. + + \sa setHelpButton() helpButtonPressed() hasApplyButton() + hasCancelButton() +*/ + +bool TQTabDialog::hasHelpButton() const +{ + return d->hb != 0; +} + + +/*! + \fn void TQTabDialog::cancelButtonPressed(); + + This signal is emitted when the Cancel button is clicked. It is + automatically connected to TQDialog::reject(), which will hide the + dialog. + + The Cancel button should not change the application's state at all, + so you should generally not need to connect it to any slot. + + \sa applyButtonPressed() defaultButtonPressed() setCancelButton() +*/ + + +/*! + Returns TRUE if the tab dialog has a Cancel button; otherwise + returns FALSE. + + \sa setCancelButton() cancelButtonPressed() hasApplyButton() + hasDefaultButton() +*/ + +bool TQTabDialog::hasCancelButton() const +{ + return d->cb != 0; +} + + +/*! + \fn void TQTabDialog::defaultButtonPressed(); + + This signal is emitted when the Defaults button is pressed. It + should reset the dialog (but not the application) to the "factory + defaults". + + The application's state should not be changed until the user clicks + Apply or OK. + + \sa applyButtonPressed() cancelButtonPressed() setDefaultButton() +*/ + + +/*! + \fn void TQTabDialog::helpButtonPressed(); + + This signal is emitted when the Help button is pressed. It + could be used to present information about how to use the dialog. + + \sa applyButtonPressed() cancelButtonPressed() setHelpButton() +*/ + + +/*! + Returns TRUE if the tab dialog has an Apply button; otherwise + returns FALSE. + + \sa setApplyButton() applyButtonPressed() hasCancelButton() + hasDefaultButton() +*/ + +bool TQTabDialog::hasApplyButton() const +{ + return d->ab != 0; +} + + +/*! + Returns TRUE if the tab dialog has an OK button; otherwise returns + FALSE. + + \sa setOkButton() hasApplyButton() hasCancelButton() + hasDefaultButton() +*/ + +bool TQTabDialog::hasOkButton() const +{ + return d->ok != 0; +} + + +/*! + \fn void TQTabDialog::aboutToShow() + + This signal is emitted by show() when it is time to set the state of + the dialog's contents. The dialog should reflect the current state + of the application when it appears; if there is any possibility that + the state of the application may change between the time you call + TQTabDialog::TQTabDialog() and TQTabDialog::show(), you should set the + dialog's state in a slot and connect this signal to it. + + This applies mainly to TQTabDialog objects that are kept around + hidden, rather than being created, shown, and deleted afterwards. + + \sa applyButtonPressed(), show(), cancelButtonPressed() +*/ + + +/*!\reimp +*/ +void TQTabDialog::show() +{ + // Reimplemented in order to delay show()'ing of every page + // except the initially visible one, and in order to emit the + // aboutToShow() signal. + if ( topLevelWidget() == this ) + d->tw->setFocus(); + emit aboutToShow(); + setSizes(); + setUpLayout(); + TQDialog::show(); +} + + +/*! + Ensures that tab page \a i is visible and appropriately sized. +*/ + +void TQTabDialog::showTab( int i ) +{ + d->tw->showTab( i ); +} + + +/*! + Adds another tab and page to the tab view. + + The new page is \a child; the tab's label is \a label. + Note the difference between the widget name (which you supply to + widget constructors and to setTabEnabled(), for example) and the tab + label. The name is internal to the program and invariant, whereas + the label is shown on-screen and may vary according to language and + other factors. + + If the tab's \a label contains an ampersand, the letter following + the ampersand is used as an accelerator for the tab, e.g. if the + label is "Bro&wse" then Alt+W becomes an accelerator which will + move the focus to this tab. + + If you call addTab() after show() the screen will flicker and the + user may be confused. + + \sa insertTab() +*/ + +void TQTabDialog::addTab( TQWidget * child, const TQString &label ) +{ + d->tw->addTab( child, label ); +} + + + +/*! \overload + + This version of the function shows the \a iconset as well as the \a + label on the tab of \a child. +*/ +void TQTabDialog::addTab( TQWidget *child, const TQIconSet& iconset, const TQString &label) +{ + d->tw->addTab( child, iconset, label ); +} + +/*! + \overload + + This is a lower-level method for adding tabs, similar to the other + addTab() method. It is useful if you are using setTabBar() to set a + TQTabBar subclass with an overridden TQTabBar::paint() function for a + subclass of TQTab. + + The \a child is the widget to be placed on the new tab page. The \a + tab is the tab to display on the tab page -- normally this shows a + label or an icon that identifies the tab page. + +*/ +void TQTabDialog::addTab( TQWidget * child, TQTab* tab ) +{ + d->tw->addTab( child, tab ); +} + +/*! + Inserts another tab and page to the tab view. + + The new page is \a child; the tab's label is \a label. + Note the difference between the widget name (which you supply to + widget constructors and to setTabEnabled(), for example) and the tab + label. The name is internal to the program and invariant, whereas + the label is shown on-screen and may vary according to language and + other factors. + + If the tab's \a label contains an ampersand, the letter following + the ampersand is used as an accelerator for the tab, e.g. if the + label is "Bro&wse" then Alt+W becomes an accelerator which will + move the focus to this tab. + + If \a index is not specified, the tab is simply added. Otherwise + it is inserted at the specified position. + + If you call insertTab() after show(), the screen will flicker and the + user may be confused. + + \sa addTab() +*/ + +void TQTabDialog::insertTab( TQWidget * child, const TQString &label, int index ) +{ + d->tw->insertTab( child, label, index ); +} + + +/*! \overload + + This version of the function shows the \a iconset as well as the \a + label on the tab of \a child. + */ +void TQTabDialog::insertTab( TQWidget *child, const TQIconSet& iconset, const TQString &label, int index) +{ + d->tw->insertTab( child, iconset, label, index ); +} + +/*! + \overload + + This is a lower-level method for inserting tabs, similar to the other + insertTab() method. It is useful if you are using setTabBar() to set a + TQTabBar subclass with an overridden TQTabBar::paint() function for a + subclass of TQTab. + + The \a child is the widget to be placed on the new tab page. The \a + tab is the tab to display on the tab page -- normally this shows a + label or an icon that identifies the tab page. The \a index is the + position where this tab page should be inserted. + +*/ +void TQTabDialog::insertTab( TQWidget * child, TQTab* tab, int index ) +{ + d->tw->insertTab( child, tab, index ); +} + +/*! + Replaces the TQTabBar heading the dialog by the given tab bar, \a tb. + Note that this must be called \e before any tabs have been added, + or the behavior is undefined. + \sa tabBar() +*/ +void TQTabDialog::setTabBar( TQTabBar* tb ) +{ + d->tw->setTabBar( tb ); + setUpLayout(); +} + +/*! + Returns the currently set TQTabBar. + \sa setTabBar() +*/ +TQTabBar* TQTabDialog::tabBar() const +{ + return d->tw->tabBar(); +} + +/*! Ensures that widget \a w is shown. This is mainly useful for accelerators. + + \warning If used carelessly, this function can easily surprise or + confuse the user. + + \sa TQTabBar::setCurrentTab() +*/ + +void TQTabDialog::showPage( TQWidget * w ) +{ + d->tw->showPage( w ); +} + + +/*! \obsolete + Returns TRUE if the page with object name \a name is enabled and + FALSE if it is disabled. + + If \a name is 0 or not the name of any of the pages, isTabEnabled() + returns FALSE. + + \sa setTabEnabled(), TQWidget::isEnabled() +*/ + +bool TQTabDialog::isTabEnabled( const char* name ) const +{ + if ( !name ) + return FALSE; + TQObjectList * l + = ((TQTabDialog *)this)->queryList( "TQWidget", name, FALSE, TRUE ); + if ( l && l->first() ) { + TQWidget * w; + while( l->current() ) { + while( l->current() && !l->current()->isWidgetType() ) + l->next(); + w = (TQWidget *)(l->current()); + if ( w ) { + bool enabled = d->tw->isTabEnabled( w ); + delete l; + return enabled; + } + } + } + delete l; + return FALSE; +} + + +/*!\obsolete + + Finds the page with object name \a name, enables/disables it + according to the value of \a enable and redraws the page's tab + appropriately. + + TQTabDialog uses TQWidget::setEnabled() internally, rather than keeping a + separate flag. + + Note that even a disabled tab/page may be visible. If the page is + already visible TQTabDialog will not hide it; if all the pages + are disabled TQTabDialog will show one of them. + + The object name is used (rather than the tab label) because the tab + text may not be invariant in multi-language applications. + + \sa isTabEnabled(), TQWidget::setEnabled() +*/ + +void TQTabDialog::setTabEnabled( const char* name, bool enable ) +{ + if ( !name ) + return; + TQObjectList * l + = ((TQTabDialog *)this)->queryList( "TQWidget", name, FALSE, TRUE ); + if ( l && l->first() ) { + TQObjectListIt it(*l); + TQObject *o; + while( (o = it.current()) ) { + ++it; + if( o->isWidgetType() ) + d->tw->setTabEnabled( (TQWidget*)o, enable ); + } + } + delete l; +} + + +/* ### SHOULD THIS BE HERE? + Adds an Apply button to the dialog. The button's text is set to \e + text (and defaults to "Apply"). + + The Apply button should apply the current settings in the dialog box + to the application, while keeping the dialog visible. + + When Apply is clicked, the applyButtonPressed() signal is emitted. + + If \a text is a + \link TQString::operator!() null string\endlink, + no button is shown. + + \sa setCancelButton() setDefaultButton() applyButtonPressed() +*/ + + +/*! + Returns TRUE if the page \a w is enabled; otherwise returns FALSE. + + \sa setTabEnabled(), TQWidget::isEnabled() +*/ + +bool TQTabDialog::isTabEnabled( TQWidget* w ) const +{ + return d->tw->isTabEnabled( w ); +} + +/*! + If \a enable is TRUE the page \a w is enabled; otherwise \a w is + disabled. The page's tab is redrawn appropriately. + + TQTabWidget uses TQWidget::setEnabled() internally, rather than keeping a + separate flag. + + Note that even a disabled tab and tab page may be visible. If the + page is already visible TQTabWidget will not hide it; if all the + pages are disabled TQTabWidget will show one of them. + + \sa isTabEnabled(), TQWidget::setEnabled() +*/ + +void TQTabDialog::setTabEnabled( TQWidget* w, bool enable) +{ + d->tw->setTabEnabled( w, enable ); +} + + +/*! + Adds an Apply button to the dialog. The button's text is set to \a + text. + + The Apply button should apply the current settings in the dialog box + to the application while keeping the dialog visible. + + When Apply is clicked, the applyButtonPressed() signal is emitted. + + If \a text is a + \link TQString::operator!() null string\endlink, + no button is shown. + + \sa setCancelButton() setDefaultButton() applyButtonPressed() +*/ +void TQTabDialog::setApplyButton( const TQString &text ) +{ + if ( !text && d->ab ) { + delete d->ab; + d->ab = 0; + setSizes(); + } else { + if ( !d->ab ) { + d->ab = new TQPushButton( this, "apply settings" ); + connect( d->ab, SIGNAL(clicked()), + this, SIGNAL(applyButtonPressed()) ); + setUpLayout(); + } + d->ab->setText( text ); + setSizes(); + //d->ab->show(); + } +} + +/*! + \overload + + Adds an Apply button to the dialog. The button's text is set to + a localizable "Apply". + */ +void TQTabDialog::setApplyButton() +{ + setApplyButton( tr("Apply") ); +} + + +/*! + Adds a Help button to the dialog. The button's text is set to \a + text. + + When Help is clicked, the helpButtonPressed() signal is emitted. + + If \a text is a + \link TQString::operator!() null string\endlink, + no button is shown. + + \sa setApplyButton() setCancelButton() helpButtonPressed() +*/ + +void TQTabDialog::setHelpButton( const TQString &text ) +{ + if ( !text ) { + delete d->hb; + d->hb = 0; + setSizes(); + } else { + if ( !d->hb ) { + d->hb = new TQPushButton( this, "give help" ); + connect( d->hb, SIGNAL(clicked()), + this, SIGNAL(helpButtonPressed()) ); + setUpLayout(); + } + d->hb->setText( text ); + setSizes(); + //d->hb->show(); + } +} + + +/*! + \overload + + Adds a Help button to the dialog. The button's text is set to + a localizable "Help". + */ +void TQTabDialog::setHelpButton() +{ + setHelpButton( tr("Help") ); +} + +/*! + Adds a Defaults button to the dialog. The button's text is set to \a + text. + + The Defaults button should set the dialog (but not the application) + back to the application defaults. + + When Defaults is clicked, the defaultButtonPressed() signal is emitted. + + If \a text is a + \link TQString::operator!() null string\endlink, + no button is shown. + + \sa setApplyButton() setCancelButton() defaultButtonPressed() +*/ + +void TQTabDialog::setDefaultButton( const TQString &text ) +{ + if ( !text ) { + delete d->db; + d->db = 0; + setSizes(); + } else { + if ( !d->db ) { + d->db = new TQPushButton( this, "back to default" ); + connect( d->db, SIGNAL(clicked()), + this, SIGNAL(defaultButtonPressed()) ); + setUpLayout(); + } + d->db->setText( text ); + setSizes(); + //d->db->show(); + } +} + + +/*! + \overload + + Adds a Defaults button to the dialog. The button's text is set to + a localizable "Defaults". + */ +void TQTabDialog::setDefaultButton() +{ + setDefaultButton( tr("Defaults") ); +} + +/*! + Adds a Cancel button to the dialog. The button's text is set to \a + text. + + The cancel button should always return the application to the state + it was in before the tab view popped up, or if the user has clicked + Apply, back to the state immediately after the last Apply. + + When Cancel is clicked, the cancelButtonPressed() signal is emitted. + The dialog is closed at the same time. + + If \a text is a + \link TQString::operator!() null string\endlink, + no button is shown. + + \sa setApplyButton() setDefaultButton() cancelButtonPressed() +*/ + +void TQTabDialog::setCancelButton( const TQString &text ) +{ + if ( !text ) { + delete d->cb; + d->cb = 0; + setSizes(); + } else { + if ( !d->cb ) { + d->cb = new TQPushButton( this, "cancel dialog" ); + connect( d->cb, SIGNAL(clicked()), + this, SIGNAL(cancelButtonPressed()) ); + connect( d->cb, SIGNAL(clicked()), + this, SLOT(reject()) ); + setUpLayout(); + } + d->cb->setText( text ); + setSizes(); + //d->cb->show(); + } +} + + +/*! + \overload + + Adds a Cancel button to the dialog. The button's text is set to + a localizable "Cancel". + */ + +void TQTabDialog::setCancelButton() +{ + setCancelButton( tr("Cancel") ); +} + + +/*! Sets up the layout manager for the tab dialog. + + \sa setSizes() setApplyButton() setCancelButton() setDefaultButton() +*/ + +void TQTabDialog::setUpLayout() +{ + // the next four are probably the same, really? + const int topMargin = 6; + const int leftMargin = 6; + const int rightMargin = 6; + const int bottomMargin = 6; + const int betweenButtonsMargin = 7; + const int aboveButtonsMargin = 8; + + delete d->tll; + d->tll = new TQBoxLayout( this, TQBoxLayout::Down ); + + // top margin + d->tll->addSpacing( topMargin ); + + TQBoxLayout * tmp = new TQHBoxLayout(); + d->tll->addLayout( tmp, 1 ); + tmp->addSpacing( leftMargin ); + tmp->addWidget( d->tw, 1); + tmp->addSpacing( rightMargin + 2 ); + + d->tll->addSpacing( aboveButtonsMargin + 2 ); + TQBoxLayout * buttonRow = new TQBoxLayout(TQBoxLayout::RightToLeft); + d->tll->addLayout( buttonRow, 0 ); + d->tll->addSpacing( bottomMargin ); + + buttonRow->addSpacing( rightMargin ); + if ( d->cb ) { + buttonRow->addWidget( d->cb, 0 ); + buttonRow->addSpacing( betweenButtonsMargin ); + d->cb->raise(); + } + + if ( d->ab ) { + buttonRow->addWidget( d->ab, 0 ); + buttonRow->addSpacing( betweenButtonsMargin ); + d->ab->raise(); + } + + if ( d->db ) { + buttonRow->addWidget( d->db, 0 ); + buttonRow->addSpacing( betweenButtonsMargin ); + d->db->raise(); + } + + if ( d->hb ) { + buttonRow->addWidget( d->hb, 0 ); + buttonRow->addSpacing( betweenButtonsMargin ); + d->hb->raise(); + } + + if ( d->ok ) { + buttonRow->addWidget( d->ok, 0 ); + buttonRow->addSpacing( betweenButtonsMargin ); + d->ok->raise(); + } + + // add one custom widget here + buttonRow->addStretch( 1 ); + // add another custom widget here + + d->tll->activate(); +} + + +/*! Sets up the minimum and maximum sizes for each child widget. + + \sa setUpLayout() setFont() +*/ + +void TQTabDialog::setSizes() +{ + // compute largest button size + TQSize s( 0, 0 ); + int bw = s.width(); + int bh = s.height(); + + if ( d->ok ) { + s = d->ok->sizeHint(); + if ( s.width() > bw ) + bw = s.width(); + if ( s.height() > bh ) + bh = s.height(); + } + + if ( d->ab ) { + s = d->ab->sizeHint(); + if ( s.width() > bw ) + bw = s.width(); + if ( s.height() > bh ) + bh = s.height(); + } + + if ( d->db ) { + s = d->db->sizeHint(); + if ( s.width() > bw ) + bw = s.width(); + if ( s.height() > bh ) + bh = s.height(); + } + + if ( d->hb ) { + s = d->hb->sizeHint(); + if ( s.width() > bw ) + bw = s.width(); + if ( s.height() > bh ) + bh = s.height(); + } + + if ( d->cb ) { + s = d->cb->sizeHint(); + if ( s.width() > bw ) + bw = s.width(); + if ( s.height() > bh ) + bh = s.height(); + } + + // and set all the buttons to that size + if ( d->ok ) + d->ok->setFixedSize( bw, bh ); + if ( d->ab ) + d->ab->setFixedSize( bw, bh ); + if ( d->db ) + d->db->setFixedSize( bw, bh ); + if ( d->hb ) + d->hb->setFixedSize( bw, bh ); + if ( d->cb ) + d->cb->setFixedSize( bw, bh ); + + // fiddle the tab chain so the buttons are in their natural order + TQWidget * w = d->ok; + + if ( d->hb ) { + if ( w ) + setTabOrder( w, d->hb ); + w = d->hb; + } + if ( d->db ) { + if ( w ) + setTabOrder( w, d->db ); + w = d->db; + } + if ( d->ab ) { + if ( w ) + setTabOrder( w, d->ab ); + w = d->ab; + } + if ( d->cb ) { + if ( w ) + setTabOrder( w, d->cb ); + w = d->cb; + } + setTabOrder( w, d->tw ); +} + +/*!\reimp +*/ +void TQTabDialog::resizeEvent( TQResizeEvent * e ) +{ + TQDialog::resizeEvent( e ); +} + + +/*!\reimp +*/ +void TQTabDialog::paintEvent( TQPaintEvent * ) +{ +} + + +/*! + Adds an OK button to the dialog and sets the button's text to \a text. + + When the OK button is clicked, the applyButtonPressed() signal is emitted, + and the current settings in the dialog box should be applied to + the application. The dialog then closes. + + If \a text is a + \link TQString::operator!() null string\endlink, + no button is shown. + + \sa setCancelButton() setDefaultButton() applyButtonPressed() +*/ + +void TQTabDialog::setOkButton( const TQString &text ) +{ + if ( !text ) { + delete d->ok; + d->ok = 0; + setSizes(); + } else { + if ( !d->ok ) { + d->ok = new TQPushButton( this, "ok" ); + connect( d->ok, SIGNAL(clicked()), + this, SIGNAL(applyButtonPressed()) ); + setUpLayout(); + } + d->ok->setText( text ); + setSizes(); + //d->ok->show(); + } +} +/*! + \overload + + Adds an OK button to the dialog. The button's text is set to + a localizable "OK". + */ + +void TQTabDialog::setOkButton() +{ + setOkButton( tr("OK") ); +} + + +/* + \overload + Old version of setOkButton(), provided for backward compatibility. +*/ +void TQTabDialog::setOKButton( const TQString &text ) +{ + // Ugly workaround for original "OK" default argument + TQString newText( text ); + if ( text.isNull() ) + newText = TQString::fromLatin1( "OK" ); + setOkButton( newText ); +} + + +/*! Returns the text in the tab for page \a w. +*/ + +TQString TQTabDialog::tabLabel( TQWidget * w ) +{ + return d->tw->tabLabel( w ); +} + + +/*! \reimp +*/ +void TQTabDialog::styleChange( TQStyle& s ) +{ + TQDialog::styleChange( s ); + setSizes(); +} + + +/*! Returns a pointer to the page currently being displayed by the +tab dialog. The tab dialog does its best to make sure that this value +is never 0 (but if you try hard enough, it can be). +*/ + +TQWidget * TQTabDialog::currentPage() const +{ + return d->tw->currentPage(); +} + +/*! + \overload + Defines a new \a label for the tab of page \a w + */ +void TQTabDialog::changeTab( TQWidget *w, const TQString &label) +{ + d->tw->changeTab( w, label ); +} + +/*! + Changes tab page \a w's iconset to \a iconset and label to \a label. + + */ +void TQTabDialog::changeTab( TQWidget *w, const TQIconSet& iconset, const TQString &label) +{ + d->tw->changeTab( w, iconset, label ); +} + +/*! Removes page \a w from this stack of widgets. Does not + delete \a w. + \sa showPage(), TQTabWidget::removePage(), TQWidgetStack::removeWidget() +*/ +void TQTabDialog::removePage( TQWidget * w ) +{ + d->tw->removePage( w ); +} + +#endif diff --git a/src/dialogs/qtabdialog.h b/src/dialogs/qtabdialog.h new file mode 100644 index 000000000..4165b25c0 --- /dev/null +++ b/src/dialogs/qtabdialog.h @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Definition of TQTabDialog class +** +** Created : 960825 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQTABDIALOG_H +#define TQTABDIALOG_H + +#ifndef QT_H +#include "qdialog.h" +#include "qiconset.h" +#endif // QT_H + +#ifndef QT_NO_TABDIALOG + +class TQTabBar; +class TQTab; +class TQTabDialogPrivate; + +class Q_EXPORT TQTabDialog : public TQDialog +{ + Q_OBJECT +public: + TQTabDialog( TQWidget* parent=0, const char* name=0, bool modal=FALSE, + WFlags f=0 ); + ~TQTabDialog(); + + void show(); + void setFont( const TQFont & font ); + + void addTab( TQWidget *, const TQString &); + void addTab( TQWidget *child, const TQIconSet& iconset, const TQString &label); + void addTab( TQWidget *, TQTab* ); + + void insertTab( TQWidget *, const TQString &, int index = -1); + void insertTab( TQWidget *child, const TQIconSet& iconset, const TQString &label, int index = -1); + void insertTab( TQWidget *, TQTab*, int index = -1 ); + + void changeTab( TQWidget *, const TQString &); + void changeTab( TQWidget *child, const TQIconSet& iconset, const TQString &label); + + bool isTabEnabled( TQWidget * ) const; + void setTabEnabled( TQWidget *, bool ); + bool isTabEnabled( const char* ) const; // compatibility + void setTabEnabled( const char*, bool ); // compatibility + + void showPage( TQWidget * ); + void removePage( TQWidget * ); + TQString tabLabel( TQWidget * ); + + TQWidget * currentPage() const; + + void setDefaultButton( const TQString &text ); + void setDefaultButton(); + bool hasDefaultButton() const; + + void setHelpButton( const TQString &text ); + void setHelpButton(); + bool hasHelpButton() const; + + void setCancelButton( const TQString &text ); + void setCancelButton(); + bool hasCancelButton() const; + + void setApplyButton( const TQString &text ); + void setApplyButton(); + bool hasApplyButton() const; + +#ifndef Q_QDOC + void setOKButton( const TQString &text = TQString::null ); +#endif + void setOkButton( const TQString &text ); + void setOkButton(); + bool hasOkButton() const; + +protected: + void paintEvent( TQPaintEvent * ); + void resizeEvent( TQResizeEvent * ); + void styleChange( TQStyle& ); + void setTabBar( TQTabBar* ); + TQTabBar* tabBar() const; + +signals: + void aboutToShow(); + + void applyButtonPressed(); + void cancelButtonPressed(); + void defaultButtonPressed(); + void helpButtonPressed(); + + void currentChanged( TQWidget * ); + void selected( const TQString& ); // obsolete + +private slots: + void showTab( int i ); + +private: + void setSizes(); + void setUpLayout(); + + TQTabDialogPrivate *d; +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQTabDialog( const TQTabDialog & ); + TQTabDialog& operator=( const TQTabDialog & ); +#endif +}; + +#endif // QT_NO_TABDIALOG + +#endif // TQTABDIALOG_H diff --git a/src/dialogs/qwizard.cpp b/src/dialogs/qwizard.cpp new file mode 100644 index 000000000..08213577b --- /dev/null +++ b/src/dialogs/qwizard.cpp @@ -0,0 +1,917 @@ +/**************************************************************************** +** +** Implementation of TQWizard class. +** +** Created : 990124 +** +** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qwizard.h" + +#ifndef QT_NO_WIZARD + +#include "qlayout.h" +#include "qpushbutton.h" +#include "qcursor.h" +#include "qlabel.h" +#include "qwidgetstack.h" +#include "qapplication.h" +#include "qptrlist.h" +#include "qpainter.h" +#include "qaccel.h" + +/*! \file wizard/wizard.cpp */ +/*! \file wizard/wizard.h */ + +/*! + \class TQWizard qwizard.h + \brief The TQWizard class provides a framework for wizard dialogs. + + \ingroup abstractwidgets + \ingroup organizers + \ingroup dialogs + \mainclass + + A wizard is a special type of input dialog that consists of a + sequence of dialog pages. A wizard's purpose is to walk the user + through a process step by step. Wizards are useful for complex or + infrequently occurring tasks that people may find difficult to + learn or do. + + TQWizard provides page titles and displays Next, Back, Finish, + Cancel, and Help push buttons, as appropriate to the current + position in the page sequence. These buttons can be + enabled/disabled using setBackEnabled(), setNextEnabled(), + setFinishEnabled() and setHelpEnabled(). + + Create and populate dialog pages that inherit from TQWidget and add + them to the wizard using addPage(). Use insertPage() to add a + dialog page at a certain position in the page sequence. Use + removePage() to remove a page from the page sequence. + + Use currentPage() to retrieve a pointer to the currently displayed + page. page() returns a pointer to the page at a certain position + in the page sequence. + + Use pageCount() to retrieve the total number of pages in the page + sequence. indexOf() will return the index of a page in the page + sequence. + + TQWizard provides functionality to mark pages as appropriate (or + not) in the current context with setAppropriate(). The idea is + that a page may be irrelevant and should be skipped depending on + the data entered by the user on a preceding page. + + It is generally considered good design to provide a greater number + of simple pages with fewer choices rather than a smaller number of + complex pages. + + Example code is available here: \l wizard/wizard.cpp \l wizard/wizard.h + + \img qwizard.png A TQWizard page + \caption A TQWizard page + +*/ + + +class TQWizardPrivate +{ +public: + struct Page { + Page( TQWidget * widget, const TQString & title ): + w( widget ), t( title ), + backEnabled( TRUE ), nextEnabled( TRUE ), finishEnabled( FALSE ), + helpEnabled( TRUE ), + appropriate( TRUE ) + {} + TQWidget * w; + TQString t; + bool backEnabled; + bool nextEnabled; + bool finishEnabled; + bool helpEnabled; + bool appropriate; + }; + + TQVBoxLayout * v; + Page * current; + TQWidgetStack * ws; + TQPtrList<Page> pages; + TQLabel * title; + TQPushButton * backButton; + TQPushButton * nextButton; + TQPushButton * finishButton; + TQPushButton * cancelButton; + TQPushButton * helpButton; + + TQFrame * hbar1, * hbar2; + +#ifndef QT_NO_ACCEL + TQAccel * accel; + int backAccel; + int nextAccel; +#endif + + Page * page( const TQWidget * w ) + { + if ( !w ) + return 0; + int i = pages.count(); + while( --i >= 0 && pages.at( i ) && pages.at( i )->w != w ) { } + return i >= 0 ? pages.at( i ) : 0; + } + +}; + + +/*! + Constructs an empty wizard dialog. The \a parent, \a name, \a + modal and \a f arguments are passed to the TQDialog constructor. +*/ + +TQWizard::TQWizard( TQWidget *parent, const char *name, bool modal, + WFlags f ) + : TQDialog( parent, name, modal, f ) +{ + d = new TQWizardPrivate(); + d->current = 0; // not tquite true, but... + d->ws = new TQWidgetStack( this, "qt_widgetstack" ); + d->pages.setAutoDelete( TRUE ); + d->title = new TQLabel( this, "title label" ); + + // create in nice tab order + d->nextButton = new TQPushButton( this, "next" ); + d->finishButton = new TQPushButton( this, "finish" ); + d->helpButton = new TQPushButton( this, "help" ); + d->backButton = new TQPushButton( this, "back" ); + d->cancelButton = new TQPushButton( this, "cancel" ); + + d->ws->installEventFilter( this ); + + d->v = 0; + d->hbar1 = 0; + d->hbar2 = 0; + + d->cancelButton->setText( tr( "&Cancel" ) ); + d->backButton->setText( tr( "< &Back" ) ); + d->nextButton->setText( tr( "&Next >" ) ); + d->finishButton->setText( tr( "&Finish" ) ); + d->helpButton->setText( tr( "&Help" ) ); + + d->nextButton->setDefault( TRUE ); + + connect( d->backButton, SIGNAL(clicked()), + this, SLOT(back()) ); + connect( d->nextButton, SIGNAL(clicked()), + this, SLOT(next()) ); + connect( d->finishButton, SIGNAL(clicked()), + this, SLOT(accept()) ); + connect( d->cancelButton, SIGNAL(clicked()), + this, SLOT(reject()) ); + connect( d->helpButton, SIGNAL(clicked()), + this, SLOT(help()) ); + +#ifndef QT_NO_ACCEL + d->accel = new TQAccel( this, "arrow-key accel" ); + d->backAccel = d->accel->insertItem( TQt::ALT + TQt::Key_Left ); + d->accel->connectItem( d->backAccel, this, SLOT(back()) ); + d->nextAccel = d->accel->insertItem( TQt::ALT + TQt::Key_Right ); + d->accel->connectItem( d->nextAccel, this, SLOT(next()) ); +#endif +} + + +/*! + Destroys the object and frees any allocated resources, including + all pages and controllers. +*/ + +TQWizard::~TQWizard() +{ + delete d; +} + + +/*! + \reimp +*/ + +void TQWizard::show() +{ + if ( !d->current ) { + // No page yet + if ( pageCount() > 0 ) + showPage( d->pages.at( 0 )->w ); + else + showPage( 0 ); + } + + TQDialog::show(); +} + + +/*! + \reimp +*/ + +void TQWizard::setFont( const TQFont & font ) +{ + TQApplication::postEvent( this, new TQEvent( TQEvent::LayoutHint ) ); + TQDialog::setFont( font ); +} + + +/*! + Adds \a page to the end of the page sequence, with the title, \a + title. +*/ + +void TQWizard::addPage( TQWidget * page, const TQString & title ) +{ + if ( !page ) + return; + if ( d->page( page ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "TQWizard::addPage(): already added %s/%s to %s/%s", + page->className(), page->name(), + className(), name() ); +#endif + return; + } + int i = d->pages.count(); + + if( i > 0 ) + d->pages.at( i - 1 )->nextEnabled = TRUE; + + TQWizardPrivate::Page * p = new TQWizardPrivate::Page( page, title ); + p->backEnabled = ( i > 0 ); + d->ws->addWidget( page, i ); + d->pages.append( p ); +} + +/*! + Inserts \a page at position \a index into the page sequence, with + title \a title. If \a index is -1, the page will be appended to + the end of the wizard's page sequence. +*/ + +void TQWizard::insertPage( TQWidget * page, const TQString & title, int index ) +{ + if ( !page ) + return; + if ( d->page( page ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "TQWizard::insertPage(): already added %s/%s to %s/%s", + page->className(), page->name(), + className(), name() ); +#endif + return; + } + + if ( index < 0 || index > (int)d->pages.count() ) + index = d->pages.count(); + + if( index > 0 && ( index == (int)d->pages.count() ) ) + d->pages.at( index - 1 )->nextEnabled = TRUE; + + TQWizardPrivate::Page * p = new TQWizardPrivate::Page( page, title ); + p->backEnabled = ( index > 0 ); + p->nextEnabled = ( index < (int)d->pages.count() ); + + d->ws->addWidget( page, index ); + d->pages.insert( index, p ); +} + +/*! + \fn void TQWizard::selected(const TQString&) + + This signal is emitted when the current page changes. The + parameter contains the title of the selected page. +*/ + + +/*! + Makes \a page the current page and emits the selected() signal. + + This virtual function is called whenever a different page is to + be shown, including the first time the TQWizard is shown. + By reimplementing it (and calling TQWizard::showPage()), + you can prepare each page prior to it being shown. +*/ + +void TQWizard::showPage( TQWidget * page ) +{ + TQWizardPrivate::Page * p = d->page( page ); + if ( p ) { + int i; + for( i = 0; i < (int)d->pages.count() && d->pages.at( i ) != p; i++ ); + bool notFirst( FALSE ); + + if( i ) { + i--; + while( ( i >= 0 ) && !notFirst ) { + notFirst |= appropriate( d->pages.at( i )->w ); + i--; + } + } + setBackEnabled( notFirst ); + setNextEnabled( TRUE ); + d->ws->raiseWidget( page ); + d->current = p; + } + + layOut(); + updateButtons(); + emit selected( p ? p->t : TQString::null ); +} + + +/*! + Returns the number of pages in the wizard. +*/ + +int TQWizard::pageCount() const +{ + return d->pages.count(); +} + +/*! + Returns the position of page \a page. If the page is not part of + the wizard -1 is returned. +*/ + +int TQWizard::indexOf( TQWidget* page ) const +{ + TQWizardPrivate::Page * p = d->page( page ); + if ( !p ) return -1; + + return d->pages.find( p ); +} + +/*! + Called when the user clicks the Back button; this function shows + the preceding relevant page in the sequence. + + \sa appropriate() +*/ +void TQWizard::back() +{ + int i = 0; + + while( i < (int)d->pages.count() && d->pages.at( i ) && + d->current && d->pages.at( i )->w != d->current->w ) + i++; + + i--; + while( i >= 0 && ( !d->pages.at( i ) || !appropriate( d->pages.at( i )->w ) ) ) + i--; + + if( i >= 0 ) + if( d->pages.at( i ) ) + showPage( d->pages.at( i )->w ); +} + + +/*! + Called when the user clicks the Next button, this function shows + the next relevant page in the sequence. + + \sa appropriate() +*/ +void TQWizard::next() +{ + int i = 0; + while( i < (int)d->pages.count() && d->pages.at( i ) && + d->current && d->pages.at( i )->w != d->current->w ) + i++; + i++; + while( i <= (int)d->pages.count()-1 && + ( !d->pages.at( i ) || !appropriate( d->pages.at( i )->w ) ) ) + i++; + // if we fell of the end of the world, step back + while ( i > 0 && (i >= (int)d->pages.count() || !d->pages.at( i ) ) ) + i--; + if ( d->pages.at( i ) ) + showPage( d->pages.at( i )->w ); +} + + +/*! + \fn void TQWizard::helpClicked() + + This signal is emitted when the user clicks on the Help button. +*/ + +/*! + Called when the user clicks the Help button, this function emits + the helpClicked() signal. +*/ + +void TQWizard::help() +{ + TQWidget * page = d->ws->visibleWidget(); + if ( !page ) + return; + +#if 0 + TQWizardPage *wpage = ::qt_cast<TQWizardPage*>(page); + if ( wpage ) + emit wpage->helpClicked(); +#endif + emit helpClicked(); +} + + +void TQWizard::setBackEnabled( bool enable ) +{ + d->backButton->setEnabled( enable ); +#ifndef QT_NO_ACCEL + d->accel->setItemEnabled( d->backAccel, enable ); +#endif +} + + +void TQWizard::setNextEnabled( bool enable ) +{ + d->nextButton->setEnabled( enable ); +#ifndef QT_NO_ACCEL + d->accel->setItemEnabled( d->nextAccel, enable ); +#endif +} + + +void TQWizard::setHelpEnabled( bool enable ) +{ + d->helpButton->setEnabled( enable ); +} + + +/*! + \fn void TQWizard::setFinish( TQWidget *, bool ) + \obsolete + + Use setFinishEnabled instead +*/ + +/*! + If \a enable is TRUE, page \a page has a Back button; otherwise \a + page has no Back button. By default all pages have this button. +*/ +void TQWizard::setBackEnabled( TQWidget * page, bool enable ) +{ + TQWizardPrivate::Page * p = d->page( page ); + if ( !p ) + return; + + p->backEnabled = enable; + updateButtons(); +} + + +/*! + If \a enable is TRUE, page \a page has a Next button; otherwise + the Next button on \a page is disabled. By default all pages have + this button. +*/ + +void TQWizard::setNextEnabled( TQWidget * page, bool enable ) +{ + TQWizardPrivate::Page * p = d->page( page ); + if ( !p ) + return; + + p->nextEnabled = enable; + updateButtons(); +} + + +/*! + If \a enable is TRUE, page \a page has a Finish button; otherwise + \a page has no Finish button. By default \e no page has this + button. +*/ +void TQWizard::setFinishEnabled( TQWidget * page, bool enable ) +{ + TQWizardPrivate::Page * p = d->page( page ); + if ( !p ) + return; + + p->finishEnabled = enable; + updateButtons(); +} + + +/*! + If \a enable is TRUE, page \a page has a Help button; otherwise \a + page has no Help button. By default all pages have this button. +*/ +void TQWizard::setHelpEnabled( TQWidget * page, bool enable ) +{ + TQWizardPrivate::Page * p = d->page( page ); + if ( !p ) + return; + + p->helpEnabled = enable; + updateButtons(); +} + + +/*! + Called when the Next button is clicked; this virtual function + returns TRUE if \a page is relevant for display in the current + context; otherwise it is ignored by TQWizard and returns FALSE. The + default implementation returns the value set using + setAppropriate(). The ultimate default is TRUE. + + \warning The last page of the wizard will be displayed if no page + is relevant in the current context. +*/ + +bool TQWizard::appropriate( TQWidget * page ) const +{ + TQWizardPrivate::Page * p = d->page( page ); + return p ? p->appropriate : TRUE; +} + + +/*! + If \a appropriate is TRUE then page \a page is considered relevant + in the current context and should be displayed in the page + sequence; otherwise \a page should not be displayed in the page + sequence. + + \sa appropriate() +*/ +void TQWizard::setAppropriate( TQWidget * page, bool appropriate ) +{ + TQWizardPrivate::Page * p = d->page( page ); + if ( p ) + p->appropriate = appropriate; +} + + +void TQWizard::updateButtons() +{ + if ( !d->current ) + return; + + int i; + for( i = 0; i < (int)d->pages.count() && d->pages.at( i ) != d->current; i++ ); + bool notFirst( FALSE ); + if( i ) { + i--; + while( ( i >= 0 ) && !notFirst ) { + notFirst |= appropriate( d->pages.at( i )->w ); + i--; + } + } + setBackEnabled( d->current->backEnabled && notFirst ); + setNextEnabled( d->current->nextEnabled ); + d->finishButton->setEnabled( d->current->finishEnabled ); + d->helpButton->setEnabled( d->current->helpEnabled ); + + if ( ( d->current->finishEnabled && !d->finishButton->isVisible() ) || + ( d->current->backEnabled && !d->backButton->isVisible() ) || + ( d->current->nextEnabled && !d->nextButton->isVisible() ) || + ( d->current->helpEnabled && !d->helpButton->isVisible() ) ) + layOut(); +} + + +/*! + Returns a pointer to the current page in the sequence. Although + the wizard does its best to make sure that this value is never 0, + it can be if you try hard enough. +*/ + +TQWidget * TQWizard::currentPage() const +{ + return d->ws->visibleWidget(); +} + + +/*! + Returns the title of page \a page. +*/ + +TQString TQWizard::title( TQWidget * page ) const +{ + TQWizardPrivate::Page * p = d->page( page ); + return p ? p->t : TQString::null; +} + +/*! + Sets the title for page \a page to \a title. +*/ + +void TQWizard::setTitle( TQWidget *page, const TQString &title ) +{ + TQWizardPrivate::Page * p = d->page( page ); + if ( p ) + p->t = title; + if ( page == currentPage() ) + d->title->setText( title ); +} + +/*! + \property TQWizard::titleFont + \brief the font used for page titles + + The default is TQApplication::font(). +*/ +TQFont TQWizard::titleFont() const +{ + return d->title->font(); +} + +void TQWizard::setTitleFont( const TQFont & font ) +{ + d->title->setFont( font ); +} + + +/*! + Returns a pointer to the dialog's Back button + + By default, this button is connected to the back() slot, which is + virtual so you can reimplement it in a TQWizard subclass. Use + setBackEnabled() to enable/disable this button. +*/ +TQPushButton * TQWizard::backButton() const +{ + return d->backButton; +} + + +/*! + Returns a pointer to the dialog's Next button + + By default, this button is connected to the next() slot, which is + virtual so you can reimplement it in a TQWizard subclass. Use + setNextEnabled() to enable/disable this button. +*/ +TQPushButton * TQWizard::nextButton() const +{ + return d->nextButton; +} + + +/*! + Returns a pointer to the dialog's Finish button + + By default, this button is connected to the TQDialog::accept() + slot, which is virtual so you can reimplement it in a TQWizard + subclass. Use setFinishEnabled() to enable/disable this button. +*/ +TQPushButton * TQWizard::finishButton() const +{ + return d->finishButton; +} + + +/*! + Returns a pointer to the dialog's Cancel button + + By default, this button is connected to the TQDialog::reject() + slot, which is virtual so you can reimplement it in a TQWizard + subclass. +*/ +TQPushButton * TQWizard::cancelButton() const +{ + return d->cancelButton; +} + + +/*! + Returns a pointer to the dialog's Help button + + By default, this button is connected to the help() slot, which is + virtual so you can reimplement it in a TQWizard subclass. Use + setHelpEnabled() to enable/disable this button. +*/ +TQPushButton * TQWizard::helpButton() const +{ + return d->helpButton; +} + + +/*! + This virtual function is responsible for adding the buttons below + the bottom divider. + + \a layout is the horizontal layout of the entire wizard. +*/ + +void TQWizard::layOutButtonRow( TQHBoxLayout * layout ) +{ + bool hasHelp = FALSE; + bool hasEarlyFinish = FALSE; + + int i = d->pages.count() - 2; + while ( !hasEarlyFinish && i >= 0 ) { + if ( d->pages.at( i ) && d->pages.at( i )->finishEnabled ) + hasEarlyFinish = TRUE; + i--; + } + i = 0; + while ( !hasHelp && i < (int)d->pages.count() ) { + if ( d->pages.at( i ) && d->pages.at( i )->helpEnabled ) + hasHelp = TRUE; + i++; + } + + TQBoxLayout * h = new TQBoxLayout( TQBoxLayout::LeftToRight ); + layout->addLayout( h ); + + if ( hasHelp ) + h->addWidget( d->helpButton ); + else + d->helpButton->hide(); + + h->addStretch( 42 ); + + h->addWidget( d->backButton ); + + h->addSpacing( 6 ); + + if (d->current == d->pages.at( d->pages.count()-1 )) + hasEarlyFinish = FALSE; + + if ( hasEarlyFinish ) { + d->nextButton->show(); + d->finishButton->show(); + h->addWidget( d->nextButton ); + h->addSpacing( 12 ); + h->addWidget( d->finishButton ); + } else if ( d->pages.count() == 0 || + d->current->finishEnabled || + d->current == d->pages.at( d->pages.count()-1 ) ) { + d->nextButton->hide(); + d->finishButton->show(); + h->addWidget( d->finishButton ); + } else { + d->nextButton->show(); + d->finishButton->hide(); + h->addWidget( d->nextButton ); + } + + // if last page is disabled - show finished btn. at lastpage-1 + i = d->pages.count()-1; + if ( i >= 0 && !appropriate( d->pages.at( i )->w ) && + d->current == d->pages.at( d->pages.count()-2 ) ) { + d->nextButton->hide(); + d->finishButton->show(); + h->addWidget( d->finishButton ); + } + + h->addSpacing( 12 ); + h->addWidget( d->cancelButton ); +} + + +/*! + This virtual function is responsible for laying out the title row. + + \a layout is the horizontal layout for the wizard, and \a + title is the title for this page. This function is called every + time \a title changes. +*/ + +void TQWizard::layOutTitleRow( TQHBoxLayout * layout, const TQString & title ) +{ + d->title->setText( title ); + layout->addWidget( d->title, 10 ); +} + + +/* + +*/ + +void TQWizard::layOut() +{ + delete d->v; + d->v = new TQVBoxLayout( this, 6, 0, "top-level layout" ); + + TQHBoxLayout * l; + l = new TQHBoxLayout( 6 ); + d->v->addLayout( l, 0 ); + layOutTitleRow( l, d->current ? d->current->t : TQString::null ); + + if ( ! d->hbar1 ) { + d->hbar1 = new TQFrame( this, "<hr>", 0 ); + d->hbar1->setFrameStyle( TQFrame::Sunken + TQFrame::HLine ); + d->hbar1->setFixedHeight( 12 ); + } + + d->v->addWidget( d->hbar1 ); + + d->v->addWidget( d->ws, 10 ); + + if ( ! d->hbar2 ) { + d->hbar2 = new TQFrame( this, "<hr>", 0 ); + d->hbar2->setFrameStyle( TQFrame::Sunken + TQFrame::HLine ); + d->hbar2->setFixedHeight( 12 ); + } + d->v->addWidget( d->hbar2 ); + + l = new TQHBoxLayout( 6 ); + d->v->addLayout( l ); + layOutButtonRow( l ); + d->v->activate(); +} + + +/*! + \reimp +*/ + +bool TQWizard::eventFilter( TQObject * o, TQEvent * e ) +{ + if ( o == d->ws && e && e->type() == TQEvent::ChildRemoved ) { + TQChildEvent * c = (TQChildEvent*)e; + if ( c->child() && c->child()->isWidgetType() ) + removePage( (TQWidget *)c->child() ); + } + return TQDialog::eventFilter( o, e ); +} + + +/*! + Removes \a page from the page sequence but does not delete the + page. If \a page is currently being displayed, TQWizard will + display the page that precedes it, or the first page if this was + the first page. +*/ + +void TQWizard::removePage( TQWidget * page ) +{ + if ( !page ) + return; + + int i = d->pages.count(); + TQWidget* cp = currentPage(); + while( --i >= 0 && d->pages.at( i ) && d->pages.at( i )->w != page ) { } + if ( i < 0 ) + return; + TQWizardPrivate::Page * p = d->pages.at( i ); + d->pages.removeRef( p ); + d->ws->removeWidget( page ); + + if( cp == page ) { + i--; + if( i < 0 ) + i = 0; + if ( pageCount() > 0 ) + showPage( TQWizard::page( i ) ); + } +} + + +/*! + Returns a pointer to the page at position \a index in the + sequence, or 0 if \a index is out of range. The first page has + index 0. +*/ + +TQWidget* TQWizard::page( int index ) const +{ + if ( index >= pageCount() || index < 0 ) + return 0; + + return d->pages.at( index )->w; +} + +#endif // QT_NO_WIZARD diff --git a/src/dialogs/qwizard.h b/src/dialogs/qwizard.h new file mode 100644 index 000000000..d9dfad2c0 --- /dev/null +++ b/src/dialogs/qwizard.h @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Definition of the TQWizard class. +** +** Created : 990101 +** +** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the dialogs module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQWIZARDDIALOG_H +#define TQWIZARDDIALOG_H + + +#ifndef QT_H +#include "qdialog.h" +#endif // QT_H + +#ifndef QT_NO_WIZARD + +class TQHBoxLayout; +class TQWizardPrivate; + +class Q_EXPORT TQWizard : public TQDialog +{ + Q_OBJECT + Q_PROPERTY( TQFont titleFont READ titleFont WRITE setTitleFont ) + +public: + TQWizard( TQWidget* parent=0, const char* name=0, bool modal=FALSE, + WFlags f=0 ); + ~TQWizard(); + + void show(); + + void setFont( const TQFont & font ); + + virtual void addPage( TQWidget *, const TQString & ); + virtual void insertPage( TQWidget*, const TQString&, int ); + virtual void removePage( TQWidget * ); + + TQString title( TQWidget * ) const; + void setTitle( TQWidget *, const TQString & ); + TQFont titleFont() const; + void setTitleFont( const TQFont & ); + + virtual void showPage( TQWidget * ); + + TQWidget * currentPage() const; + + TQWidget* page( int ) const; + int pageCount() const; + int indexOf( TQWidget* ) const; + + virtual bool appropriate( TQWidget * ) const; + virtual void setAppropriate( TQWidget *, bool ); + + TQPushButton * backButton() const; + TQPushButton * nextButton() const; + TQPushButton * finishButton() const; + TQPushButton * cancelButton() const; + TQPushButton * helpButton() const; + + bool eventFilter( TQObject *, TQEvent * ); + +public slots: + virtual void setBackEnabled( TQWidget *, bool ); + virtual void setNextEnabled( TQWidget *, bool ); + virtual void setFinishEnabled( TQWidget *, bool ); + + virtual void setHelpEnabled( TQWidget *, bool ); + + // obsolete + virtual void setFinish( TQWidget *, bool ) {} + +protected slots: + virtual void back(); + virtual void next(); + virtual void help(); + +signals: + void helpClicked(); + void selected( const TQString& ); + +protected: + virtual void layOutButtonRow( TQHBoxLayout * ); + virtual void layOutTitleRow( TQHBoxLayout *, const TQString & ); + +private: + void setBackEnabled( bool ); + void setNextEnabled( bool ); + + void setHelpEnabled( bool ); + + void setNextPage( TQWidget * ); + + void updateButtons(); + + void layOut(); + + TQWizardPrivate *d; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + TQWizard( const TQWizard & ); + TQWizard& operator=( const TQWizard & ); +#endif +}; + +#endif // QT_NO_WIZARD + +#endif // TQWIZARD_H |